aboutsummaryrefslogtreecommitdiffstats
path: root/public/system/storage
diff options
context:
space:
mode:
Diffstat (limited to 'public/system/storage')
-rw-r--r--public/system/storage/cache/index.html0
-rw-r--r--public/system/storage/download/index.html0
-rw-r--r--public/system/storage/logs/index.html0
-rw-r--r--public/system/storage/modification/index.html10
-rw-r--r--public/system/storage/session/index.html0
-rw-r--r--public/system/storage/upload/index.html0
-rw-r--r--public/system/storage/vendor/autoload.php7
-rw-r--r--public/system/storage/vendor/bin/pscss10
-rw-r--r--public/system/storage/vendor/bin/pscss.bat4
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/.gitignore6
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/CHANGELOG.md362
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/LICENSE22
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/README.md79
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/Rakefile67
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/ci.sh11
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/composer.json28
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree.php152
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOn.php27
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOnGateway.php51
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Address.php148
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddressGateway.php305
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AndroidPayCard.php85
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ApplePayCard.php95
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Base.php70
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientToken.php47
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientTokenGateway.php122
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CoinbaseAccount.php108
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Collection.php153
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Configuration.php397
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CredentialsParser.php145
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCard.php311
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardGateway.php472
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerification.php22
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationGateway.php49
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationSearch.php53
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Customer.php373
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerGateway.php619
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerSearch.php31
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Descriptor.php4
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Digest.php59
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Disbursement.php49
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DisbursementDetails.php25
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Discount.php18
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DiscountGateway.php28
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute.php75
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute/TransactionDetails.php22
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/EqualityNode.php10
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Codes.php492
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ErrorCollection.php109
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Validation.php56
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ValidationErrorCollection.php127
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception.php11
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authentication.php13
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authorization.php15
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Configuration.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/DownForMaintenance.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ForgedQueryString.php16
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidChallenge.php5
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidSignature.php5
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/NotFound.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCaFileNotFound.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCertificate.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ServerError.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Unexpected.php13
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/UpgradeRequired.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ValidationsFailed.php12
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Gateway.php186
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Http.php145
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Instance.php72
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/IsNode.php21
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/KeyValueNode.php22
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Merchant.php26
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount.php62
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/AddressDetails.php5
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/BusinessDetails.php19
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/FundingDetails.php6
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/IndividualDetails.php19
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccountGateway.php152
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantGateway.php40
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Modification.php19
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueNode.php37
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueOrTextNode.php45
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthCredentials.php33
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthGateway.php102
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartialMatchNode.php16
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartnerMerchant.php40
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccount.php107
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccountGateway.php175
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentInstrumentType.php11
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethod.php44
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodGateway.php250
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonce.php52
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonceGateway.php64
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Plan.php48
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PlanGateway.php31
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RangeNode.php38
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ResourceCollection.php141
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/CreditCardVerification.php94
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Error.php109
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Successful.php86
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RiskData.php27
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummary.php42
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummaryGateway.php104
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SignatureService.php22
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription.php138
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription/StatusDetails.php19
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionGateway.php210
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionSearch.php64
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/CreditCardNumbers.php69
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/MerchantAccount.php19
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/Nonces.php33
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/TransactionAmounts.php17
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/VenmoSdk.php28
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TextNode.php10
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ThreeDSecureInfo.php27
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction.php517
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AddressDetails.php24
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AndroidPayCardDetails.php44
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/ApplePayCardDetails.php36
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CoinbaseDetails.php36
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CreditCardDetails.php35
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CustomerDetails.php22
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/PayPalDetails.php36
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/StatusDetails.php18
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/SubscriptionDetails.php15
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionGateway.php445
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionSearch.php129
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirect.php100
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirectGateway.php283
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/UnknownPaymentMethod.php68
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Util.php383
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Version.php33
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookNotification.php126
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookTesting.php283
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml.php38
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Generator.php143
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Parser.php133
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/lib/ssl/api_braintreegateway_com.ca.crt351
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/phpunit.xml.dist23
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardDefaults.php7
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardNumbers/CardTypeIndicators.php13
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/Braintree/OAuthTestHelper.php32
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/Braintree/fixtures/composer_implementation.php5
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/SanityTest.php20
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/TestHelper.php161
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/AddOnsTest.php83
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/AddressTest.php298
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/ClientTokenTest.php183
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardTest.php1289
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardVerificationAdvancedSearchTest.php253
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerAdvancedSearchTest.php195
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerTest.php1190
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/DisbursementTest.php33
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/DiscountTest.php83
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ErrorCollectionTest.php75
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ValidationErrorCollectionTest.php71
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpClientApi.php84
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpTest.php62
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantAccountTest.php419
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantTest.php56
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/MultipleValueNodeTest.php89
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/OAuthTest.php278
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/PayPalAccountTest.php294
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodNonceTest.php66
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodTest.php1154
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/PlanTest.php126
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/Result/ErrorTest.php28
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/SettlementBatchSummaryTest.php88
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionSearchTest.php337
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTest.php1197
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTestHelper.php84
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/TextNodeTest.php142
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionAdvancedSearchTest.php1526
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionTest.php2833
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/integration/TransparentRedirectTest.php348
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/AddOnTest.php29
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/AddressTest.php74
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/BraintreeTest.php20
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/ClientApi/ClientTokenTest.php17
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/ConfigurationTest.php392
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/CreditCardTest.php135
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/CustomerTest.php54
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/DigestTest.php93
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementDetailsTest.php23
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementTest.php29
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/DiscountTest.php29
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/GatewayTest.php46
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/InstanceTest.php32
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/MerchantAccountTest.php63
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueNodeTest.php19
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueOrTextNodeTest.php47
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/OAuthTest.php66
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/PayPalAccountTest.php39
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/PaymentMethodTest.php54
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/RangeNodeTest.php33
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/ResourceCollectionTest.php83
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/ErrorTest.php11
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/SuccessfulTest.php16
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/SanityTest.php15
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionSearchTest.php59
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionTest.php17
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/TextNodeTest.php40
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/TransactionTest.php45
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/TransparentRedirectTest.php26
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/UnknownPaymentMethodTest.php20
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/UtilTest.php235
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/WebhookNotificationTest.php408
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_GeneratorTest.php105
-rw-r--r--public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_ParserTest.php536
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/.gitignore8
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/.travis.yml13
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/LICENSE21
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/README.md69
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/composer.json30
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/docs/README.md399
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/phpspec.yml.dist4
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/phpunit.xml.dist35
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/ClientSpec.php204
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/DeclinedSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ForbiddenSpec.php19
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InternalServerErrorSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InvalidAttributeValueSpec.php43
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/MethodNotAllowedSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotAcceptableSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotFoundSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestSpec.php90
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestTimeoutSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ServiceUnavailableSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnauthorizedSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedErrorSpec.php14
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedResponseSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ValidationFailedSpec.php28
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ClientAdapterSpec.php97
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ExceptionMapperSpec.php117
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ErrorSpec.php19
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/AuthorizationInformationSpec.php14
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/CreateSpec.php72
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/FinalizeSpec.php62
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetAllSpec.php56
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetSpec.php56
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentCardSpec.php14
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentRecurringSpec.php14
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentSpec.php71
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/CreateSpec.php72
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetAllSpec.php58
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetSpec.php64
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/RefundSpec.php19
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ResultObjectMapperSpec.php138
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/CreateSpec.php72
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetAllSpec.php58
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetSpec.php64
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/SettlementSpec.php19
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ValidatorSpec.php76
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/CreateSpec.php68
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetAllSpec.php58
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetSpec.php64
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/VoidSpec.php19
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Client.php185
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Declined.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Forbidden.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InternalServerError.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InvalidAttributeValue.php24
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/MethodNotAllowed.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotAcceptable.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotFound.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Request.php63
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/RequestTimeout.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ResultObjectPropertyNotFound.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Runtime.php8
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ServiceUnavailable.php10
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Unauthorized.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedError.php7
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedResponse.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ValidationFailed.php10
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/ClientInterface.php17
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ClientAdapter.php60
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ExceptionMapper.php94
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Error.php116
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodInterface.php53
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodResultCollectionInterface.php11
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/AuthorizationInformation.php56
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Create.php141
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Finalize.php60
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Get.php46
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/GetAll.php54
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Payment.php403
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentCard.php121
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentInterface.php8
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentRecurring.php31
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Create.php64
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Get.php57
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/GetAll.php50
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Refund.php268
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObject.php139
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectInterface.php15
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapper.php115
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapperInterface.php9
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Create.php63
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Get.php57
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/GetAll.php50
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Settlement.php268
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Validator.php41
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ValidatorInterface.php17
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Create.php56
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Get.php57
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/GetAll.php50
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Void.php221
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ClientTestCase.php56
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ErrorTest.php98
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/PaymentTest.php267
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/RefundTest.php115
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/SettlementTest.php111
-rw-r--r--public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/VoidTest.php105
-rw-r--r--public/system/storage/vendor/composer/ClassLoader.php445
-rw-r--r--public/system/storage/vendor/composer/LICENSE21
-rw-r--r--public/system/storage/vendor/composer/autoload_classmap.php15
-rw-r--r--public/system/storage/vendor/composer/autoload_files.php12
-rw-r--r--public/system/storage/vendor/composer/autoload_namespaces.php11
-rw-r--r--public/system/storage/vendor/composer/autoload_psr4.php23
-rw-r--r--public/system/storage/vendor/composer/autoload_real.php70
-rw-r--r--public/system/storage/vendor/composer/autoload_static.php145
-rw-r--r--public/system/storage/vendor/composer/installed.json899
-rw-r--r--public/system/storage/vendor/divido/divido-php/.gitignore1
-rw-r--r--public/system/storage/vendor/divido/divido-php/Example.php138
-rw-r--r--public/system/storage/vendor/divido/divido-php/README.md1771
-rw-r--r--public/system/storage/vendor/divido/divido-php/composer.json30
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido.php45
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Activation.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/ApiConnectionError.php5
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/ApiError.php5
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/ApiRequestor.php475
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/ApiResource.php218
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/AttachedObject.php23
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/AuthenticationError.php5
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Cancellation.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Comments.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/CreditRequest.php62
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/DealCalculator.php49
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Divido.php185
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Error.php29
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Finances.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Fulfillment.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/InvalidRequestError.php12
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/List.php54
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Object.php265
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/PaymentError.php13
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/RateLimitError.php11
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Refund.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/SendApplication.php50
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/SingletonApiResource.php31
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Util.php89
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/Divido/Util/Set.php39
-rw-r--r--public/system/storage/vendor/divido/divido-php/lib/data/ca-certificates.crt5165
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/.travis.yml52
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/CHANGELOG.md1071
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/LICENSE19
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/README.md70
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/UPGRADING.md1050
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/composer.json38
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/BatchResults.php148
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Client.php362
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/ClientInterface.php150
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Collection.php236
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php248
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php75
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php86
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php66
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php373
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php20
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php61
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php40
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php63
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php26
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php14
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/Emitter.php145
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php96
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EndEvent.php28
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php27
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EventInterface.php23
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php15
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php20
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php88
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php51
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php56
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php34
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php7
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php7
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ParseException.php31
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php121
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php7
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/StateException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php34
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/HasDataTrait.php75
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php253
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AppliesHeadersInterface.php24
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php158
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php364
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php71
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php136
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageParser.php171
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Request.php195
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php136
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Response.php208
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php111
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Mimetypes.php963
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Pool.php333
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php109
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBody.php287
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php109
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFile.php135
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php41
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Query.php204
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/QueryParser.php163
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/RequestFsm.php153
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/RingBridge.php165
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php58
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/History.php172
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php36
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php147
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php130
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php176
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/ToArrayInterface.php15
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Transaction.php103
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/UriTemplate.php241
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Url.php595
-rw-r--r--public/system/storage/vendor/guzzlehttp/guzzle/src/Utils.php215
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/.gitignore6
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/.travis.yml13
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/LICENSE19
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/README.rst151
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/composer.json30
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/phpunit.xml.dist14
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/src/Formatter.php179
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/src/LogSubscriber.php89
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/src/SimpleLogger.php32
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/tests/FormatterTest.php90
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/tests/LogSubscriberTest.php76
-rw-r--r--public/system/storage/vendor/guzzlehttp/log-subscriber/tests/SimpleLoggerTest.php41
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/.gitignore6
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/.travis.yml13
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/LICENSE19
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/README.rst68
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/composer.json29
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/phpunit.xml.dist21
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/src/Oauth1.php308
-rw-r--r--public/system/storage/vendor/guzzlehttp/oauth-subscriber/tests/Oauth1Test.php282
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/.editorconfig12
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/.gitignore4
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/.travis.yml43
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/CHANGELOG.md118
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/LICENSE19
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/Makefile46
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/README.rst46
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/composer.json43
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/Makefile153
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/client_handlers.rst173
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/client_middleware.rst165
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/conf.py23
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/futures.rst164
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/index.rst50
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/requirements.txt1
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/spec.rst311
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/docs/testing.rst74
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/phpunit.xml.dist14
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php74
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php560
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php135
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php248
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/Middleware.php58
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php52
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php414
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Core.php364
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php7
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php7
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/RingException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php125
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php43
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php57
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php40
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php11
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php40
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php12
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php32
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php821
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php96
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php181
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php65
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php86
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/Server.php183
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php480
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/server.js241
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/CoreTest.php336
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php21
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php46
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php56
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php109
-rw-r--r--public/system/storage/vendor/guzzlehttp/ringphp/tests/bootstrap.php11
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/.gitignore6
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/.travis.yml17
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/CHANGELOG.rst94
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/LICENSE19
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/Makefile19
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/README.rst36
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/composer.json28
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/phpunit.xml.dist17
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/AppendStream.php220
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/AsyncReadStream.php207
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/BufferStream.php138
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/CachingStream.php122
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/DroppingStream.php42
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php4
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/Exception/SeekException.php27
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/FnStream.php147
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php117
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/InflateStream.php27
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/LazyOpenStream.php37
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/LimitStream.php161
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php11
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/NoSeekStream.php25
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/NullStream.php78
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/PumpStream.php161
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/Stream.php261
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php143
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/StreamInterface.php159
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/src/Utils.php196
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/AppendStreamTest.php178
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php186
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/BufferStreamTest.php69
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/CachingStreamTest.php136
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php26
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php16
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/FnStreamTest.php89
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php99
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/InflateStreamTest.php16
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php64
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/LimitStreamTest.php133
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php41
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/NullStreamTest.php39
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/PumpStreamTest.php77
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php147
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/StreamTest.php252
-rw-r--r--public/system/storage/vendor/guzzlehttp/streams/tests/UtilsTest.php155
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/.coveralls.yml3
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/.gitignore3
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/.travis.yml29
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/CHANGELOG.md17
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/README.md67
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/composer.json46
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/composer.lock3569
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/add_shipping_info.php34
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/trigger_send_out.php22
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/update_customer_details.php27
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout.php60
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout_attachment.php79
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/fetch_checkout.php19
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/update_checkout.php56
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/acknowledge_order.php22
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/cancel_order.php21
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/create_capture.php49
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/extend_authorization_time.php19
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_capture.php21
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_order.php19
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/refund_order.php37
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/release_remaining_authorization.php21
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_customer_details.php30
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_merchant_references.php25
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_order_lines.php37
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/README.md14
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/coffeelint103
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/message-format34
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/ticket-number30
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/jshint69
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-coffee59
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-js59
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-php65
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-python48
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/phpmd.xml32
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/phpunit.xml.dist40
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Checkout/Order.php112
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Capture.php149
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Order.php317
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Resource.php200
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Connector.php186
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ConnectorInterface.php94
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Exception/ConnectorException.php110
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ResponseValidator.php137
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgent.php130
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgentInterface.php117
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Component/Checkout/OrderTest.php135
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/CaptureTest.php168
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/OrderTest.php451
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Component/ResourceTestCase.php45
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Component/TestCase.php80
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Component/Transport/ConnectorTest.php144
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/Checkout/OrderTest.php418
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/CaptureTest.php512
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/OrderTest.php921
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/TestCase.php57
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ConnectorTest.php343
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/Exception/ConnectorExceptionTest.php80
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ResponseValidatorTest.php249
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/UserAgentTest.php125
-rw-r--r--public/system/storage/vendor/klarna/kco_rest/tests/bootstrap.php23
-rw-r--r--public/system/storage/vendor/leafo/scssphp/.gitignore5
-rw-r--r--public/system/storage/vendor/leafo/scssphp/.travis.yml7
-rw-r--r--public/system/storage/vendor/leafo/scssphp/LICENSE.md660
-rw-r--r--public/system/storage/vendor/leafo/scssphp/Makefile3
-rw-r--r--public/system/storage/vendor/leafo/scssphp/README.md34
-rw-r--r--public/system/storage/vendor/leafo/scssphp/composer.json28
-rw-r--r--public/system/storage/vendor/leafo/scssphp/package.sh24
-rw-r--r--public/system/storage/vendor/leafo/scssphp/phpunit.xml.dist28
-rw-r--r--public/system/storage/vendor/leafo/scssphp/pscss53
-rw-r--r--public/system/storage/vendor/leafo/scssphp/scss.inc.php4574
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/.gitignore2
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/composer.html6
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/docs/index.md306
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/index.md210
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/site.moon15
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/style.scss303
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/templates/index.html81
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/www/.gitignore2
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/www/img/tile.pngbin0 -> 244 bytes
-rw-r--r--public/system/storage/vendor/leafo/scssphp/site/www/style/normalize.css500
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/ApiTest.php80
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/ExceptionTest.php86
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/InputTest.php83
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/compare-scss.sh25
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/builtins.scss171
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/comments.scss28
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/compass_extract.scss248
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/content.scss61
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/content_with_function.scss17
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/default_args.scss15
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/directives.scss108
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/extends.scss184
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/filter_effects.scss48
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/functions.scss81
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/ie7.scss12
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/if.scss76
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/if_on_null.scss8
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/import.scss23
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/_partial.scss10
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/simple.scss4
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/interpolation.scss86
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/keyword_args.scss24
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/list.scss15
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/looping.scss51
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/media.scss208
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/mixins.scss158
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/nesting.scss45
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/null.scss41
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/operators.scss143
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/placeholder_selector.scss18
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/scss_css.scss986
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/selectors.scss187
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/values.scss43
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/inputs/variables.scss56
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/builtins.css126
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/comments.css19
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/compass_extract.css28
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/content.css29
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/content_with_function.css2
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/default_args.css3
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/directives.css77
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/extends.css87
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/filter_effects.css20
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/functions.css22
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/ie7.css8
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/if.css21
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/if_on_null.css2
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/import.css27
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/interpolation.css54
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/keyword_args.css6
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/list.css7
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/looping.css45
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/media.css103
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/mixins.css83
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/nesting.css22
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/null.css21
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/operators.css105
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/placeholder_selector.css7
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/scss_css.css741
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/selectors.css335
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/values.css34
-rw-r--r--public/system/storage/vendor/leafo/scssphp/tests/outputs/variables.css24
-rw-r--r--public/system/storage/vendor/leafo/scssphp/todo47
-rw-r--r--public/system/storage/vendor/psr/log/.gitignore1
-rw-r--r--public/system/storage/vendor/psr/log/LICENSE19
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/AbstractLogger.php128
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/InvalidArgumentException.php7
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/LogLevel.php18
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareInterface.php18
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareTrait.php26
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/LoggerInterface.php123
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/LoggerTrait.php140
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/NullLogger.php28
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php144
-rw-r--r--public/system/storage/vendor/psr/log/Psr/Log/Test/TestLogger.php146
-rw-r--r--public/system/storage/vendor/psr/log/README.md52
-rw-r--r--public/system/storage/vendor/psr/log/composer.json26
-rw-r--r--public/system/storage/vendor/react/promise/.gitignore5
-rw-r--r--public/system/storage/vendor/react/promise/.travis.yml28
-rw-r--r--public/system/storage/vendor/react/promise/CHANGELOG.md135
-rw-r--r--public/system/storage/vendor/react/promise/LICENSE22
-rw-r--r--public/system/storage/vendor/react/promise/README.md870
-rw-r--r--public/system/storage/vendor/react/promise/composer.json29
-rw-r--r--public/system/storage/vendor/react/promise/phpunit.xml.dist28
-rw-r--r--public/system/storage/vendor/react/promise/src/CancellablePromiseInterface.php11
-rw-r--r--public/system/storage/vendor/react/promise/src/CancellationQueue.php55
-rw-r--r--public/system/storage/vendor/react/promise/src/Deferred.php65
-rw-r--r--public/system/storage/vendor/react/promise/src/Exception/LengthException.php7
-rw-r--r--public/system/storage/vendor/react/promise/src/ExtendedPromiseInterface.php30
-rw-r--r--public/system/storage/vendor/react/promise/src/FulfilledPromise.php68
-rw-r--r--public/system/storage/vendor/react/promise/src/LazyPromise.php63
-rw-r--r--public/system/storage/vendor/react/promise/src/Promise.php256
-rw-r--r--public/system/storage/vendor/react/promise/src/PromiseInterface.php14
-rw-r--r--public/system/storage/vendor/react/promise/src/PromisorInterface.php11
-rw-r--r--public/system/storage/vendor/react/promise/src/RejectedPromise.php76
-rw-r--r--public/system/storage/vendor/react/promise/src/UnhandledRejectionException.php31
-rw-r--r--public/system/storage/vendor/react/promise/src/functions.php246
-rw-r--r--public/system/storage/vendor/react/promise/src/functions_include.php5
-rw-r--r--public/system/storage/vendor/react/promise/tests/CancellationQueueTest.php100
-rw-r--r--public/system/storage/vendor/react/promise/tests/DeferredTest.php112
-rw-r--r--public/system/storage/vendor/react/promise/tests/FulfilledPromiseTest.php76
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionAllTest.php114
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionAnyTest.php204
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionCheckTypehintTest.php118
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionMapTest.php198
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionRaceTest.php211
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionReduceTest.php347
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionRejectTest.php64
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionResolveTest.php171
-rw-r--r--public/system/storage/vendor/react/promise/tests/FunctionSomeTest.php258
-rw-r--r--public/system/storage/vendor/react/promise/tests/LazyPromiseTest.php107
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseAdapter/CallbackPromiseAdapter.php40
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseAdapter/PromiseAdapterInterface.php14
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest.php293
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/CancelTestTrait.php246
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/FullTestTrait.php15
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/NotifyTestTrait.php336
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseFulfilledTestTrait.php351
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/PromisePendingTestTrait.php68
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseRejectedTestTrait.php512
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseSettledTestTrait.php86
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/RejectTestTrait.php368
-rw-r--r--public/system/storage/vendor/react/promise/tests/PromiseTest/ResolveTestTrait.php312
-rw-r--r--public/system/storage/vendor/react/promise/tests/RejectedPromiseTest.php76
-rw-r--r--public/system/storage/vendor/react/promise/tests/Stub/CallableStub.php10
-rw-r--r--public/system/storage/vendor/react/promise/tests/TestCase.php43
-rw-r--r--public/system/storage/vendor/react/promise/tests/bootstrap.php7
-rw-r--r--public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestPromise.php21
-rw-r--r--public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestThenable.php21
-rw-r--r--public/system/storage/vendor/react/promise/tests/fixtures/SimpleRejectedTestPromise.php21
-rw-r--r--public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellable.php13
-rw-r--r--public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellableThenable.php18
-rw-r--r--public/system/storage/vendor/scss.inc.php4574
-rw-r--r--public/system/storage/vendor/symfony/polyfill-ctype/Ctype.php227
-rw-r--r--public/system/storage/vendor/symfony/polyfill-ctype/LICENSE19
-rw-r--r--public/system/storage/vendor/symfony/polyfill-ctype/README.md12
-rw-r--r--public/system/storage/vendor/symfony/polyfill-ctype/bootstrap.php26
-rw-r--r--public/system/storage/vendor/symfony/polyfill-ctype/composer.json34
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/LICENSE19
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/Mbstring.php800
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/README.md13
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php1096
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php5
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php1104
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/bootstrap.php58
-rw-r--r--public/system/storage/vendor/symfony/polyfill-mbstring/composer.json34
-rw-r--r--public/system/storage/vendor/symfony/translation/.gitignore3
-rw-r--r--public/system/storage/vendor/symfony/translation/CHANGELOG.md69
-rw-r--r--public/system/storage/vendor/symfony/translation/Catalogue/AbstractOperation.php171
-rw-r--r--public/system/storage/vendor/symfony/translation/Catalogue/MergeOperation.php55
-rw-r--r--public/system/storage/vendor/symfony/translation/Catalogue/OperationInterface.php77
-rw-r--r--public/system/storage/vendor/symfony/translation/Catalogue/TargetOperation.php69
-rw-r--r--public/system/storage/vendor/symfony/translation/DataCollector/TranslationDataCollector.php150
-rw-r--r--public/system/storage/vendor/symfony/translation/DataCollectorTranslator.php152
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/CsvFileDumper.php63
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/DumperInterface.php31
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/FileDumper.php123
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/IcuResFileDumper.php106
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/IniFileDumper.php45
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/JsonFileDumper.php44
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/MoFileDumper.php82
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/PhpFileDumper.php38
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/PoFileDumper.php61
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/QtFileDumper.php50
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/XliffFileDumper.php183
-rw-r--r--public/system/storage/vendor/symfony/translation/Dumper/YamlFileDumper.php54
-rw-r--r--public/system/storage/vendor/symfony/translation/Exception/ExceptionInterface.php21
-rw-r--r--public/system/storage/vendor/symfony/translation/Exception/InvalidResourceException.php21
-rw-r--r--public/system/storage/vendor/symfony/translation/Exception/NotFoundResourceException.php21
-rw-r--r--public/system/storage/vendor/symfony/translation/Extractor/AbstractFileExtractor.php83
-rw-r--r--public/system/storage/vendor/symfony/translation/Extractor/ChainExtractor.php60
-rw-r--r--public/system/storage/vendor/symfony/translation/Extractor/ExtractorInterface.php38
-rw-r--r--public/system/storage/vendor/symfony/translation/IdentityTranslator.php65
-rw-r--r--public/system/storage/vendor/symfony/translation/Interval.php107
-rw-r--r--public/system/storage/vendor/symfony/translation/LICENSE19
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/ArrayLoader.php66
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/CsvFileLoader.php65
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/FileLoader.php65
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/IcuDatFileLoader.php62
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/IcuResFileLoader.php92
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/IniFileLoader.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/JsonFileLoader.php64
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/LoaderInterface.php38
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/MoFileLoader.php154
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/PhpFileLoader.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/PoFileLoader.php151
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/QtFileLoader.php77
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/XliffFileLoader.php321
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/YamlFileLoader.php48
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd2223
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-2.0.xsd411
-rw-r--r--public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xml.xsd309
-rw-r--r--public/system/storage/vendor/symfony/translation/LoggingTranslator.php124
-rw-r--r--public/system/storage/vendor/symfony/translation/MessageCatalogue.php270
-rw-r--r--public/system/storage/vendor/symfony/translation/MessageCatalogueInterface.php142
-rw-r--r--public/system/storage/vendor/symfony/translation/MessageSelector.php86
-rw-r--r--public/system/storage/vendor/symfony/translation/MetadataAwareInterface.php54
-rw-r--r--public/system/storage/vendor/symfony/translation/PluralizationRules.php209
-rw-r--r--public/system/storage/vendor/symfony/translation/README.md13
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php73
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php83
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php82
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php148
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php93
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php29
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php83
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php38
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php28
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php89
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php46
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/IdentityTranslatorTest.php95
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/IntervalTest.php48
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php60
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php64
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php51
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php50
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php61
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php22
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php71
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php49
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php108
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php67
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php183
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php70
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/LoggingTranslatorTest.php49
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/MessageCatalogueTest.php214
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/MessageSelectorTest.php130
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/PluralizationRulesTest.php123
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/TranslatorCacheTest.php299
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/TranslatorTest.php533
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php73
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php65
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.mobin0 -> 49 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.po3
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.csv0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.ini0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.json0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.mo0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.po0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.xlf0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.yml0
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/encoding.xlf16
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po10
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id.po8
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po10
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf23
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/malformed.json3
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/messages.yml3
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/messages_linear.yml2
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.xlf11
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.yml1
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.mobin0 -> 74 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.po5
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resname.xlf19
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat1
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.resbin0 -> 120 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt3
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.resbin0 -> 124 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt3
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt2
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.datbin0 -> 352 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.resbin0 -> 84 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf23
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf25
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf25
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf14
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf14
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.csv4
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.dump.json1
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ini1
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.json3
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.mobin0 -> 52 bytes
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.php5
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.po8
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ts10
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.xlf23
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.yml1
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/valid.csv4
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf21
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf12
-rw-r--r--public/system/storage/vendor/symfony/translation/Tests/fixtures/withnote.xlf22
-rw-r--r--public/system/storage/vendor/symfony/translation/Translator.php441
-rw-r--r--public/system/storage/vendor/symfony/translation/TranslatorBagInterface.php31
-rw-r--r--public/system/storage/vendor/symfony/translation/TranslatorInterface.php65
-rw-r--r--public/system/storage/vendor/symfony/translation/Util/ArrayConverter.php99
-rw-r--r--public/system/storage/vendor/symfony/translation/Writer/TranslationWriter.php89
-rw-r--r--public/system/storage/vendor/symfony/translation/composer.json48
-rw-r--r--public/system/storage/vendor/symfony/translation/phpunit.xml.dist28
-rw-r--r--public/system/storage/vendor/symfony/validator/.gitignore3
-rw-r--r--public/system/storage/vendor/symfony/validator/CHANGELOG.md175
-rw-r--r--public/system/storage/vendor/symfony/validator/ClassBasedInterface.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraint.php298
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintValidator.php214
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintValidatorFactory.php51
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintValidatorFactoryInterface.php27
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintValidatorInterface.php33
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintViolation.php204
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintViolationInterface.php123
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintViolationList.php161
-rw-r--r--public/system/storage/vendor/symfony/validator/ConstraintViolationListInterface.php65
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/AbstractComparison.php51
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/AbstractComparisonValidator.php94
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/All.php38
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/AllValidator.php56
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Bic.php39
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/BicValidator.php90
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Blank.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/BlankValidator.php47
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Callback.php77
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CallbackValidator.php74
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CardScheme.php47
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CardSchemeValidator.php143
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Choice.php52
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/ChoiceValidator.php133
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Collection.php85
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Collection/Optional.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Collection/Required.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CollectionValidator.php110
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Composite.php149
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Count.php54
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CountValidator.php85
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Country.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CountryValidator.php61
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Currency.php32
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/CurrencyValidator.php62
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Date.php33
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/DateTime.php35
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/DateTimeValidator.php88
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/DateValidator.php91
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Email.php38
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/EmailValidator.php155
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/EqualTo.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/EqualToValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Existence.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Expression.php65
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/ExpressionValidator.php110
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/False.php26
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/FalseValidator.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/File.php123
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/FileValidator.php329
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/GreaterThan.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqual.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqualValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/GreaterThanValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/GroupSequence.php208
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/GroupSequenceProvider.php24
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Iban.php47
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IbanValidator.php293
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IdenticalTo.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IdenticalToValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Image.php77
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/ImageValidator.php261
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Ip.php86
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IpValidator.php110
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsFalse.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsFalseValidator.php49
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsNull.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsNullValidator.php47
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsTrue.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsTrueValidator.php51
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Isbn.php67
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IsbnValidator.php216
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Issn.php44
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/IssnValidator.php183
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Language.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LanguageValidator.php61
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Length.php58
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LengthValidator.php109
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LessThan.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqual.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqualValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LessThanValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Locale.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LocaleValidator.php62
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Luhn.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/LuhnValidator.php111
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotBlank.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotBlankValidator.php47
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotEqualTo.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotEqualToValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalTo.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalToValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotNull.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NotNullValidator.php47
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Null.php26
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/NullValidator.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Optional.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Range.php67
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/RangeValidator.php104
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Regex.php102
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/RegexValidator.php60
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Required.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Time.php33
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/TimeValidator.php91
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Traverse.php50
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/True.php26
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/TrueValidator.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Type.php48
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/TypeValidator.php64
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Url.php34
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/UrlValidator.php100
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Uuid.php77
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/UuidValidator.php350
-rw-r--r--public/system/storage/vendor/symfony/validator/Constraints/Valid.php44
-rw-r--r--public/system/storage/vendor/symfony/validator/Context/ExecutionContext.php467
-rw-r--r--public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactory.php56
-rw-r--r--public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactoryInterface.php36
-rw-r--r--public/system/storage/vendor/symfony/validator/Context/ExecutionContextInterface.php225
-rw-r--r--public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContext.php46
-rw-r--r--public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContextFactory.php64
-rw-r--r--public/system/storage/vendor/symfony/validator/DefaultTranslator.php171
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/BadMethodCallException.php21
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/ConstraintDefinitionException.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/ExceptionInterface.php21
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/GroupDefinitionException.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/InvalidArgumentException.php21
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/InvalidOptionsException.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/MappingException.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/MissingOptionsException.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/NoSuchMetadataException.php19
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/OutOfBoundsException.php21
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/RuntimeException.php21
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/UnexpectedTypeException.php20
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/UnsupportedMetadataException.php19
-rw-r--r--public/system/storage/vendor/symfony/validator/Exception/ValidatorException.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/ExecutionContext.php269
-rw-r--r--public/system/storage/vendor/symfony/validator/ExecutionContextInterface.php299
-rw-r--r--public/system/storage/vendor/symfony/validator/GlobalExecutionContextInterface.php71
-rw-r--r--public/system/storage/vendor/symfony/validator/GroupSequenceProviderInterface.php28
-rw-r--r--public/system/storage/vendor/symfony/validator/LICENSE19
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/BlackholeMetadataFactory.php28
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Cache/ApcCache.php57
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Cache/CacheInterface.php43
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Cache/DoctrineCache.php59
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/CascadingStrategy.php52
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/ClassMetadata.php591
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataFactory.php28
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataInterface.php79
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/ElementMetadata.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Factory/BlackHoleMetadataFactory.php40
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php167
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Factory/MetadataFactoryInterface.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/GenericMetadata.php237
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/GetterMetadata.php80
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/AbstractLoader.php88
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/AnnotationLoader.php92
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/FileLoader.php51
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/FilesLoader.php61
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderChain.php59
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderInterface.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/StaticMethodLoader.php66
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFileLoader.php213
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFilesLoader.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFileLoader.php178
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFilesLoader.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd160
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/MemberMetadata.php248
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/MetadataInterface.php58
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadata.php74
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadataInterface.php35
-rw-r--r--public/system/storage/vendor/symfony/validator/Mapping/TraversalStrategy.php65
-rw-r--r--public/system/storage/vendor/symfony/validator/MetadataFactoryInterface.php43
-rw-r--r--public/system/storage/vendor/symfony/validator/MetadataInterface.php73
-rw-r--r--public/system/storage/vendor/symfony/validator/ObjectInitializerInterface.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/PropertyMetadataContainerInterface.php45
-rw-r--r--public/system/storage/vendor/symfony/validator/PropertyMetadataInterface.php46
-rw-r--r--public/system/storage/vendor/symfony/validator/README.md16
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.af.xlf227
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.ar.xlf315
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.az.xlf227
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.bg.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.ca.xlf311
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.cs.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.cy.xlf227
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.da.xlf251
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.de.xlf327
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.el.xlf283
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.en.xlf331
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.es.xlf327
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.et.xlf283
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.eu.xlf291
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.fa.xlf283
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.fi.xlf231
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.fr.xlf327
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.gl.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.he.xlf307
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.hr.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.hu.xlf327
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.hy.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.id.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.it.xlf327
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.ja.xlf331
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.lb.xlf327
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.lt.xlf311
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.lv.xlf315
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.mn.xlf151
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.nb.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.nl.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.nn.xlf227
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.no.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.pl.xlf331
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt.xlf311
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt_BR.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.ro.xlf287
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.ru.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.sk.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.sl.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.sq.xlf227
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf303
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Latn.xlf303
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.sv.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.th.xlf303
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.tl.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.tr.xlf231
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.uk.xlf323
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.vi.xlf283
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_CN.xlf319
-rw-r--r--public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_TW.xlf283
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/ConstraintTest.php245
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationListTest.php135
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationTest.php56
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php192
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractConstraintValidatorTest.php441
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/AllTest.php42
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/AllValidatorTest.php93
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/BicValidatorTest.php106
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/BlankValidatorTest.php70
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CallbackValidatorTest.php351
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CardSchemeValidatorTest.php143
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/ChoiceValidatorTest.php304
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionTest.php113
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php20
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayTest.php20
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorTest.php389
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CompositeTest.php148
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorArrayTest.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorCountableTest.php25
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorTest.php203
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CountryValidatorTest.php110
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/CurrencyValidatorTest.php112
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/DateTimeValidatorTest.php110
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/DateValidatorTest.php106
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/EmailValidatorTest.php190
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/EqualToValidatorTest.php74
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/ExpressionValidatorTest.php279
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/FileTest.php139
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorObjectTest.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorPathTest.php36
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorTest.php483
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/foo0
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test.gifbin0 -> 801 bytes
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_4by3.gifbin0 -> 57 bytes
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_landscape.gifbin0 -> 43 bytes
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_portrait.gifbin0 -> 43 bytes
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php76
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanValidatorTest.php79
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/GroupSequenceTest.php100
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IbanValidatorTest.php450
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IdenticalToValidatorTest.php94
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/ImageValidatorTest.php332
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IpValidatorTest.php456
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IsFalseValidatorTest.php57
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IsNullValidatorTest.php67
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IsTrueValidatorTest.php57
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IsbnValidatorTest.php271
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/IssnValidatorTest.php187
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/LanguageValidatorTest.php110
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/LengthValidatorTest.php252
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanOrEqualValidatorTest.php79
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanValidatorTest.php78
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/LocaleValidatorTest.php98
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/LuhnValidatorTest.php127
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/NotBlankValidatorTest.php106
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/NotEqualToValidatorTest.php74
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/NotIdenticalToValidatorTest.php92
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/NotNullValidatorTest.php63
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/RangeValidatorTest.php403
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexTest.php88
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexValidatorTest.php98
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/TimeValidatorTest.php107
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/TypeValidatorTest.php187
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/UrlValidatorTest.php242
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/UuidValidatorTest.php221
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Constraints/ValidTest.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/CallbackClass.php24
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ClassConstraint.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintA.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintAValidator.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintB.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintC.php30
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValue.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValueAsDefault.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/Countable.php27
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/CustomArrayObject.php70
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/Entity.php104
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceA.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceB.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParent.php31
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParentInterface.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCar.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCarTurbo.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticVehicle.php25
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraint.php24
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraintValidator.php23
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeClassMetadata.php26
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeMetadataFactory.php72
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/FilesLoader.php39
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderEntity.php36
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraint.php18
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraintValidator.php16
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/LegacyClassMetadata.php20
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/PropertyConstraint.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/Reference.php29
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/StubGlobalExecutionContext.php68
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Fixtures/ToString.php22
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/LegacyExecutionContextTest.php335
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/LegacyValidatorTest.php42
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/DoctrineCacheTest.php85
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/LegacyApcCacheTest.php83
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/ClassMetadataTest.php323
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/BlackHoleMetadataFactoryTest.php34
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php218
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/GetterMetadataTest.php72
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/LegacyElementMetadataTest.php79
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AbstractStaticMethodLoader.php19
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AnnotationLoaderTest.php164
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/FilesLoaderTest.php49
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/LoaderChainTest.php85
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php140
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/XmlFileLoaderTest.php136
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/YamlFileLoaderTest.php139
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/bad-format.yml9
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml19
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.xml124
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.yml62
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/empty-mapping.yml0
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/nonvalid-mapping.yml1
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/withdoctype.xml7
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/MemberMetadataTest.php120
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Mapping/PropertyMetadataTest.php56
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Resources/TranslationFilesTest.php48
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Util/PropertyPathTest.php37
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Validator/Abstract2Dot5ApiTest.php742
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractLegacyApiTest.php313
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractValidatorTest.php1284
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidator2Dot5ApiTest.php35
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidatorLegacyApiTest.php35
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/Validator/RecursiveValidator2Dot5ApiTest.php57
-rw-r--r--public/system/storage/vendor/symfony/validator/Tests/ValidatorBuilderTest.php117
-rw-r--r--public/system/storage/vendor/symfony/validator/Util/PropertyPath.php56
-rw-r--r--public/system/storage/vendor/symfony/validator/Validation.php68
-rw-r--r--public/system/storage/vendor/symfony/validator/ValidationVisitor.php181
-rw-r--r--public/system/storage/vendor/symfony/validator/ValidationVisitorInterface.php82
-rw-r--r--public/system/storage/vendor/symfony/validator/Validator.php208
-rw-r--r--public/system/storage/vendor/symfony/validator/Validator/ContextualValidatorInterface.php83
-rw-r--r--public/system/storage/vendor/symfony/validator/Validator/LegacyValidator.php27
-rw-r--r--public/system/storage/vendor/symfony/validator/Validator/RecursiveContextualValidator.php831
-rw-r--r--public/system/storage/vendor/symfony/validator/Validator/RecursiveValidator.php171
-rw-r--r--public/system/storage/vendor/symfony/validator/Validator/ValidatorInterface.php92
-rw-r--r--public/system/storage/vendor/symfony/validator/ValidatorBuilder.php372
-rw-r--r--public/system/storage/vendor/symfony/validator/ValidatorBuilderInterface.php181
-rw-r--r--public/system/storage/vendor/symfony/validator/ValidatorInterface.php103
-rw-r--r--public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilder.php181
-rw-r--r--public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilderInterface.php114
-rw-r--r--public/system/storage/vendor/symfony/validator/Violation/LegacyConstraintViolationBuilder.php166
-rw-r--r--public/system/storage/vendor/symfony/validator/composer.json58
-rw-r--r--public/system/storage/vendor/symfony/validator/phpunit.xml.dist31
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/.gitignore1
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/MIT-LICENSE.txt21
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/README.md89
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Cache.php146
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Common.php234
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Prpcrypt.php196
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Tools.php308
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Loader.php129
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCard.php819
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCustom.php385
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatDevice.php467
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatExtends.php209
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatHardware.php160
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMedia.php430
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMenu.php183
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMessage.php352
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatOauth.php138
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPay.php620
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPoi.php193
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatReceive.php771
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatScript.php138
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatService.php408
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatUser.php612
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/composer.json18
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/include.php17
-rw-r--r--public/system/storage/vendor/zoujingli/wechat-php-sdk/test.php68
1328 files changed, 174432 insertions, 0 deletions
diff --git a/public/system/storage/cache/index.html b/public/system/storage/cache/index.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/cache/index.html
diff --git a/public/system/storage/download/index.html b/public/system/storage/download/index.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/download/index.html
diff --git a/public/system/storage/logs/index.html b/public/system/storage/logs/index.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/logs/index.html
diff --git a/public/system/storage/modification/index.html b/public/system/storage/modification/index.html
new file mode 100644
index 0000000..170db24
--- /dev/null
+++ b/public/system/storage/modification/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Untitled Document</title>
+</head>
+
+<body>
+</body>
+</html>
diff --git a/public/system/storage/session/index.html b/public/system/storage/session/index.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/session/index.html
diff --git a/public/system/storage/upload/index.html b/public/system/storage/upload/index.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/upload/index.html
diff --git a/public/system/storage/vendor/autoload.php b/public/system/storage/vendor/autoload.php
new file mode 100644
index 0000000..60874b1
--- /dev/null
+++ b/public/system/storage/vendor/autoload.php
@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit4356ab4fdc794d105db4fa48b241456c::getLoader();
diff --git a/public/system/storage/vendor/bin/pscss b/public/system/storage/vendor/bin/pscss
new file mode 100644
index 0000000..7fd45db
--- /dev/null
+++ b/public/system/storage/vendor/bin/pscss
@@ -0,0 +1,10 @@
+#!/usr/bin/env sh
+
+dir=$(cd "${0%[/\\]*}" > /dev/null; cd "../leafo/scssphp" && pwd)
+
+if [ -d /proc/cygdrive ] && [[ $(which php) == $(readlink -n /proc/cygdrive)/* ]]; then
+ # We are in Cgywin using Windows php, so the path must be translated
+ dir=$(cygpath -m "$dir");
+fi
+
+"${dir}/pscss" "$@"
diff --git a/public/system/storage/vendor/bin/pscss.bat b/public/system/storage/vendor/bin/pscss.bat
new file mode 100644
index 0000000..e09aae1
--- /dev/null
+++ b/public/system/storage/vendor/bin/pscss.bat
@@ -0,0 +1,4 @@
+@ECHO OFF
+setlocal DISABLEDELAYEDEXPANSION
+SET BIN_TARGET=%~dp0/../leafo/scssphp/pscss
+php "%BIN_TARGET%" %*
diff --git a/public/system/storage/vendor/braintree/braintree_php/.gitignore b/public/system/storage/vendor/braintree/braintree_php/.gitignore
new file mode 100644
index 0000000..2fc162c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/.gitignore
@@ -0,0 +1,6 @@
+/vendor
+/docs
+/tags
+composer.lock
+composer.phar
+*.tgz
diff --git a/public/system/storage/vendor/braintree/braintree_php/CHANGELOG.md b/public/system/storage/vendor/braintree/braintree_php/CHANGELOG.md
new file mode 100644
index 0000000..106a1db
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/CHANGELOG.md
@@ -0,0 +1,362 @@
+## 3.2.0
+* Add additional search criteria
+
+## 3.1.0
+* Add support for HHVM
+* Validate that configuration is valid before verifying webhooks
+* Make OAuth methods conform more to existing API
+* Expose customer paymentMethods as an attribute
+
+## 3.0.1
+* Add support for Android Pay
+
+## 3.0.0
+* Deprecate PHP 5.2 and 5.3
+* Validate webhook challenge payload
+* Bugfix for calling `__toString()` on objects that contain a `\DateTime`
+
+## 2.40.0
+* Add missing criteria to credit card verification search
+* Bugfix for autoloading files with Composer
+
+## 2.39.0
+* Add oauth functionality
+* Add 3DS info to the server side
+
+## 2.38.0
+* Update payment instrument types and test nonces
+* Add missing valid params to PaymentMethodGateway
+
+## 2.37.0
+* Add 3D Secure transaction fields
+* Add ability to create nonce from vaulted payment methods
+
+## 2.36.0
+* Surface Apple Pay payment instrument name in responses
+* Support Coinbase payment instruments
+
+## 2.35.2
+* Fix E_STRICT errors
+* Expose subscription status details
+
+## 2.35.1
+* Bugfix for auto loading files
+
+## 2.35.0
+* Allow PayPal fields in transaction.options.paypal
+* Add error code constants
+* Internal refactoring
+
+## 2.34.0
+* Add risk_data to Transaction and Verification with Kount decision and id
+* Add verification_amount an option when creating a credit card
+* Add TravelCruise industry type to Transaction
+* Add room_rate to Lodging industry type
+* Add CreditCard#verification as the latest verification on that credit card
+* Add ApplePay support to all endpoints that may return ApplePayCard objects
+* Add prefix to sample Webhook to simulate webhook query params
+
+## 2.33.0
+* Allow descriptor to be passed in Funding Details options params for Merchant Account create and update.
+
+## 2.32.0
+* Add additionalProcessorResponse to Transaction
+
+## 2.31.1
+* Allow payee_email to be passed in options params for Transaction create
+
+## 2.31.0
+* Added paypal specific fields to transaction calls
+* Added SettlementPending, SettlementDeclined transaction statuses
+
+## 2.30.0
+* Add descriptor url support
+
+## 2.29.0
+* Allow credit card verification options to be passed outside of the nonce for PaymentMethod.create
+* Allow billing_address parameters and billing_address_id to be passed outside of the nonce for PaymentMethod.create
+* Add Subscriptions to paypal accounts
+* Add PaymentMethod.update
+* Add fail_on_duplicate_payment_method option to PaymentMethod.create
+
+## 2.28.0
+* Adds support for v.zero SDKs.
+
+## 2.27.2
+
+* Make webhook parsing more robust with newlines
+* Add messages to InvalidSignature exceptions
+
+## 2.27.1
+
+* Updated secureCompare to correctly compare strings in consistent time
+* Add better error messages around webhook verification
+
+## 2.27.0
+
+* Include Dispute information on Transaction
+* Search for Transactions disputed on a certain date
+
+## 2.26.0
+
+* Disbursement Webhooks
+
+## 2.25.1
+
+* Fix factories on AddOn and Discount (thanks [stewe](https://github.com/stewe))
+* Allow billingAddressId on transaction create
+
+## 2.25.0
+
+* Merchant account find API
+
+## 2.24.0
+
+* Merchant account update API
+* Merchant account create API v2
+
+## 2.23.1
+
+* Update configuration URLs
+
+## 2.23.0
+
+* Official Partnership support
+
+## 2.22.2
+
+* Add Partner Merchant Declined webhook
+* use preg_callback_replace instead of preg_replace (thanks [jonthornton](https://github.com/jonthornton)!)
+
+## 2.22.1
+
+* Adds missing test contstant to library namespace
+
+## 2.22.0
+
+* Adds holdInEscrow method
+* Add error codes for verification not supported error
+* Add companyName and taxId to merchant account create
+* Adds cancelRelease method
+* Adds releaseFromEscrow functionality
+* Adds phone to merchant account signature.
+* Adds merchant account phone error code.
+* Fix casing issues with Braintree\_Http and Braintree\_Util references (thanks [steven-hadfield](https://github.com/steven-hadfield)!)
+* Fixed transaction initialization arguments to be optional (thanks [karolsojko](https://github.com/karolsojko)!)
+
+## 2.21.0
+
+* Enable device data.
+
+## 2.20.0
+
+* Fixed getting custom fields with valueForHtmlField. [Thanks to Miguel Manso for the fix.](https://github.com/mumia)
+* Adds disbursement details to transactions.
+* Adds image url to transactions.
+
+## 2.19.0
+
+* Adds channel field to transactions.
+
+## 2.18.0
+
+* Adds country of issuance and issuing bank bin database fields
+
+## 2.17.0
+
+* Adds verification search
+
+## 2.16.0
+
+* Additional card information, such as prepaid, debit, commercial, Durbin regulated, healthcare, and payroll, are returned on credit card responses
+* Allows transactions to be specified as recurring
+
+## 2.15.0
+
+* Adds prepaid field to credit cards (possible values include Yes, No, Unknown)
+
+## 2.14.1
+
+* Adds composer support (thanks [till](https://github.com/till))
+* Fixes erroneous version number
+* Braintree_Plan::all() returns empty array if no plans exist
+
+## 2.14.0
+
+* Adds webhook gateways for parsing, verifying, and testing notifications
+
+## 2.13.0
+
+* Adds search for duplicate credit cards given a payment method token
+* Adds flag to fail saving credit card to vault if card is duplicate
+
+## 2.12.5
+
+* Exposes plan_id on transactions
+
+## 2.12.4
+
+* Added error code for invalid purchase order number
+
+## 2.12.3
+
+* Fixed problematic case in ResourceCollection when no results are returned from a search.
+
+## 2.12.2
+
+* Fixed customer search, which returned customers when no customers matched search criteria
+
+## 2.12.1
+
+* Added new error message for merchant accounts that do not support refunds
+
+## 2.12.0
+
+* Added ability to retrieve all Plans, AddOns, and Discounts
+* Added Transaction cloning
+
+## 2.11.0
+
+* Added Braintree_SettlementBatchSummary
+
+## 2.10.1
+
+* Wrap dependency requirement in a function, to prevent pollution of the global namespace
+
+## 2.10.0
+
+* Added subscriptionDetails to Transaction
+* Added flag to store in vault only when a transaction is successful
+* Added new error code
+
+## 2.9.0
+
+* Added a new transaction state, AUTHORIZATION_EXPIRED.
+* Enabled searching by authorizationExpiredAt.
+
+## 2.8.0
+
+* Added next_billing_date and transaction_id to subscription search
+* Added address_country_name to customer search
+* Added new error codes
+
+## 2.7.0
+
+* Added Customer search
+* Added dynamic descriptors to Subscriptions and Transactions
+* Added level 2 fields to Transactions:
+ * tax_amount
+ * tax_exempt
+ * purchase_order_number
+
+## 2.6.1
+
+* Added billingAddressId to allowed parameters for credit cards create and update
+* Allow searching on subscriptions that are currently in a trial period using inTrialPeriod
+
+## 2.6.0
+
+* Added ability to perform multiple partial refunds on Braintree_Transactions
+* Allow passing expirationMonth and expirationYear separately when creating Braintree_Transactions
+* Added revertSubscriptionOnProrationFailure flag to Braintree_Subscription update that specifies how a Subscription should react to a failed proration charge
+* Deprecated Braintree_Subscription nextBillAmount in favor of nextBillingPeriodAmount
+* Deprecated Braintree_Transaction refundId in favor of refundIds
+* Added new fields to Braintree_Subscription:
+ * balance
+ * paidThroughDate
+ * nextBillingPeriodAmount
+
+## 2.5.0
+
+* Added Braintree_AddOns/Braintree_Discounts
+* Enhanced Braintree_Subscription search
+* Enhanced Braintree_Transaction search
+* Added constants for Braintree_Result_CreditCardVerification statuses
+* Added EXPIRED and PENDING statuses to Braintree_Subscription
+* Allowed prorateCharges to be specified on Braintree_Subscription update
+* Added Braintree_AddOn/Braintree_Discount details to Braintree_Transactions that were created from a Braintree_Subscription
+* Removed 13 digit Visa Sandbox Credit Card number and replaced it with a 16 digit Visa
+* Added new fields to Braintree_Subscription:
+ * billingDayOfMonth
+ * daysPastDue
+ * firstBillingDate
+ * neverExpires
+ * numberOfBillingCycles
+
+## 2.4.0
+
+* Added ability to specify country using countryName, countryCodeAlpha2, countryCodeAlpha3, or countryCodeNumeric (see [ISO_3166-1](http://en.wikipedia.org/wiki/ISO_3166-1))
+* Added gatewayRejectionReason to Braintree_Transaction and Braintree_Verification
+* Added unified message to result objects
+
+## 2.3.0
+
+* Added unified Braintree_TransparentRedirect url and confirm methods and deprecated old methods
+* Added functions to Braintree_CreditCard to allow searching on expiring and expired credit cards
+* Allow card verification against a specified merchant account
+* Added ability to update a customer, credit card, and billing address in one request
+* Allow updating the paymentMethodToken on a subscription
+
+## 2.2.0
+
+* Prevent race condition when pulling back collection results -- search results represent the state of the data at the time the query was run
+* Rename ResourceCollection's approximate_size to maximum_size because items that no longer match the query will not be returned in the result set
+* Correctly handle HTTP error 426 (Upgrade Required) -- the error code is returned when your client library version is no long compatible with the gateway
+* Add the ability to specify merchant_account_id when verifying credit cards
+* Add subscription_id to transactions created from subscriptions
+
+## 2.1.0
+
+* Added transaction advanced search
+* Added ability to partially refund transactions
+* Added ability to manually retry past-due subscriptions
+* Added new transaction error codes
+* Allow merchant account to be specified when creating transactions
+* Allow creating a transaction with a vault customer and new payment method
+* Allow existing billing address to be updated when updating credit card
+* Correctly handle xml with nil=true
+
+## 2.0.0
+
+* Updated success? on transaction responses to return false on declined transactions
+* Search results now include Enumerable and will automatically paginate data
+* Added credit_card[cardholder_name] to allowed transaction params and CreditCardDetails (thanks [chrismcc](http://github.com/chrismcc))
+* Fixed a bug with Customer::all
+* Added constants for error codes
+
+## 1.2.1
+
+* Added methods to get both shallow and deep errors from a Braintree_ValidationErrorCollection
+* Added the ability to make a credit card the default card for a customer
+* Added constants for transaction statuses
+* Updated Quick Start in README.md to show a workflow with error checking
+
+## 1.2.0
+
+* Added subscription search
+* Provide access to associated subscriptions from CreditCard
+* Switched from using Zend framework for HTTP requests to using curl extension
+* Fixed a bug in Transparent Redirect when arg_separator.output is configured as &amp; instead of &
+* Increased http request timeout
+* Fixed a bug where ForgedQueryString exception was being raised instead of DownForMaintenance
+* Updated SSL CA files
+
+## 1.1.1
+
+* Added Braintree_Transaction::refund
+* Added Braintree_Transaction::submitForSettlementNoValidate
+* Fixed a bug in errors->onHtmlField when checking for errors on custom fields when there are none
+* Added support for passing merchantAccountId for Transaction and Subscription
+
+## 1.1.0
+
+* Added recurring billing support
+
+## 1.0.1
+
+* Fixed bug with Braintree_Error_ErrorCollection.deepSize
+* Added methods for accessing validation errors and params by html field name
+
+## 1.0.0
+
+* Initial release
diff --git a/public/system/storage/vendor/braintree/braintree_php/LICENSE b/public/system/storage/vendor/braintree/braintree_php/LICENSE
new file mode 100644
index 0000000..8c352d5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014 Braintree, a division of PayPal, Inc.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/public/system/storage/vendor/braintree/braintree_php/README.md b/public/system/storage/vendor/braintree/braintree_php/README.md
new file mode 100644
index 0000000..5d77b8c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/README.md
@@ -0,0 +1,79 @@
+# Braintree PHP Client Library
+
+The Braintree PHP library provides integration access to the Braintree Gateway.
+
+## Dependencies
+
+PHP version >= 5.4.0 is required.
+
+The following PHP extensions are required:
+
+* curl
+* dom
+* hash
+* openssl
+* xmlwriter
+
+## Quick Start Example
+
+```php
+<?php
+
+require_once 'PATH_TO_BRAINTREE/lib/Braintree.php';
+
+Braintree_Configuration::environment('sandbox');
+Braintree_Configuration::merchantId('your_merchant_id');
+Braintree_Configuration::publicKey('your_public_key');
+Braintree_Configuration::privateKey('your_private_key');
+
+$result = Braintree_Transaction::sale(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+));
+
+if ($result->success) {
+ print_r("success!: " . $result->transaction->id);
+} else if ($result->transaction) {
+ print_r("Error processing transaction:");
+ print_r("\n code: " . $result->transaction->processorResponseCode);
+ print_r("\n text: " . $result->transaction->processorResponseText);
+} else {
+ print_r("Validation errors: \n");
+ print_r($result->errors->deepAll());
+}
+
+?>
+```
+
+## HHVM Support
+
+The Braintree PHP library will run on HHVM >= 3.4.2.
+
+## Legacy PHP Support
+
+Version [2.40.0](https://github.com/braintree/braintree_php/releases/tag/2.40.0) is compatible with PHP 5.2 and 5.3. You can find it on our releases page.
+
+## Documentation
+
+ * [Official documentation](https://developers.braintreepayments.com/php/sdk/server/overview)
+
+## Testing
+
+Tests are written in PHPunit (installed by composer). Unit tests should run on
+any system meeting the base requirements:
+
+ phpunit tests/unit/
+
+Please note that the integration tests require access to services internal to
+Braintree, and so will not run in your test environment.
+
+## Open Source Attribution
+
+A list of open source projects that help power Braintree can be found [here](https://www.braintreepayments.com/developers/open-source).
+
+## License
+
+See the LICENSE file.
diff --git a/public/system/storage/vendor/braintree/braintree_php/Rakefile b/public/system/storage/vendor/braintree/braintree_php/Rakefile
new file mode 100644
index 0000000..30fbfe2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/Rakefile
@@ -0,0 +1,67 @@
+task :default => :test
+task :test => %w[test:unit test:integration]
+
+namespace :test do
+ task :unit => %w[test:php:unit test:hhvm:unit]
+ task :integration => %w[test:php:integration test:hhvm:integration]
+
+ namespace :php do
+ desc "print PHP version"
+ task :version do
+ print_php_version("php")
+ end
+
+ desc "run unit tests under PHP"
+ task :unit => :version do
+ run_php_test_suite("php", "unit")
+ end
+
+ desc "run integration tests under PHP"
+ task :integration do
+ run_php_test_suite("php", "integration")
+ end
+ end
+
+ namespace :hhvm do
+ desc "print HHVM version"
+ task :version do
+ print_php_version("hhvm")
+ end
+
+ desc "run tests under HHVM"
+ task :test => [:unit, :integration]
+
+ desc "run unit tests under HHVM"
+ task :unit => :version do
+ run_php_test_suite("hhvm", "unit")
+ end
+
+ desc "run integration tests under HHVM"
+ task :integration do
+ run_php_test_suite("hhvm", "integration")
+ end
+ end
+
+ desc "run tests under PHP"
+ task :php => %w[php:unit php:integration]
+
+ desc "run tests under HHVM"
+ task :hhvm => %w[hhvm:unit hhvm:integration]
+
+ desc "run a single test file"
+ task :single_test, :file_path do |t, args|
+ run_php_test_file(args[:file_path])
+ end
+end
+
+def print_php_version(interpreter)
+ sh "#{interpreter} --version"
+end
+
+def run_php_test_suite(interpreter, test_suite)
+ sh "#{interpreter} ./vendor/bin/phpunit --testsuite #{test_suite}"
+end
+
+def run_php_test_file(test_file)
+ sh "./vendor/bin/phpunit #{test_file}"
+end
diff --git a/public/system/storage/vendor/braintree/braintree_php/ci.sh b/public/system/storage/vendor/braintree/braintree_php/ci.sh
new file mode 100644
index 0000000..4f3e8b7
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/ci.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+curl -sS https://getcomposer.org/installer | php -d suhosin.executor.include.whitelist=phar
+
+php -d suhosin.executor.include.whitelist=phar ./composer.phar install
+
+if [ "$1" == "hhvm" ]; then
+ rake test:hhvm --trace
+else
+ rake test:php --trace
+fi
diff --git a/public/system/storage/vendor/braintree/braintree_php/composer.json b/public/system/storage/vendor/braintree/braintree_php/composer.json
new file mode 100644
index 0000000..f822fc4
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "braintree/braintree_php",
+ "type": "library",
+ "description": "Braintree PHP Client Library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Braintree",
+ "homepage": "http://www.braintreepayments.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "ext-curl": "*",
+ "ext-dom": "*",
+ "ext-hash": "*",
+ "ext-openssl": "*",
+ "ext-xmlwriter": "*"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*"
+ },
+ "autoload": {
+ "psr-0": {
+ "Braintree": "lib"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree.php
new file mode 100644
index 0000000..b5d2811
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Braintree PHP Library
+ *
+ * Braintree base class and initialization
+ * Provides methods to child classes. This class cannot be instantiated.
+ *
+ * PHP version 5
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+
+set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__)));
+
+require_once('Braintree/Base.php');
+require_once('Braintree/Modification.php');
+require_once('Braintree/Instance.php');
+
+require_once('Braintree/OAuthCredentials.php');
+require_once('Braintree/Address.php');
+require_once('Braintree/AddressGateway.php');
+require_once('Braintree/AddOn.php');
+require_once('Braintree/AddOnGateway.php');
+require_once('Braintree/AndroidPayCard.php');
+require_once('Braintree/ApplePayCard.php');
+require_once('Braintree/ClientToken.php');
+require_once('Braintree/ClientTokenGateway.php');
+require_once('Braintree/CoinbaseAccount.php');
+require_once('Braintree/Collection.php');
+require_once('Braintree/Configuration.php');
+require_once('Braintree/CredentialsParser.php');
+require_once('Braintree/CreditCard.php');
+require_once('Braintree/CreditCardGateway.php');
+require_once('Braintree/Customer.php');
+require_once('Braintree/CustomerGateway.php');
+require_once('Braintree/CustomerSearch.php');
+require_once('Braintree/DisbursementDetails.php');
+require_once('Braintree/Dispute.php');
+require_once('Braintree/Dispute/TransactionDetails.php');
+require_once('Braintree/Descriptor.php');
+require_once('Braintree/Digest.php');
+require_once('Braintree/Discount.php');
+require_once('Braintree/DiscountGateway.php');
+require_once('Braintree/IsNode.php');
+require_once('Braintree/EqualityNode.php');
+require_once('Braintree/Exception.php');
+require_once('Braintree/Gateway.php');
+require_once('Braintree/Http.php');
+require_once('Braintree/KeyValueNode.php');
+require_once('Braintree/Merchant.php');
+require_once('Braintree/MerchantGateway.php');
+require_once('Braintree/MerchantAccount.php');
+require_once('Braintree/MerchantAccountGateway.php');
+require_once('Braintree/MerchantAccount/BusinessDetails.php');
+require_once('Braintree/MerchantAccount/FundingDetails.php');
+require_once('Braintree/MerchantAccount/IndividualDetails.php');
+require_once('Braintree/MerchantAccount/AddressDetails.php');
+require_once('Braintree/MultipleValueNode.php');
+require_once('Braintree/MultipleValueOrTextNode.php');
+require_once('Braintree/OAuthGateway.php');
+require_once('Braintree/PartialMatchNode.php');
+require_once('Braintree/Plan.php');
+require_once('Braintree/PlanGateway.php');
+require_once('Braintree/RangeNode.php');
+require_once('Braintree/ResourceCollection.php');
+require_once('Braintree/RiskData.php');
+require_once('Braintree/ThreeDSecureInfo.php');
+require_once('Braintree/SettlementBatchSummary.php');
+require_once('Braintree/SettlementBatchSummaryGateway.php');
+require_once('Braintree/SignatureService.php');
+require_once('Braintree/Subscription.php');
+require_once('Braintree/SubscriptionGateway.php');
+require_once('Braintree/SubscriptionSearch.php');
+require_once('Braintree/Subscription/StatusDetails.php');
+require_once('Braintree/TextNode.php');
+require_once('Braintree/Transaction.php');
+require_once('Braintree/TransactionGateway.php');
+require_once('Braintree/Disbursement.php');
+require_once('Braintree/TransactionSearch.php');
+require_once('Braintree/TransparentRedirect.php');
+require_once('Braintree/TransparentRedirectGateway.php');
+require_once('Braintree/Util.php');
+require_once('Braintree/Version.php');
+require_once('Braintree/Xml.php');
+require_once('Braintree/Error/Codes.php');
+require_once('Braintree/Error/ErrorCollection.php');
+require_once('Braintree/Error/Validation.php');
+require_once('Braintree/Error/ValidationErrorCollection.php');
+require_once('Braintree/Exception/Authentication.php');
+require_once('Braintree/Exception/Authorization.php');
+require_once('Braintree/Exception/Configuration.php');
+require_once('Braintree/Exception/DownForMaintenance.php');
+require_once('Braintree/Exception/ForgedQueryString.php');
+require_once('Braintree/Exception/InvalidChallenge.php');
+require_once('Braintree/Exception/InvalidSignature.php');
+require_once('Braintree/Exception/NotFound.php');
+require_once('Braintree/Exception/ServerError.php');
+require_once('Braintree/Exception/SSLCertificate.php');
+require_once('Braintree/Exception/SSLCaFileNotFound.php');
+require_once('Braintree/Exception/Unexpected.php');
+require_once('Braintree/Exception/UpgradeRequired.php');
+require_once('Braintree/Exception/ValidationsFailed.php');
+require_once('Braintree/Result/CreditCardVerification.php');
+require_once('Braintree/Result/Error.php');
+require_once('Braintree/Result/Successful.php');
+require_once('Braintree/Test/CreditCardNumbers.php');
+require_once('Braintree/Test/MerchantAccount.php');
+require_once('Braintree/Test/TransactionAmounts.php');
+require_once('Braintree/Test/VenmoSdk.php');
+require_once('Braintree/Test/Nonces.php');
+require_once('Braintree/Transaction/AddressDetails.php');
+require_once('Braintree/Transaction/AndroidPayCardDetails.php');
+require_once('Braintree/Transaction/ApplePayCardDetails.php');
+require_once('Braintree/Transaction/CoinbaseDetails.php');
+require_once('Braintree/Transaction/CreditCardDetails.php');
+require_once('Braintree/Transaction/PayPalDetails.php');
+require_once('Braintree/Transaction/CustomerDetails.php');
+require_once('Braintree/Transaction/StatusDetails.php');
+require_once('Braintree/Transaction/SubscriptionDetails.php');
+require_once('Braintree/WebhookNotification.php');
+require_once('Braintree/WebhookTesting.php');
+require_once('Braintree/Xml/Generator.php');
+require_once('Braintree/Xml/Parser.php');
+require_once('Braintree/CreditCardVerification.php');
+require_once('Braintree/CreditCardVerificationGateway.php');
+require_once('Braintree/CreditCardVerificationSearch.php');
+require_once('Braintree/PartnerMerchant.php');
+require_once('Braintree/PayPalAccount.php');
+require_once('Braintree/PayPalAccountGateway.php');
+require_once('Braintree/PaymentMethod.php');
+require_once('Braintree/PaymentMethodGateway.php');
+require_once('Braintree/PaymentMethodNonce.php');
+require_once('Braintree/PaymentMethodNonceGateway.php');
+require_once('Braintree/PaymentInstrumentType.php');
+require_once('Braintree/UnknownPaymentMethod.php');
+
+if (version_compare(PHP_VERSION, '5.4.0', '<')) {
+ throw new Braintree_Exception('PHP version >= 5.4.0 required');
+}
+
+
+function requireDependencies() {
+ $requiredExtensions = array('xmlwriter', 'openssl', 'dom', 'hash', 'curl');
+ foreach ($requiredExtensions AS $ext) {
+ if (!extension_loaded($ext)) {
+ throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.');
+ }
+ }
+}
+
+requireDependencies();
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOn.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOn.php
new file mode 100644
index 0000000..ed31c0b
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOn.php
@@ -0,0 +1,27 @@
+<?php
+
+class Braintree_AddOn extends Braintree_Modification
+{
+ /**
+ *
+ * @param array $attributes
+ * @return Braintree_AddOn
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+
+ /**
+ * static methods redirecting to gateway
+ *
+ * @return Braintree_AddOn[]
+ */
+ public static function all()
+ {
+ return Braintree_Configuration::gateway()->addOn()->all();
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOnGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOnGateway.php
new file mode 100644
index 0000000..6fc3a6e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddOnGateway.php
@@ -0,0 +1,51 @@
+<?php
+
+class Braintree_AddOnGateway
+{
+ /**
+ *
+ * @var Braintree_Gateway
+ */
+ private $_gateway;
+
+ /**
+ *
+ * @var Braintree_Configuration
+ */
+ private $_config;
+
+ /**
+ *
+ * @var Braintree_Http
+ */
+ private $_http;
+
+ /**
+ *
+ * @param Braintree_Gateway $gateway
+ */
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ /**
+ *
+ * @return Braintree_AddOn[]
+ */
+ public function all()
+ {
+ $path = $this->_config->merchantPath() . '/add_ons';
+ $response = $this->_http->get($path);
+
+ $addOns = array("addOn" => $response['addOns']);
+
+ return Braintree_Util::extractAttributeAsArray(
+ $addOns,
+ 'addOn'
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Address.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Address.php
new file mode 100644
index 0000000..5db2a67
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Address.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Braintree Address module
+ * PHP Version 5
+ * Creates and manages Braintree Addresses
+ *
+ * An Address belongs to a Customer. It can be associated to a
+ * CreditCard as the billing address. It can also be used
+ * as the shipping address when creating a Transaction.
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $company
+ * @property-read string $countryName
+ * @property-read string $createdAt
+ * @property-read string $customerId
+ * @property-read string $extendedAddress
+ * @property-read string $firstName
+ * @property-read string $id
+ * @property-read string $lastName
+ * @property-read string $locality
+ * @property-read string $postalCode
+ * @property-read string $region
+ * @property-read string $streetAddress
+ * @property-read string $updatedAt
+ */
+class Braintree_Address extends Braintree_Base
+{
+ /**
+ * returns false if comparing object is not a Braintree_Address,
+ * or is a Braintree_Address with a different id
+ *
+ * @param object $other address to compare against
+ * @return boolean
+ */
+ public function isEqual($other)
+ {
+ return !($other instanceof Braintree_Address) ?
+ false :
+ ($this->id === $other->id && $this->customerId === $other->customerId);
+ }
+
+ /**
+ * create a printable representation of the object as:
+ * ClassName[property=value, property=value]
+ * @ignore
+ * @return var
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @ignore
+ * @access protected
+ * @param array $addressAttribs array of address data
+ * @return none
+ */
+ protected function _initialize($addressAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $addressAttribs;
+ }
+
+ /**
+ * factory method: returns an instance of Braintree_Address
+ * to the requesting method, with populated properties
+ * @ignore
+ * @return object instance of Braintree_Address
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+
+ }
+
+
+ // static methods redirecting to gateway
+
+ /**
+ *
+ * @param array $attribs
+ * @return Braintree_Address
+ */
+ public static function create($attribs)
+ {
+ return Braintree_Configuration::gateway()->address()->create($attribs);
+ }
+
+ /**
+ *
+ * @param array $attribs
+ * @return Braintree_Address
+ */
+ public static function createNoValidate($attribs)
+ {
+ return Braintree_Configuration::gateway()->address()->createNoValidate($attribs);
+ }
+
+ /**
+ *
+ * @param Braintree_Customer|int $customerOrId
+ * @param int $addressId
+ * @throws InvalidArgumentException
+ * @return Braintree_Result_Successful
+ */
+ public static function delete($customerOrId = null, $addressId = null)
+ {
+ return Braintree_Configuration::gateway()->address()->delete($customerOrId, $addressId);
+ }
+
+ /**
+ *
+ * @param Braintree_Customer|int $customerOrId
+ * @param int $addressId
+ * @throws Braintree_Exception_NotFound
+ * @return Braintree_Address
+ */
+ public static function find($customerOrId, $addressId)
+ {
+ return Braintree_Configuration::gateway()->address()->find($customerOrId, $addressId);
+ }
+
+ /**
+ *
+ * @param Braintree_Customer|int $customerOrId
+ * @param int $addressId
+ * @param array $attributes
+ * @throws Braintree_Exception_Unexpected
+ * @return Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public static function update($customerOrId, $addressId, $attributes)
+ {
+ return Braintree_Configuration::gateway()->address()->update($customerOrId, $addressId, $attributes);
+ }
+
+ public static function updateNoValidate($customerOrId, $addressId, $attributes)
+ {
+ return Braintree_Configuration::gateway()->address()->updateNoValidate($customerOrId, $addressId, $attributes);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddressGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddressGateway.php
new file mode 100644
index 0000000..b8dd7bb
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AddressGateway.php
@@ -0,0 +1,305 @@
+<?php
+/**
+ * Braintree AddressGateway module
+ * PHP Version 5
+ * Creates and manages Braintree Addresses
+ *
+ * An Address belongs to a Customer. It can be associated to a
+ * CreditCard as the billing address. It can also be used
+ * as the shipping address when creating a Transaction.
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_AddressGateway
+{
+ /**
+ *
+ * @var Braintree_Gateway
+ */
+ private $_gateway;
+
+ /**
+ *
+ * @var Braintree_Configuration
+ */
+ private $_config;
+
+ /**
+ *
+ * @var Braintree_Http
+ */
+ private $_http;
+
+ /**
+ *
+ * @param Braintree_Gateway $gateway
+ */
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+
+ /* public class methods */
+ /**
+ *
+ * @access public
+ * @param array $attribs
+ * @return object Result, either Successful or Error
+ */
+ public function create($attribs)
+ {
+ Braintree_Util::verifyKeys(self::createSignature(), $attribs);
+ $customerId = isset($attribs['customerId']) ?
+ $attribs['customerId'] :
+ null;
+
+ $this->_validateCustomerId($customerId);
+ unset($attribs['customerId']);
+ return $this->_doCreate(
+ '/customers/' . $customerId . '/addresses',
+ array('address' => $attribs)
+ );
+ }
+
+ /**
+ * attempts the create operation assuming all data will validate
+ * returns a Braintree_Address object instead of a Result
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ * @throws Braintree_Exception_ValidationError
+ */
+ public function createNoValidate($attribs)
+ {
+ $result = $this->create($attribs);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+
+ }
+
+ /**
+ * delete an address by id
+ *
+ * @param mixed $customerOrId
+ * @param string $addressId
+ */
+ public function delete($customerOrId = null, $addressId = null)
+ {
+ $this->_validateId($addressId);
+ $customerId = $this->_determineCustomerId($customerOrId);
+ $path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId;
+ $this->_http->delete($path);
+ return new Braintree_Result_Successful();
+ }
+
+ /**
+ * find an address by id
+ *
+ * Finds the address with the given <b>addressId</b> that is associated
+ * to the given <b>customerOrId</b>.
+ * If the address cannot be found, a NotFound exception will be thrown.
+ *
+ *
+ * @access public
+ * @param mixed $customerOrId
+ * @param string $addressId
+ * @return object Braintree_Address
+ * @throws Braintree_Exception_NotFound
+ */
+ public function find($customerOrId, $addressId)
+ {
+
+ $customerId = $this->_determineCustomerId($customerOrId);
+ $this->_validateId($addressId);
+
+ try {
+ $path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId;
+ $response = $this->_http->get($path);
+ return Braintree_Address::factory($response['address']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'address for customer ' . $customerId .
+ ' with id ' . $addressId . ' not found.'
+ );
+ }
+
+ }
+
+ /**
+ * updates the address record
+ *
+ * if calling this method in context,
+ * customerOrId is the 2nd attribute, addressId 3rd.
+ * customerOrId & addressId are not sent in object context.
+ *
+ *
+ * @access public
+ * @param array $attributes
+ * @param mixed $customerOrId (only used in call)
+ * @param string $addressId (only used in call)
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ */
+ public function update($customerOrId, $addressId, $attributes)
+ {
+ $this->_validateId($addressId);
+ $customerId = $this->_determineCustomerId($customerOrId);
+ Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
+
+ $path = $this->_config->merchantPath() . '/customers/' . $customerId . '/addresses/' . $addressId;
+ $response = $this->_http->put($path, array('address' => $attributes));
+
+ return $this->_verifyGatewayResponse($response);
+
+ }
+
+ /**
+ * update an address record, assuming validations will pass
+ *
+ * if calling this method in context,
+ * customerOrId is the 2nd attribute, addressId 3rd.
+ * customerOrId & addressId are not sent in object context.
+ *
+ * @access public
+ * @param array $transactionAttribs
+ * @param string $customerId
+ * @return object Braintree_Transaction
+ * @throws Braintree_Exception_ValidationsFailed
+ * @see Braintree_Address::update()
+ */
+ public function updateNoValidate($customerOrId, $addressId, $attributes)
+ {
+ $result = $this->update($customerOrId, $addressId, $attributes);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+
+ /**
+ * creates a full array signature of a valid create request
+ * @return array gateway create request format
+ */
+ public static function createSignature()
+ {
+ return array(
+ 'company', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric',
+ 'countryName', 'customerId', 'extendedAddress', 'firstName',
+ 'lastName', 'locality', 'postalCode', 'region', 'streetAddress'
+ );
+ }
+
+ /**
+ * creates a full array signature of a valid update request
+ * @return array gateway update request format
+ */
+ public static function updateSignature()
+ {
+ // TODO: remove customerId from update signature
+ return self::createSignature();
+
+ }
+
+ /**
+ * verifies that a valid address id is being used
+ * @ignore
+ * @param string $id address id
+ * @throws InvalidArgumentException
+ */
+ private function _validateId($id = null)
+ {
+ if (empty($id) || trim($id) == "") {
+ throw new InvalidArgumentException(
+ 'expected address id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
+ throw new InvalidArgumentException(
+ $id . ' is an invalid address id.'
+ );
+ }
+ }
+
+ /**
+ * verifies that a valid customer id is being used
+ * @ignore
+ * @param string $id customer id
+ * @throws InvalidArgumentException
+ */
+ private function _validateCustomerId($id = null)
+ {
+ if (empty($id) || trim($id) == "") {
+ throw new InvalidArgumentException(
+ 'expected customer id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
+ throw new InvalidArgumentException(
+ $id . ' is an invalid customer id.'
+ );
+ }
+
+ }
+
+ /**
+ * determines if a string id or Customer object was passed
+ * @ignore
+ * @param mixed $customerOrId
+ * @return string customerId
+ */
+ private function _determineCustomerId($customerOrId)
+ {
+ $customerId = ($customerOrId instanceof Braintree_Customer) ? $customerOrId->id : $customerOrId;
+ $this->_validateCustomerId($customerId);
+ return $customerId;
+
+ }
+
+ /* private class methods */
+ /**
+ * sends the create request to the gateway
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ private function _doCreate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+
+ }
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * creates a new Braintree_Address object and encapsulates
+ * it inside a Braintree_Result_Successful object, or
+ * encapsulates a Braintree_Errors object inside a Result_Error
+ * alternatively, throws an Unexpected exception if the response is invalid.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return object Result_Successful|Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['address'])) {
+ // return a populated instance of Braintree_Address
+ return new Braintree_Result_Successful(
+ Braintree_Address::factory($response['address'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected address or apiErrorResponse"
+ );
+ }
+
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AndroidPayCard.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AndroidPayCard.php
new file mode 100644
index 0000000..81201df
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/AndroidPayCard.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Braintree AndroidPayCard module
+ * Creates and manages Braintree Android Pay cards
+ *
+ * <b>== More information ==</b>
+ *
+ * See {@link https://developers.braintreepayments.com/javascript+php}<br />
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $bin
+ * @property-read string $cardType
+ * @property-read string $createdAt
+ * @property-read string $default
+ * @property-read string $expirationMonth
+ * @property-read string $expirationYear
+ * @property-read string $googleTransactionId
+ * @property-read string $imageUrl
+ * @property-read string $last4
+ * @property-read string $sourceCardLast4
+ * @property-read string $sourceCardType
+ * @property-read string $token
+ * @property-read string $updatedAt
+ * @property-read string $virtualCardLast4
+ * @property-read string $virtualCardType
+ */
+class Braintree_AndroidPayCard extends Braintree_Base
+{
+ /* instance methods */
+ /**
+ * returns false if default is null or false
+ *
+ * @return boolean
+ */
+ public function isDefault()
+ {
+ return $this->default;
+ }
+
+ /**
+ * factory method: returns an instance of Braintree_AndroidPayCard
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_AndroidPayCard
+ */
+ public static function factory($attributes)
+ {
+ $defaultAttributes = array(
+ 'expirationMonth' => '',
+ 'expirationYear' => '',
+ 'last4' => $attributes['virtualCardLast4'],
+ 'cardType' => $attributes['virtualCardType'],
+ );
+
+ $instance = new self();
+ $instance->_initialize(array_merge($defaultAttributes, $attributes));
+ return $instance;
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @access protected
+ * @param array $androidPayCardAttribs array of Android Pay card properties
+ * @return none
+ */
+ protected function _initialize($androidPayCardAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $androidPayCardAttribs;
+
+ $subscriptionArray = array();
+ if (isset($androidPayCardAttribs['subscriptions'])) {
+ foreach ($androidPayCardAttribs['subscriptions'] AS $subscription) {
+ $subscriptionArray[] = Braintree_Subscription::factory($subscription);
+ }
+ }
+
+ $this->_set('subscriptions', $subscriptionArray);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ApplePayCard.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ApplePayCard.php
new file mode 100644
index 0000000..4c18966
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ApplePayCard.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Braintree ApplePayCard module
+ * Creates and manages Braintree Apple Pay cards
+ *
+ * <b>== More information ==</b>
+ *
+ * See {@link https://developers.braintreepayments.com/javascript+php}<br />
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $cardType
+ * @property-read string $createdAt
+ * @property-read string $expirationDate
+ * @property-read string $expirationMonth
+ * @property-read string $expirationYear
+ * @property-read string $imageUrl
+ * @property-read string $last4
+ * @property-read string $token
+ * @property-read string $paymentInstrumentName
+ * @property-read string $updatedAt
+ */
+class Braintree_ApplePayCard extends Braintree_Base
+{
+ // Card Type
+ const AMEX = 'Apple Pay - American Express';
+ const MASTER_CARD = 'Apple Pay - MasterCard';
+ const VISA = 'Apple Pay - Visa';
+
+ /* instance methods */
+ /**
+ * returns false if default is null or false
+ *
+ * @return boolean
+ */
+ public function isDefault()
+ {
+ return $this->default;
+ }
+
+ /**
+ * checks whether the card is expired based on the current date
+ *
+ * @return boolean
+ */
+ public function isExpired()
+ {
+ return $this->expired;
+ }
+
+ /**
+ * factory method: returns an instance of Braintree_ApplePayCard
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_ApplePayCard
+ */
+ public static function factory($attributes)
+ {
+ $defaultAttributes = array(
+ 'expirationMonth' => '',
+ 'expirationYear' => '',
+ 'last4' => '',
+ );
+
+ $instance = new self();
+ $instance->_initialize(array_merge($defaultAttributes, $attributes));
+ return $instance;
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @access protected
+ * @param array $applePayCardAttribs array of Apple Pay card properties
+ * @return none
+ */
+ protected function _initialize($applePayCardAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $applePayCardAttribs;
+
+ $subscriptionArray = array();
+ if (isset($applePayCardAttribs['subscriptions'])) {
+ foreach ($applePayCardAttribs['subscriptions'] AS $subscription) {
+ $subscriptionArray[] = Braintree_Subscription::factory($subscription);
+ }
+ }
+
+ $this->_set('subscriptions', $subscriptionArray);
+ $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Base.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Base.php
new file mode 100644
index 0000000..f484af3
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Base.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * Base functionality for library classes
+ */
+abstract class Braintree_Base
+{
+ /**
+ * Disable the default constructor
+ *
+ * Objects that inherit from Braintree_Base should be constructed with
+ * the static factory() method.
+ *
+ * @ignore
+ */
+ protected function __construct()
+ {
+ }
+
+ /**
+ * Disable cloning of objects
+ *
+ * @ignore
+ */
+ protected function __clone()
+ {
+ }
+
+ /**
+ * Accessor for instance properties stored in the private $_attributes property
+ *
+ * @ignore
+ * @param string $name
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ if (array_key_exists($name, $this->_attributes)) {
+ return $this->_attributes[$name];
+ }
+ else {
+ trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE);
+ return null;
+ }
+ }
+
+ /**
+ * Checks for the existance of a property stored in the private $_attributes property
+ *
+ * @ignore
+ * @param string $name
+ * @return boolean
+ */
+ public function __isset($name)
+ {
+ return array_key_exists($name, $this->_attributes);
+ }
+
+ /**
+ * Mutator for instance properties stored in the private $_attributes property
+ *
+ * @ignore
+ * @param string $key
+ * @param mixed $value
+ */
+ public function _set($key, $value)
+ {
+ $this->_attributes[$key] = $value;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientToken.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientToken.php
new file mode 100644
index 0000000..13278da
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientToken.php
@@ -0,0 +1,47 @@
+<?php
+
+class Braintree_ClientToken
+{
+ const DEFAULT_VERSION = 2;
+
+
+ // static methods redirecting to gateway
+
+ /**
+ *
+ * @param array $params
+ * @return array
+ */
+ public static function generate($params=array())
+ {
+ return Braintree_Configuration::gateway()->clientToken()->generate($params);
+ }
+
+ /**
+ *
+ * @param type $params
+ * @throws InvalidArgumentException
+ */
+ public static function conditionallyVerifyKeys($params)
+ {
+ return Braintree_Configuration::gateway()->clientToken()->conditionallyVerifyKeys($params);
+ }
+
+ /**
+ *
+ * @return string client token retrieved from server
+ */
+ public static function generateWithCustomerIdSignature()
+ {
+ return Braintree_Configuration::gateway()->clientToken()->generateWithCustomerIdSignature();
+ }
+
+ /**
+ *
+ * @return string client token retrieved from server
+ */
+ public static function generateWithoutCustomerIdSignature()
+ {
+ return Braintree_Configuration::gateway()->clientToken()->generateWithoutCustomerIdSignature();
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientTokenGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientTokenGateway.php
new file mode 100644
index 0000000..bdeea4d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ClientTokenGateway.php
@@ -0,0 +1,122 @@
+<?php
+
+class Braintree_ClientTokenGateway
+{
+ /**
+ *
+ * @var Braintree_Gateway
+ */
+ private $_gateway;
+
+ /**
+ *
+ * @var Braintree_Configuration
+ */
+ private $_config;
+
+ /**
+ *
+ * @var Braintree_Http
+ */
+ private $_http;
+
+ /**
+ *
+ * @param Braintree_Gateway $gateway
+ */
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function generate($params=array())
+ {
+ if (!array_key_exists("version", $params)) {
+ $params["version"] = Braintree_ClientToken::DEFAULT_VERSION;
+ }
+
+ $this->conditionallyVerifyKeys($params);
+ $generateParams = array("client_token" => $params);
+
+ return $this->_doGenerate('/client_token', $generateParams);
+ }
+
+ /**
+ * sends the generate request to the gateway
+ *
+ * @ignore
+ * @param var $url
+ * @param array $params
+ * @return mixed
+ */
+ public function _doGenerate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ *
+ * @param array $params
+ * @throws InvalidArgumentException
+ */
+ public function conditionallyVerifyKeys($params)
+ {
+ if (array_key_exists("customerId", $params)) {
+ Braintree_Util::verifyKeys($this->generateWithCustomerIdSignature(), $params);
+ } else {
+ Braintree_Util::verifyKeys($this->generateWithoutCustomerIdSignature(), $params);
+ }
+ }
+
+ /**
+ *
+ * @return mixed[]
+ */
+ public function generateWithCustomerIdSignature()
+ {
+ return array("version", "customerId", "proxyMerchantId", array("options" => array("makeDefault", "verifyCard", "failOnDuplicatePaymentMethod")), "merchantAccountId");
+ }
+
+ /**
+ *
+ * @return string[]
+ */
+ public function generateWithoutCustomerIdSignature()
+ {
+ return array("version", "proxyMerchantId", "merchantAccountId");
+ }
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * If the request is successful, returns a client token string.
+ * Otherwise, throws an InvalidArgumentException with the error
+ * response from the Gateway or an HTTP status code exception.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return string client token
+ * @throws InvalidArgumentException | HTTP status code exception
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['clientToken'])) {
+ return $response['clientToken']['value'];
+ } elseif (isset($response['apiErrorResponse'])) {
+ throw new InvalidArgumentException(
+ $response['apiErrorResponse']['message']
+ );
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected clientToken or apiErrorResponse"
+ );
+ }
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CoinbaseAccount.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CoinbaseAccount.php
new file mode 100644
index 0000000..7e839ac
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CoinbaseAccount.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Braintree CoinbaseAccount module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Manages Braintree CoinbaseAccounts
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $token
+ * @property-read string $userId
+ * @property-read string $userName
+ * @property-read string $userEmail
+ */
+class Braintree_CoinbaseAccount extends Braintree_Base
+{
+ /**
+ * factory method: returns an instance of Braintree_CoinbaseAccount
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_CoinbaseAccount
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ /* instance methods */
+
+ /**
+ * returns false if default is null or false
+ *
+ * @return boolean
+ */
+ public function isDefault()
+ {
+ return $this->default;
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @access protected
+ * @param array $coinbaseAccountAttribs array of coinbaseAccount data
+ * @return none
+ */
+ protected function _initialize($coinbaseAccountAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $coinbaseAccountAttribs;
+
+ $subscriptionArray = array();
+ if (isset($coinbaseAccountAttribs['subscriptions'])) {
+ foreach ($coinbaseAccountAttribs['subscriptions'] AS $subscription) {
+ $subscriptionArray[] = Braintree_Subscription::factory($subscription);
+ }
+ }
+
+ $this->_set('subscriptions', $subscriptionArray);
+ }
+
+ /**
+ * create a printable representation of the object as:
+ * ClassName[property=value, property=value]
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function find($token)
+ {
+ return Braintree_Configuration::gateway()->coinbaseAccount()->find($token);
+ }
+
+ public static function update($token, $attributes)
+ {
+ return Braintree_Configuration::gateway()->coinbaseAccount()->update($token, $attributes);
+ }
+
+ public static function delete($token)
+ {
+ return Braintree_Configuration::gateway()->coinbaseAccount()->delete($token);
+ }
+
+ public static function sale($token, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->coinbaseAccount()->sale($token, $transactionAttribs);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Collection.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Collection.php
new file mode 100644
index 0000000..d0637ac
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Collection.php
@@ -0,0 +1,153 @@
+<?php
+/**
+ * Braintree Generic collection
+ *
+ * PHP Version 5
+ *
+ * Based on Generic Collection class from:
+ * {@link http://codeutopia.net/code/library/CU/Collection.php}
+ *
+ * @package Braintree
+ * @subpackage Utility
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+class Braintree_Collection implements Countable, IteratorAggregate, ArrayAccess
+{
+ /**
+ *
+ * @var array $_collection collection storage
+ */
+ protected $_collection = array();
+
+ /**
+ * Add a value into the collection
+ * @param string $value
+ */
+ public function add($value)
+ {
+ $this->_collection[] = $value;
+ }
+
+ /**
+ * Set index's value
+ * @param integer $index
+ * @param mixed $value
+ * @throws OutOfRangeException
+ */
+ public function set($index, $value)
+ {
+ if($index >= $this->count())
+ throw new OutOfRangeException('Index out of range');
+
+ $this->_collection[$index] = $value;
+ }
+
+ /**
+ * Remove a value from the collection
+ * @param integer $index index to remove
+ * @throws OutOfRangeException if index is out of range
+ */
+ public function remove($index)
+ {
+ if($index >= $this->count())
+ throw new OutOfRangeException('Index out of range');
+
+ array_splice($this->_collection, $index, 1);
+ }
+
+ /**
+ * Return value at index
+ * @param integer $index
+ * @return mixed
+ * @throws OutOfRangeException
+ */
+ public function get($index)
+ {
+ if($index >= $this->count())
+ throw new OutOfRangeException('Index out of range');
+
+ return $this->_collection[$index];
+ }
+
+ /**
+ * Determine if index exists
+ * @param integer $index
+ * @return boolean
+ */
+ public function exists($index)
+ {
+ if($index >= $this->count())
+ return false;
+
+ return true;
+ }
+ /**
+ * Return count of items in collection
+ * Implements countable
+ * @return integer
+ */
+ public function count()
+ {
+ return count($this->_collection);
+ }
+
+
+ /**
+ * Return an iterator
+ * Implements IteratorAggregate
+ * @return ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->_collection);
+ }
+
+ /**
+ * Set offset to value
+ * Implements ArrayAccess
+ * @see set
+ * @param integer $offset
+ * @param mixed $value
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->set($offset, $value);
+ }
+
+ /**
+ * Unset offset
+ * Implements ArrayAccess
+ * @see remove
+ * @param integer $offset
+ */
+ public function offsetUnset($offset)
+ {
+ $this->remove($offset);
+ }
+
+ /**
+ * get an offset's value
+ * Implements ArrayAccess
+ * @see get
+ * @param integer $offset
+ * @return mixed
+ */
+ public function offsetGet($offset)
+ {
+ return $this->get($offset);
+ }
+
+ /**
+ * Determine if offset exists
+ * Implements ArrayAccess
+ * @see exists
+ * @param integer $offset
+ * @return boolean
+ */
+ public function offsetExists($offset)
+ {
+ return $this->exists($offset);
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Configuration.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Configuration.php
new file mode 100644
index 0000000..5b167c6
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Configuration.php
@@ -0,0 +1,397 @@
+<?php
+/**
+ *
+ * Configuration registry
+ *
+ * @package Braintree
+ * @subpackage Utility
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+class Braintree_Configuration
+{
+ public static $global;
+
+ private $_environment = null;
+ private $_merchantId = null;
+ private $_publicKey = null;
+ private $_privateKey = null;
+ private $_clientId = null;
+ private $_clientSecret = null;
+ private $_accessToken = null;
+
+ /**
+ * Braintree API version to use
+ * @access public
+ */
+ const API_VERSION = 4;
+
+ public function __construct($attribs = array())
+ {
+ foreach ($attribs as $kind => $value) {
+ if ($kind == 'environment') {
+ Braintree_CredentialsParser::assertValidEnvironment($value);
+ $this->_environment = $value;
+ }
+ if ($kind == 'merchantId') {
+ $this->_merchantId = $value;
+ }
+ if ($kind == 'publicKey') {
+ $this->_publicKey = $value;
+ }
+ if ($kind == 'privateKey') {
+ $this->_privateKey = $value;
+ }
+ }
+
+ if (isset($attribs['clientId']) || isset($attribs['accessToken'])) {
+ if (isset($attribs['environment']) || isset($attribs['merchantId']) || isset($attribs['publicKey']) || isset($attribs['privateKey'])) {
+ throw new Braintree_Exception_Configuration('Cannot mix OAuth credentials (clientId, clientSecret, accessToken) with key credentials (publicKey, privateKey, environment, merchantId).');
+ }
+ $parsedCredentials = new Braintree_CredentialsParser($attribs);
+
+ $this->_environment = $parsedCredentials->getEnvironment();
+ $this->_merchantId = $parsedCredentials->getMerchantId();
+ $this->_clientId = $parsedCredentials->getClientId();
+ $this->_clientSecret = $parsedCredentials->getClientSecret();
+ $this->_accessToken = $parsedCredentials->getAccessToken();
+ }
+ }
+
+ /**
+ * resets configuration to default
+ * @access public
+ */
+ public static function reset()
+ {
+ self::$global = new Braintree_Configuration();
+ }
+
+ public static function gateway()
+ {
+ return new Braintree_Gateway(self::$global);
+ }
+
+ public static function environment($value=null)
+ {
+ if (empty($value)) {
+ return self::$global->getEnvironment();
+ }
+ Braintree_CredentialsParser::assertValidEnvironment($value);
+ self::$global->setEnvironment($value);
+ }
+
+ public static function merchantId($value=null)
+ {
+ if (empty($value)) {
+ return self::$global->getMerchantId();
+ }
+ self::$global->setMerchantId($value);
+ }
+
+ public static function publicKey($value=null)
+ {
+ if (empty($value)) {
+ return self::$global->getPublicKey();
+ }
+ self::$global->setPublicKey($value);
+ }
+
+ public static function privateKey($value=null)
+ {
+ if (empty($value)) {
+ return self::$global->getPrivateKey();
+ }
+ self::$global->setPrivateKey($value);
+ }
+
+ public static function assertGlobalHasAccessTokenOrKeys()
+ {
+ self::$global->assertHasAccessTokenOrKeys();
+ }
+
+ public function assertHasAccessTokenOrKeys()
+ {
+ if (empty($this->_accessToken)) {
+ if (empty($this->_merchantId)) {
+ throw new Braintree_Exception_Configuration('Braintree_Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree_Gateway).');
+ } else if (empty($this->_environment)) {
+ throw new Braintree_Exception_Configuration('Braintree_Configuration::environment needs to be set.');
+ } else if (empty($this->_publicKey)) {
+ throw new Braintree_Exception_Configuration('Braintree_Configuration::publicKey needs to be set.');
+ } else if (empty($this->_privateKey)) {
+ throw new Braintree_Exception_Configuration('Braintree_Configuration::privateKey needs to be set.');
+ }
+ }
+ }
+
+ public function assertHasClientCredentials()
+ {
+ $this->assertHasClientId();
+ $this->assertHasClientSecret();
+ }
+
+ public function assertHasClientId()
+ {
+ if (empty($this->_clientId)) {
+ throw new Braintree_Exception_Configuration('clientId needs to be passed to Braintree_Gateway.');
+ }
+ }
+
+ public function assertHasClientSecret()
+ {
+ if (empty($this->_clientSecret)) {
+ throw new Braintree_Exception_Configuration('clientSecret needs to be passed to Braintree_Gateway.');
+ }
+ }
+
+ public function getEnvironment()
+ {
+ return $this->_environment;
+ }
+
+ /**
+ * Do not use this method directly. Pass in the environment to the constructor.
+ */
+ public function setEnvironment($value)
+ {
+ $this->_environment = $value;
+ }
+
+ public function getMerchantId()
+ {
+ return $this->_merchantId;
+ }
+
+ /**
+ * Do not use this method directly. Pass in the merchantId to the constructor.
+ */
+ public function setMerchantId($value)
+ {
+ $this->_merchantId = $value;
+ }
+
+ public function getPublicKey()
+ {
+ return $this->_publicKey;
+ }
+
+ public function getClientId()
+ {
+ return $this->_clientId;
+ }
+
+ /**
+ * Do not use this method directly. Pass in the publicKey to the constructor.
+ */
+ public function setPublicKey($value)
+ {
+ $this->_publicKey = $value;
+ }
+
+ public function getPrivateKey()
+ {
+ return $this->_privateKey;
+ }
+
+ public function getClientSecret()
+ {
+ return $this->_clientSecret;
+ }
+
+ /**
+ * Do not use this method directly. Pass in the privateKey to the constructor.
+ */
+ public function setPrivateKey($value)
+ {
+ $this->_privateKey = $value;
+ }
+
+ public function getAccessToken()
+ {
+ return $this->_accessToken;
+ }
+
+ public function isAccessToken()
+ {
+ return !empty($this->_accessToken);
+ }
+
+ public function isClientCredentials()
+ {
+ return !empty($this->_clientId);
+ }
+ /**
+ * returns the base braintree gateway URL based on config values
+ *
+ * @access public
+ * @param none
+ * @return string braintree gateway URL
+ */
+ public function baseUrl()
+ {
+ static $defaultPorts = array(
+ 'http' => 80,
+ 'https' => 443,
+ );
+
+ if ($this->portNumber() === $defaultPorts[$this->protocol()]) {
+ return sprintf('%s://%s', $this->protocol(), $this->serverName());
+ } else {
+ return sprintf('%s://%s:%d', $this->protocol(), $this->serverName(), $this->portNumber());
+ }
+ }
+
+ /**
+ * sets the merchant path based on merchant ID
+ *
+ * @access protected
+ * @param none
+ * @return string merchant path uri
+ */
+ public function merchantPath()
+ {
+ return '/merchants/'.$this->_merchantId;
+ }
+
+ /**
+ * sets the physical path for the location of the CA certs
+ *
+ * @access public
+ * @param none
+ * @return string filepath
+ */
+ public function caFile($sslPath = NULL)
+ {
+ $sslPath = $sslPath ? $sslPath : DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR .
+ 'ssl' . DIRECTORY_SEPARATOR;
+
+ $caPath = realpath(
+ dirname(__FILE__) .
+ $sslPath . 'api_braintreegateway_com.ca.crt'
+ );
+
+ if (!file_exists($caPath))
+ {
+ throw new Braintree_Exception_SSLCaFileNotFound();
+ }
+
+ return $caPath;
+ }
+
+ /**
+ * returns the port number depending on environment
+ *
+ * @access public
+ * @param none
+ * @return int portnumber
+ */
+ public function portNumber()
+ {
+ if ($this->sslOn()) {
+ return 443;
+ }
+ return getenv("GATEWAY_PORT") ? getenv("GATEWAY_PORT") : 3000;
+ }
+
+ /**
+ * returns http protocol depending on environment
+ *
+ * @access public
+ * @param none
+ * @return string http || https
+ */
+ public function protocol()
+ {
+ return $this->sslOn() ? 'https' : 'http';
+ }
+
+ /**
+ * returns gateway server name depending on environment
+ *
+ * @access public
+ * @param none
+ * @return string server domain name
+ */
+ public function serverName()
+ {
+ switch($this->_environment) {
+ case 'production':
+ $serverName = 'api.braintreegateway.com';
+ break;
+ case 'qa':
+ $serverName = 'gateway.qa.braintreepayments.com';
+ break;
+ case 'sandbox':
+ $serverName = 'api.sandbox.braintreegateway.com';
+ break;
+ case 'development':
+ case 'integration':
+ default:
+ $serverName = 'localhost';
+ break;
+ }
+
+ return $serverName;
+ }
+
+ public function authUrl()
+ {
+ switch($this->_environment) {
+ case 'production':
+ $serverName = 'https://auth.venmo.com';
+ break;
+ case 'qa':
+ $serverName = 'https://auth.qa.venmo.com';
+ break;
+ case 'sandbox':
+ $serverName = 'https://auth.sandbox.venmo.com';
+ break;
+ case 'development':
+ case 'integration':
+ default:
+ $serverName = 'http://auth.venmo.dev:9292';
+ break;
+ }
+
+ return $serverName;
+ }
+
+ /**
+ * returns boolean indicating SSL is on or off for this session,
+ * depending on environment
+ *
+ * @access public
+ * @param none
+ * @return boolean
+ */
+ public function sslOn()
+ {
+ switch($this->_environment) {
+ case 'integration':
+ case 'development':
+ $ssl = false;
+ break;
+ case 'production':
+ case 'qa':
+ case 'sandbox':
+ default:
+ $ssl = true;
+ break;
+ }
+
+ return $ssl;
+ }
+
+ /**
+ * log message to default logger
+ *
+ * @param string $message
+ *
+ */
+ public function logMessage($message)
+ {
+ error_log('[Braintree] ' . $message);
+ }
+}
+Braintree_Configuration::reset();
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CredentialsParser.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CredentialsParser.php
new file mode 100644
index 0000000..d2f1018
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CredentialsParser.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ *
+ * CredentialsParser registry
+ *
+ * @package Braintree
+ * @subpackage Utility
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+class Braintree_CredentialsParser
+{
+ private $_clientId;
+ private $_clientSecret;
+ private $_accessToken;
+ private $_environment;
+ private $_merchantId;
+
+ public function __construct($attribs)
+ {
+ foreach ($attribs as $kind => $value) {
+ if ($kind == 'clientId') {
+ $this->_clientId = $value;
+ }
+ if ($kind == 'clientSecret') {
+ $this->_clientSecret = $value;
+ }
+ if ($kind == 'accessToken') {
+ $this->_accessToken = $value;
+ }
+ }
+ $this->parse();
+ }
+
+ /**
+ *
+ * @access protected
+ * @static
+ * @var array valid environments, used for validation
+ */
+ private static $_validEnvironments = array(
+ 'development',
+ 'integration',
+ 'sandbox',
+ 'production',
+ 'qa',
+ );
+
+
+ public function parse()
+ {
+ $environments = array();
+ if (!empty($this->_clientId)) {
+ $environments[] = array('clientId', $this->_parseClientCredential('clientId', $this->_clientId, 'client_id'));
+ }
+ if (!empty($this->_clientSecret)) {
+ $environments[] = array('clientSecret', $this->_parseClientCredential('clientSecret', $this->_clientSecret, 'client_secret'));
+ }
+ if (!empty($this->_accessToken)) {
+ $environments[] = array('accessToken', $this->_parseAccessToken());
+ }
+
+ $checkEnv = $environments[0];
+ foreach ($environments as $env) {
+ if ($env[1] !== $checkEnv[1]) {
+ throw new Braintree_Exception_Configuration(
+ 'Mismatched credential environments: ' . $checkEnv[0] . ' environment is ' . $checkEnv[1] .
+ ' and ' . $env[0] . ' environment is ' . $env[1]);
+ }
+ }
+
+ self::assertValidEnvironment($checkEnv[1]);
+ $this->_environment = $checkEnv[1];
+ }
+
+ public static function assertValidEnvironment($environment) {
+ if (!in_array($environment, self::$_validEnvironments)) {
+ throw new Braintree_Exception_Configuration('"' .
+ $environment . '" is not a valid environment.');
+ }
+ }
+
+ private function _parseClientCredential($credentialType, $value, $expectedValuePrefix)
+ {
+ $explodedCredential = explode('$', $value);
+ if (sizeof($explodedCredential) != 3) {
+ throw new Braintree_Exception_Configuration('Incorrect ' . $credentialType . ' format. Expected: type$environment$token');
+ }
+
+ $gotValuePrefix = $explodedCredential[0];
+ $environment = $explodedCredential[1];
+ $token = $explodedCredential[2];
+
+ if ($gotValuePrefix != $expectedValuePrefix) {
+ throw new Braintree_Exception_Configuration('Value passed for ' . $credentialType . ' is not a ' . $credentialType);
+ }
+
+ return $environment;
+ }
+
+ private function _parseAccessToken()
+ {
+ $accessTokenExploded = explode('$', $this->_accessToken);
+ if (sizeof($accessTokenExploded) != 4) {
+ throw new Braintree_Exception_Configuration('Incorrect accessToken syntax. Expected: type$environment$merchant_id$token');
+ }
+
+ $gotValuePrefix = $accessTokenExploded[0];
+ $environment = $accessTokenExploded[1];
+ $merchantId = $accessTokenExploded[2];
+ $token = $accessTokenExploded[3];
+
+ if ($gotValuePrefix != 'access_token') {
+ throw new Braintree_Exception_Configuration('Value passed for accessToken is not an accessToken');
+ }
+
+ $this->_merchantId = $merchantId;
+ return $environment;
+ }
+
+ public function getClientId()
+ {
+ return $this->_clientId;
+ }
+
+ public function getClientSecret()
+ {
+ return $this->_clientSecret;
+ }
+
+ public function getAccessToken()
+ {
+ return $this->_accessToken;
+ }
+
+ public function getEnvironment()
+ {
+ return $this->_environment;
+ }
+
+ public function getMerchantId()
+ {
+ return $this->_merchantId;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCard.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCard.php
new file mode 100644
index 0000000..7763b5b
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCard.php
@@ -0,0 +1,311 @@
+<?php
+/**
+ * Braintree CreditCard module
+ * Creates and manages Braintree CreditCards
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on CreditCards, see {@link http://www.braintreepayments.com/gateway/credit-card-api http://www.braintreepaymentsolutions.com/gateway/credit-card-api}<br />
+ * For more detailed information on CreditCard verifications, see {@link http://www.braintreepayments.com/gateway/credit-card-verification-api http://www.braintreepaymentsolutions.com/gateway/credit-card-verification-api}
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $billingAddress
+ * @property-read string $bin
+ * @property-read string $cardType
+ * @property-read string $cardholderName
+ * @property-read string $createdAt
+ * @property-read string $customerId
+ * @property-read string $expirationDate
+ * @property-read string $expirationMonth
+ * @property-read string $expirationYear
+ * @property-read string $imageUrl
+ * @property-read string $last4
+ * @property-read string $maskedNumber
+ * @property-read string $token
+ * @property-read string $updatedAt
+ */
+class Braintree_CreditCard extends Braintree_Base
+{
+ // Card Type
+ const AMEX = 'American Express';
+ const CARTE_BLANCHE = 'Carte Blanche';
+ const CHINA_UNION_PAY = 'China UnionPay';
+ const DINERS_CLUB_INTERNATIONAL = 'Diners Club';
+ const DISCOVER = 'Discover';
+ const JCB = 'JCB';
+ const LASER = 'Laser';
+ const MAESTRO = 'Maestro';
+ const MASTER_CARD = 'MasterCard';
+ const SOLO = 'Solo';
+ const SWITCH_TYPE = 'Switch';
+ const VISA = 'Visa';
+ const UNKNOWN = 'Unknown';
+
+ // Credit card origination location
+ const INTERNATIONAL = "international";
+ const US = "us";
+
+ const PREPAID_YES = 'Yes';
+ const PREPAID_NO = 'No';
+ const PREPAID_UNKNOWN = 'Unknown';
+
+ const PAYROLL_YES = 'Yes';
+ const PAYROLL_NO = 'No';
+ const PAYROLL_UNKNOWN = 'Unknown';
+
+ const HEALTHCARE_YES = 'Yes';
+ const HEALTHCARE_NO = 'No';
+ const HEALTHCARE_UNKNOWN = 'Unknown';
+
+ const DURBIN_REGULATED_YES = 'Yes';
+ const DURBIN_REGULATED_NO = 'No';
+ const DURBIN_REGULATED_UNKNOWN = 'Unknown';
+
+ const DEBIT_YES = 'Yes';
+ const DEBIT_NO = 'No';
+ const DEBIT_UNKNOWN = 'Unknown';
+
+ const COMMERCIAL_YES = 'Yes';
+ const COMMERCIAL_NO = 'No';
+ const COMMERCIAL_UNKNOWN = 'Unknown';
+
+ const COUNTRY_OF_ISSUANCE_UNKNOWN = "Unknown";
+ const ISSUING_BANK_UNKNOWN = "Unknown";
+
+ /* instance methods */
+ /**
+ * returns false if default is null or false
+ *
+ * @return boolean
+ */
+ public function isDefault()
+ {
+ return $this->default;
+ }
+
+ /**
+ * checks whether the card is expired based on the current date
+ *
+ * @return boolean
+ */
+ public function isExpired()
+ {
+ return $this->expired;
+ }
+
+ /**
+ * checks whether the card is associated with venmo sdk
+ *
+ * @return boolean
+ */
+ public function isVenmoSdk()
+ {
+ return $this->venmoSdk;
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @access protected
+ * @param array $creditCardAttribs array of creditcard data
+ * @return none
+ */
+ protected function _initialize($creditCardAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $creditCardAttribs;
+
+ // map each address into its own object
+ $billingAddress = isset($creditCardAttribs['billingAddress']) ?
+ Braintree_Address::factory($creditCardAttribs['billingAddress']) :
+ null;
+
+ $subscriptionArray = array();
+ if (isset($creditCardAttribs['subscriptions'])) {
+ foreach ($creditCardAttribs['subscriptions'] AS $subscription) {
+ $subscriptionArray[] = Braintree_Subscription::factory($subscription);
+ }
+ }
+
+ $this->_set('subscriptions', $subscriptionArray);
+ $this->_set('billingAddress', $billingAddress);
+ $this->_set('expirationDate', $this->expirationMonth . '/' . $this->expirationYear);
+ $this->_set('maskedNumber', $this->bin . '******' . $this->last4);
+
+ if(isset($creditCardAttribs['verifications']) && count($creditCardAttribs['verifications']) > 0) {
+ $verifications = $creditCardAttribs['verifications'];
+ usort($verifications, array($this, '_compareCreatedAtOnVerifications'));
+
+ $this->_set('verification', Braintree_CreditCardVerification::factory($verifications[0]));
+ }
+ }
+
+ private function _compareCreatedAtOnVerifications($verificationAttrib1, $verificationAttrib2)
+ {
+ return ($verificationAttrib2['createdAt'] < $verificationAttrib1['createdAt']) ? -1 : 1;
+ }
+
+ /**
+ * returns false if comparing object is not a Braintree_CreditCard,
+ * or is a Braintree_CreditCard with a different id
+ *
+ * @param object $otherCreditCard customer to compare against
+ * @return boolean
+ */
+ public function isEqual($otherCreditCard)
+ {
+ return !($otherCreditCard instanceof Braintree_CreditCard) ? false : $this->token === $otherCreditCard->token;
+ }
+
+ /**
+ * create a printable representation of the object as:
+ * ClassName[property=value, property=value]
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+ /**
+ * factory method: returns an instance of Braintree_CreditCard
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_CreditCard
+ */
+ public static function factory($attributes)
+ {
+ $defaultAttributes = array(
+ 'bin' => '',
+ 'expirationMonth' => '',
+ 'expirationYear' => '',
+ 'last4' => '',
+ );
+
+ $instance = new self();
+ $instance->_initialize(array_merge($defaultAttributes, $attributes));
+ return $instance;
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function create($attribs)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->create($attribs);
+ }
+
+ public static function createNoValidate($attribs)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->createNoValidate($attribs);
+ }
+
+ public static function createFromTransparentRedirect($queryString)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->createFromTransparentRedirect($queryString);
+ }
+
+ public static function createCreditCardUrl()
+ {
+ return Braintree_Configuration::gateway()->creditCard()->createCreditCardUrl();
+ }
+
+ public static function expired()
+ {
+ return Braintree_Configuration::gateway()->creditCard()->expired();
+ }
+
+ public static function fetchExpired($ids)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->fetchExpired($ids);
+ }
+
+ public static function expiringBetween($startDate, $endDate)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->expiringBetween($startDate, $endDate);
+ }
+
+ public static function fetchExpiring($startDate, $endDate, $ids)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->fetchExpiring($startDate, $endDate, $ids);
+ }
+
+ public static function find($token)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->find($token);
+ }
+
+ public static function fromNonce($nonce)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->fromNonce($nonce);
+ }
+
+ public static function credit($token, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->credit($token, $transactionAttribs);
+ }
+
+ public static function creditNoValidate($token, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->creditNoValidate($token, $transactionAttribs);
+ }
+
+ public static function sale($token, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->sale($token, $transactionAttribs);
+ }
+
+ public static function saleNoValidate($token, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->saleNoValidate($token, $transactionAttribs);
+ }
+
+ public static function update($token, $attributes)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->update($token, $attributes);
+ }
+
+ public static function updateNoValidate($token, $attributes)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->updateNoValidate($token, $attributes);
+ }
+
+ public static function updateCreditCardUrl()
+ {
+ return Braintree_Configuration::gateway()->creditCard()->updateCreditCardUrl();
+ }
+
+ public static function updateFromTransparentRedirect($queryString)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->updateFromTransparentRedirect($queryString);
+ }
+
+ public static function delete($token)
+ {
+ return Braintree_Configuration::gateway()->creditCard()->delete($token);
+ }
+
+ public static function allCardTypes()
+ {
+ return array(
+ Braintree_CreditCard::AMEX,
+ Braintree_CreditCard::CARTE_BLANCHE,
+ Braintree_CreditCard::CHINA_UNION_PAY,
+ Braintree_CreditCard::DINERS_CLUB_INTERNATIONAL,
+ Braintree_CreditCard::DISCOVER,
+ Braintree_CreditCard::JCB,
+ Braintree_CreditCard::LASER,
+ Braintree_CreditCard::MAESTRO,
+ Braintree_CreditCard::MASTER_CARD,
+ Braintree_CreditCard::SOLO,
+ Braintree_CreditCard::SWITCH_TYPE,
+ Braintree_CreditCard::VISA,
+ Braintree_CreditCard::UNKNOWN
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardGateway.php
new file mode 100644
index 0000000..a93846a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardGateway.php
@@ -0,0 +1,472 @@
+<?php
+/**
+ * Braintree CreditCardGateway module
+ * Creates and manages Braintree CreditCards
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on CreditCards, see {@link http://www.braintreepayments.com/gateway/credit-card-api http://www.braintreepaymentsolutions.com/gateway/credit-card-api}<br />
+ * For more detailed information on CreditCard verifications, see {@link http://www.braintreepayments.com/gateway/credit-card-verification-api http://www.braintreepaymentsolutions.com/gateway/credit-card-verification-api}
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_CreditCardGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function create($attribs)
+ {
+ Braintree_Util::verifyKeys(self::createSignature(), $attribs);
+ return $this->_doCreate('/payment_methods', array('credit_card' => $attribs));
+ }
+
+ /**
+ * attempts the create operation assuming all data will validate
+ * returns a Braintree_CreditCard object instead of a Result
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ * @throws Braintree_Exception_ValidationError
+ */
+ public function createNoValidate($attribs)
+ {
+ $result = $this->create($attribs);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+ /**
+ * create a customer from a TransparentRedirect operation
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ */
+ public function createFromTransparentRedirect($queryString)
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
+ $params = Braintree_TransparentRedirect::parseAndValidateQueryString(
+ $queryString
+ );
+ return $this->_doCreate(
+ '/payment_methods/all/confirm_transparent_redirect_request',
+ array('id' => $params['id'])
+ );
+ }
+
+ /**
+ *
+ * @access public
+ * @param none
+ * @return string
+ */
+ public function createCreditCardUrl()
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
+ return $this->_config->baseUrl() . $this->_config->merchantPath() .
+ '/payment_methods/all/create_via_transparent_redirect_request';
+ }
+
+ /**
+ * returns a ResourceCollection of expired credit cards
+ * @return object ResourceCollection
+ */
+ public function expired()
+ {
+ $path = $this->_config->merchantPath() . '/payment_methods/all/expired_ids';
+ $response = $this->_http->post($path);
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetchExpired',
+ 'methodArgs' => array()
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ }
+
+ public function fetchExpired($ids)
+ {
+ $path = $this->_config->merchantPath() . "/payment_methods/all/expired";
+ $response = $this->_http->post($path, array('search' => array('ids' => $ids)));
+
+ return Braintree_Util::extractattributeasarray(
+ $response['paymentMethods'],
+ 'creditCard'
+ );
+ }
+ /**
+ * returns a ResourceCollection of credit cards expiring between start/end
+ *
+ * @return object ResourceCollection
+ */
+ public function expiringBetween($startDate, $endDate)
+ {
+ $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring_ids?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate);
+ $response = $this->_http->post($queryPath);
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetchExpiring',
+ 'methodArgs' => array($startDate, $endDate)
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ }
+
+ public function fetchExpiring($startDate, $endDate, $ids)
+ {
+ $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate);
+ $response = $this->_http->post($queryPath, array('search' => array('ids' => $ids)));
+
+ return Braintree_Util::extractAttributeAsArray(
+ $response['paymentMethods'],
+ 'creditCard'
+ );
+ }
+
+ /**
+ * find a creditcard by token
+ *
+ * @access public
+ * @param string $token credit card unique id
+ * @return object Braintree_CreditCard
+ * @throws Braintree_Exception_NotFound
+ */
+ public function find($token)
+ {
+ $this->_validateId($token);
+ try {
+ $path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token;
+ $response = $this->_http->get($path);
+ return Braintree_CreditCard::factory($response['creditCard']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'credit card with token ' . $token . ' not found'
+ );
+ }
+
+ }
+
+ /**
+ * Convert a payment method nonce to a credit card
+ *
+ * @access public
+ * @param string $nonce payment method nonce
+ * @return object Braintree_CreditCard
+ * @throws Braintree_Exception_NotFound
+ */
+ public function fromNonce($nonce)
+ {
+ $this->_validateId($nonce, "nonce");
+ try {
+ $path = $this->_config->merchantPath() . '/payment_methods/from_nonce/' . $nonce;
+ $response = $this->_http->get($path);
+ return Braintree_CreditCard::factory($response['creditCard']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'credit card with nonce ' . $nonce . ' locked, consumed or not found'
+ );
+ }
+
+ }
+
+ /**
+ * create a credit on the card for the passed transaction
+ *
+ * @access public
+ * @param array $attribs
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ */
+ public function credit($token, $transactionAttribs)
+ {
+ $this->_validateId($token);
+ return Braintree_Transaction::credit(
+ array_merge(
+ $transactionAttribs,
+ array('paymentMethodToken' => $token)
+ )
+ );
+ }
+
+ /**
+ * create a credit on this card, assuming validations will pass
+ *
+ * returns a Braintree_Transaction object on success
+ *
+ * @access public
+ * @param array $attribs
+ * @return object Braintree_Transaction
+ * @throws Braintree_Exception_ValidationError
+ */
+ public function creditNoValidate($token, $transactionAttribs)
+ {
+ $result = $this->credit($token, $transactionAttribs);
+ return Braintree_Util::returnObjectOrThrowException('Transaction', $result);
+ }
+
+ /**
+ * create a new sale for the current card
+ *
+ * @param string $token
+ * @param array $transactionAttribs
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ * @see Braintree_Transaction::sale()
+ */
+ public function sale($token, $transactionAttribs)
+ {
+ $this->_validateId($token);
+ return Braintree_Transaction::sale(
+ array_merge(
+ $transactionAttribs,
+ array('paymentMethodToken' => $token)
+ )
+ );
+ }
+
+ /**
+ * create a new sale using this card, assuming validations will pass
+ *
+ * returns a Braintree_Transaction object on success
+ *
+ * @access public
+ * @param array $transactionAttribs
+ * @param string $token
+ * @return object Braintree_Transaction
+ * @throws Braintree_Exception_ValidationsFailed
+ * @see Braintree_Transaction::sale()
+ */
+ public function saleNoValidate($token, $transactionAttribs)
+ {
+ $result = $this->sale($token, $transactionAttribs);
+ return Braintree_Util::returnObjectOrThrowException('Transaction', $result);
+ }
+
+ /**
+ * updates the creditcard record
+ *
+ * if calling this method in context, $token
+ * is the 2nd attribute. $token is not sent in object context.
+ *
+ * @access public
+ * @param array $attributes
+ * @param string $token (optional)
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ */
+ public function update($token, $attributes)
+ {
+ Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
+ $this->_validateId($token);
+ return $this->_doUpdate('put', '/payment_methods/credit_card/' . $token, array('creditCard' => $attributes));
+ }
+
+ /**
+ * update a creditcard record, assuming validations will pass
+ *
+ * if calling this method in context, $token
+ * is the 2nd attribute. $token is not sent in object context.
+ * returns a Braintree_CreditCard object on success
+ *
+ * @access public
+ * @param array $attributes
+ * @param string $token
+ * @return object Braintree_CreditCard
+ * @throws Braintree_Exception_ValidationsFailed
+ */
+ public function updateNoValidate($token, $attributes)
+ {
+ $result = $this->update($token, $attributes);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+ /**
+ *
+ * @access public
+ * @param none
+ * @return string
+ */
+ public function updateCreditCardUrl()
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
+ return $this->_config->baseUrl() . $this->_config->merchantPath() .
+ '/payment_methods/all/update_via_transparent_redirect_request';
+ }
+
+ /**
+ * update a customer from a TransparentRedirect operation
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ */
+ public function updateFromTransparentRedirect($queryString)
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
+ $params = Braintree_TransparentRedirect::parseAndValidateQueryString(
+ $queryString
+ );
+ return $this->_doUpdate(
+ 'post',
+ '/payment_methods/all/confirm_transparent_redirect_request',
+ array('id' => $params['id'])
+ );
+ }
+
+ public function delete($token)
+ {
+ $this->_validateId($token);
+ $path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token;
+ $this->_http->delete($path);
+ return new Braintree_Result_Successful();
+ }
+
+ private static function baseOptions()
+ {
+ return array('makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession');
+ }
+
+ private static function baseSignature($options)
+ {
+ return array(
+ 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId',
+ 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode',
+ 'deviceData', 'fraudMerchantId', 'paymentMethodNonce',
+ array('options' => $options),
+ array(
+ 'billingAddress' => array(
+ 'firstName',
+ 'lastName',
+ 'company',
+ 'countryCodeAlpha2',
+ 'countryCodeAlpha3',
+ 'countryCodeNumeric',
+ 'countryName',
+ 'extendedAddress',
+ 'locality',
+ 'region',
+ 'postalCode',
+ 'streetAddress'
+ ),
+ ),
+ );
+ }
+
+ public static function createSignature()
+ {
+ $options = self::baseOptions();
+ $options[] = "failOnDuplicatePaymentMethod";
+ $signature = self::baseSignature($options);
+ $signature[] = 'customerId';
+ return $signature;
+ }
+
+ public static function updateSignature()
+ {
+ $signature = self::baseSignature(self::baseOptions());
+
+ $updateExistingBillingSignature = array(
+ array(
+ 'options' => array(
+ 'updateExisting'
+ )
+ )
+ );
+
+ foreach($signature AS $key => $value) {
+ if(is_array($value) and array_key_exists('billingAddress', $value)) {
+ $signature[$key]['billingAddress'] = array_merge_recursive($value['billingAddress'], $updateExistingBillingSignature);
+ }
+ }
+
+ return $signature;
+ }
+
+ /**
+ * sends the create request to the gateway
+ *
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ public function _doCreate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * verifies that a valid credit card identifier is being used
+ * @ignore
+ * @param string $identifier
+ * @param Optional $string $identifierType type of identifier supplied, default "token"
+ * @throws InvalidArgumentException
+ */
+ private function _validateId($identifier = null, $identifierType = "token")
+ {
+ if (empty($identifier)) {
+ throw new InvalidArgumentException(
+ 'expected credit card id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
+ throw new InvalidArgumentException(
+ $identifier . ' is an invalid credit card ' . $identifierType . '.'
+ );
+ }
+ }
+
+ /**
+ * sends the update request to the gateway
+ *
+ * @ignore
+ * @param string $url
+ * @param array $params
+ * @return mixed
+ */
+ private function _doUpdate($httpVerb, $subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->$httpVerb($fullPath, $params);
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * creates a new Braintree_CreditCard object and encapsulates
+ * it inside a Braintree_Result_Successful object, or
+ * encapsulates a Braintree_Errors object inside a Result_Error
+ * alternatively, throws an Unexpected exception if the response is invalid.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return object Result_Successful or Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['creditCard'])) {
+ // return a populated instance of Braintree_Address
+ return new Braintree_Result_Successful(
+ Braintree_CreditCard::factory($response['creditCard'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected address or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerification.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerification.php
new file mode 100644
index 0000000..f344eb1
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerification.php
@@ -0,0 +1,22 @@
+<?php
+class Braintree_CreditCardVerification extends Braintree_Result_CreditCardVerification
+{
+ public static function factory($attributes)
+ {
+ $instance = new self($attributes);
+ return $instance;
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function fetch($query, $ids)
+ {
+ return Braintree_Configuration::gateway()->creditCardVerification()->fetch($query, $ids);
+ }
+
+ public static function search($query)
+ {
+ return Braintree_Configuration::gateway()->creditCardVerification()->search($query);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationGateway.php
new file mode 100644
index 0000000..ac54620
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationGateway.php
@@ -0,0 +1,49 @@
+<?php
+class Braintree_CreditCardVerificationGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function fetch($query, $ids)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+ $criteria["ids"] = Braintree_CreditCardVerificationSearch::ids()->in($ids)->toparam();
+ $path = $this->_config->merchantPath() . '/verifications/advanced_search';
+ $response = $this->_http->post($path, array('search' => $criteria));
+
+ return Braintree_Util::extractattributeasarray(
+ $response['creditCardVerifications'],
+ 'verification'
+ );
+ }
+
+ public function search($query)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+
+ $path = $this->_config->merchantPath() . '/verifications/advanced_search_ids';
+ $response = $this->_http->post($path, array('search' => $criteria));
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetch',
+ 'methodArgs' => array($query)
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationSearch.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationSearch.php
new file mode 100644
index 0000000..faaec71
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CreditCardVerificationSearch.php
@@ -0,0 +1,53 @@
+<?php
+class Braintree_CreditCardVerificationSearch
+{
+ static function id() {
+ return new Braintree_TextNode('id');
+ }
+
+ static function creditCardCardholderName() {
+ return new Braintree_TextNode('credit_card_cardholder_name');
+ }
+
+ static function billingAddressDetailsPostalCode() {
+ return new Braintree_TextNode('billing_address_details_postal_code');
+ }
+
+ static function customerEmail() {
+ return new Braintree_TextNode('customer_email');
+ }
+
+ static function customerId() {
+ return new Braintree_TextNode('customer_id');
+ }
+
+ static function paymentMethodToken(){
+ return new Braintree_TextNode('payment_method_token');
+ }
+
+ static function creditCardExpirationDate() {
+ return new Braintree_EqualityNode('credit_card_expiration_date');
+ }
+
+ static function creditCardNumber() {
+ return new Braintree_PartialMatchNode('credit_card_number');
+ }
+
+ static function ids() {
+ return new Braintree_MultipleValueNode('ids');
+ }
+
+ static function createdAt() {
+ return new Braintree_RangeNode("created_at");
+ }
+
+ static function creditCardCardType()
+ {
+ return new Braintree_MultipleValueNode("credit_card_card_type", Braintree_CreditCard::allCardTypes());
+ }
+
+ static function status()
+ {
+ return new Braintree_MultipleValueNode("status", Braintree_Result_CreditCardVerification::allStatuses());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Customer.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Customer.php
new file mode 100644
index 0000000..f3a5da7
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Customer.php
@@ -0,0 +1,373 @@
+<?php
+/**
+ * Braintree Customer module
+ * Creates and manages Customers
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Customers, see {@link http://www.braintreepayments.com/gateway/customer-api http://www.braintreepaymentsolutions.com/gateway/customer-api}
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read array $addresses
+ * @property-read array $paymentMethods
+ * @property-read string $company
+ * @property-read string $createdAt
+ * @property-read array $creditCards
+ * @property-read array $paypalAccounts
+ * @property-read array $applePayCards
+ * @property-read array $coinbaseAccounts
+ * @property-read array $customFields custom fields passed with the request
+ * @property-read string $email
+ * @property-read string $fax
+ * @property-read string $firstName
+ * @property-read string $id
+ * @property-read string $lastName
+ * @property-read string $phone
+ * @property-read string $updatedAt
+ * @property-read string $website
+ */
+class Braintree_Customer extends Braintree_Base
+{
+ /**
+ *
+ * @return Braintree_Customer[]
+ */
+ public static function all()
+ {
+ return Braintree_Configuration::gateway()->customer()->all();
+ }
+
+ /**
+ *
+ * @param string $query
+ * @param int[] $ids
+ * @return Braintree_Customer|Braintree_Customer[]
+ */
+ public static function fetch($query, $ids)
+ {
+ return Braintree_Configuration::gateway()->customer()->fetch($query, $ids);
+ }
+
+ /**
+ *
+ * @param array $attribs
+ * @return Braintree_Customer
+ */
+ public static function create($attribs = array())
+ {
+ return Braintree_Configuration::gateway()->customer()->create($attribs);
+ }
+
+ /**
+ *
+ * @param array $attribs
+ * @return Braintree_Customer
+ */
+ public static function createNoValidate($attribs = array())
+ {
+ return Braintree_Configuration::gateway()->customer()->createNoValidate($attribs);
+ }
+
+ /**
+ * @deprecated since version 2.3.0
+ * @param string $queryString
+ * @return Braintree_Result_Successful
+ */
+ public static function createFromTransparentRedirect($queryString)
+ {
+ return Braintree_Configuration::gateway()->customer()->createFromTransparentRedirect($queryString);
+ }
+
+ /**
+ * @deprecated since version 2.3.0
+ * @return string
+ */
+ public static function createCustomerUrl()
+ {
+ return Braintree_Configuration::gateway()->customer()->createCustomerUrl();
+ }
+
+ /**
+ *
+ * @throws Braintree_Exception_NotFound
+ * @param int $id
+ * @return Braintree_Customer
+ */
+ public static function find($id)
+ {
+ return Braintree_Configuration::gateway()->customer()->find($id);
+ }
+
+ /**
+ *
+ * @param int $customerId
+ * @param array $transactionAttribs
+ * @return Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public static function credit($customerId, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->customer()->credit($customerId, $transactionAttribs);
+ }
+
+ /**
+ *
+ * @throws Braintree_Exception_ValidationError
+ * @param type $customerId
+ * @param type $transactionAttribs
+ * @return Braintree_Transaction
+ */
+ public static function creditNoValidate($customerId, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->customer()->creditNoValidate($customerId, $transactionAttribs);
+ }
+
+ /**
+ *
+ * @throws Braintree_Exception on invalid id or non-200 http response code
+ * @param int $customerId
+ * @return Braintree_Result_Successful
+ */
+ public static function delete($customerId)
+ {
+ return Braintree_Configuration::gateway()->customer()->delete($customerId);
+ }
+
+ /**
+ *
+ * @param int $customerId
+ * @param array $transactionAttribs
+ * @return Braintree_Transaction
+ */
+ public static function sale($customerId, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->customer()->sale($customerId, $transactionAttribs);
+ }
+
+ /**
+ *
+ * @param int $customerId
+ * @param array $transactionAttribs
+ * @return Braintree_Transaction
+ */
+ public static function saleNoValidate($customerId, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->customer()->saleNoValidate($customerId, $transactionAttribs);
+ }
+
+ /**
+ *
+ * @throws InvalidArgumentException
+ * @param string $query
+ * @return Braintree_ResourceCollection
+ */
+ public static function search($query)
+ {
+ return Braintree_Configuration::gateway()->customer()->search($query);
+ }
+
+ /**
+ *
+ * @throws Braintree_Exception_Unexpected
+ * @param int $customerId
+ * @param array $attributes
+ * @return Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public static function update($customerId, $attributes)
+ {
+ return Braintree_Configuration::gateway()->customer()->update($customerId, $attributes);
+ }
+
+ /**
+ *
+ * @throws Braintree_Exception_Unexpected
+ * @param int $customerId
+ * @param array $attributes
+ * @return Braintree_CustomerGateway
+ */
+ public static function updateNoValidate($customerId, $attributes)
+ {
+ return Braintree_Configuration::gateway()->customer()->updateNoValidate($customerId, $attributes);
+ }
+
+ /**
+ *
+ * @deprecated since version 2.3.0
+ * @return string
+ */
+ public static function updateCustomerUrl()
+ {
+ return Braintree_Configuration::gateway()->customer()->updateCustomerUrl();
+ }
+
+ /**
+ *
+ * @deprecated since version 2.3.0
+ * @param string $queryString
+ * @return Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public static function updateFromTransparentRedirect($queryString)
+ {
+ return Braintree_Configuration::gateway()->customer()->updateFromTransparentRedirect($queryString);
+ }
+
+ /* instance methods */
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @ignore
+ * @access protected
+ * @param array $customerAttribs array of customer data
+ */
+ protected function _initialize($customerAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $customerAttribs;
+
+ // map each address into its own object
+ $addressArray = array();
+ if (isset($customerAttribs['addresses'])) {
+
+ foreach ($customerAttribs['addresses'] AS $address) {
+ $addressArray[] = Braintree_Address::factory($address);
+ }
+ }
+ $this->_set('addresses', $addressArray);
+
+ // map each creditCard into its own object
+ $creditCardArray = array();
+ if (isset($customerAttribs['creditCards'])) {
+ foreach ($customerAttribs['creditCards'] AS $creditCard) {
+ $creditCardArray[] = Braintree_CreditCard::factory($creditCard);
+ }
+ }
+ $this->_set('creditCards', $creditCardArray);
+
+ // map each coinbaseAccount into its own object
+ $coinbaseAccountArray = array();
+ if (isset($customerAttribs['coinbaseAccounts'])) {
+ foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) {
+ $coinbaseAccountArray[] = Braintree_CoinbaseAccount::factory($coinbaseAccount);
+ }
+ }
+ $this->_set('coinbaseAccounts', $coinbaseAccountArray);
+
+ // map each paypalAccount into its own object
+ $paypalAccountArray = array();
+ if (isset($customerAttribs['paypalAccounts'])) {
+ foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) {
+ $paypalAccountArray[] = Braintree_PayPalAccount::factory($paypalAccount);
+ }
+ }
+ $this->_set('paypalAccounts', $paypalAccountArray);
+
+ // map each applePayCard into its own object
+ $applePayCardArray = array();
+ if (isset($customerAttribs['applePayCards'])) {
+ foreach ($customerAttribs['applePayCards'] AS $applePayCard) {
+ $applePayCardArray[] = Braintree_ApplePayCard::factory($applePayCard);
+ }
+ }
+ $this->_set('applePayCards', $applePayCardArray);
+
+ // map each androidPayCard into its own object
+ $androidPayCardArray = array();
+ if (isset($customerAttribs['androidPayCards'])) {
+ foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) {
+ $androidPayCardArray[] = Braintree_AndroidPayCard::factory($androidPayCard);
+ }
+ }
+ $this->_set('androidPayCards', $androidPayCardArray);
+
+ $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->coinbaseAccounts, $this->androidPayCards));
+ }
+
+ /**
+ * returns a string representation of the customer
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+ /**
+ * returns false if comparing object is not a Braintree_Customer,
+ * or is a Braintree_Customer with a different id
+ *
+ * @param object $otherCust customer to compare against
+ * @return boolean
+ */
+ public function isEqual($otherCust)
+ {
+ return !($otherCust instanceof Braintree_Customer) ? false : $this->id === $otherCust->id;
+ }
+
+ /**
+ * returns an array containt all of the customer's payment methods
+ *
+ * @deprecated since version 3.1.0 - use the paymentMethods property directly
+ *
+ * @return array
+ */
+ public function paymentMethods()
+ {
+ return $this->paymentMethods;
+ }
+
+ /**
+ * returns the customer's default payment method
+ *
+ * @return object Braintree_CreditCard or Braintree_PayPalAccount
+ */
+ public function defaultPaymentMethod()
+ {
+ $defaultPaymentMethods = array_filter($this->paymentMethods, 'Braintree_Customer::_defaultPaymentMethodFilter');
+ return current($defaultPaymentMethods);
+ }
+
+ public static function _defaultPaymentMethodFilter($paymentMethod)
+ {
+ return $paymentMethod->isDefault();
+ }
+
+ /* private class properties */
+
+ /**
+ * @access protected
+ * @var array registry of customer data
+ */
+ protected $_attributes = array(
+ 'addresses' => '',
+ 'company' => '',
+ 'creditCards' => '',
+ 'email' => '',
+ 'fax' => '',
+ 'firstName' => '',
+ 'id' => '',
+ 'lastName' => '',
+ 'phone' => '',
+ 'createdAt' => '',
+ 'updatedAt' => '',
+ 'website' => '',
+ );
+
+ /**
+ * factory method: returns an instance of Braintree_Customer
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @param array $attributes
+ * @return Braintree_Customer
+ */
+ public static function factory($attributes)
+ {
+ $instance = new Braintree_Customer();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerGateway.php
new file mode 100644
index 0000000..ae86100
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerGateway.php
@@ -0,0 +1,619 @@
+<?php
+/**
+ * Braintree CustomerGateway module
+ * Creates and manages Customers
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Customers, see {@link http://www.braintreepayments.com/gateway/customer-api http://www.braintreepaymentsolutions.com/gateway/customer-api}
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_CustomerGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function all()
+ {
+ $path = $this->_config->merchantPath() . '/customers/advanced_search_ids';
+ $response = $this->_http->post($path);
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetch',
+ 'methodArgs' => array(array())
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ }
+
+ public function fetch($query, $ids)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+ $criteria["ids"] = Braintree_CustomerSearch::ids()->in($ids)->toparam();
+ $path = $this->_config->merchantPath() . '/customers/advanced_search';
+ $response = $this->_http->post($path, array('search' => $criteria));
+
+ return Braintree_Util::extractattributeasarray(
+ $response['customers'],
+ 'customer'
+ );
+ }
+
+ /**
+ * Creates a customer using the given +attributes+. If <tt>:id</tt> is not passed,
+ * the gateway will generate it.
+ *
+ * <code>
+ * $result = Braintree_Customer::create(array(
+ * 'first_name' => 'John',
+ * 'last_name' => 'Smith',
+ * 'company' => 'Smith Co.',
+ * 'email' => 'john@smith.com',
+ * 'website' => 'www.smithco.com',
+ * 'fax' => '419-555-1234',
+ * 'phone' => '614-555-1234'
+ * ));
+ * if($result->success) {
+ * echo 'Created customer ' . $result->customer->id;
+ * } else {
+ * echo 'Could not create customer, see result->errors';
+ * }
+ * </code>
+ *
+ * @access public
+ * @param array $attribs
+ * @return object Result, either Successful or Error
+ */
+ public function create($attribs = array())
+ {
+ Braintree_Util::verifyKeys(self::createSignature(), $attribs);
+ return $this->_doCreate('/customers', array('customer' => $attribs));
+ }
+
+ /**
+ * attempts the create operation assuming all data will validate
+ * returns a Braintree_Customer object instead of a Result
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ * @throws Braintree_Exception_ValidationError
+ */
+ public function createNoValidate($attribs = array())
+ {
+ $result = $this->create($attribs);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+ /**
+ * create a customer from a TransparentRedirect operation
+ *
+ * @deprecated since version 2.3.0
+ * @access public
+ * @param array $attribs
+ * @return object
+ */
+ public function createFromTransparentRedirect($queryString)
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
+ $params = Braintree_TransparentRedirect::parseAndValidateQueryString(
+ $queryString
+ );
+ return $this->_doCreate(
+ '/customers/all/confirm_transparent_redirect_request',
+ array('id' => $params['id'])
+ );
+ }
+
+ /**
+ *
+ * @deprecated since version 2.3.0
+ * @access public
+ * @param none
+ * @return string
+ */
+ public function createCustomerUrl()
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
+ return $this->_config->baseUrl() . $this->_config->merchantPath() .
+ '/customers/all/create_via_transparent_redirect_request';
+ }
+
+
+ /**
+ * creates a full array signature of a valid create request
+ * @return array gateway create request format
+ */
+ public static function createSignature()
+ {
+
+ $creditCardSignature = Braintree_CreditCardGateway::createSignature();
+ unset($creditCardSignature[array_search('customerId', $creditCardSignature)]);
+ $signature = array(
+ 'id', 'company', 'email', 'fax', 'firstName',
+ 'lastName', 'phone', 'website', 'deviceData',
+ 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce',
+ array('creditCard' => $creditCardSignature),
+ array('customFields' => array('_anyKey_')),
+ );
+ return $signature;
+ }
+
+ /**
+ * creates a full array signature of a valid update request
+ * @return array update request format
+ */
+ public static function updateSignature()
+ {
+ $creditCardSignature = Braintree_CreditCardGateway::updateSignature();
+
+ foreach($creditCardSignature AS $key => $value) {
+ if(is_array($value) and array_key_exists('options', $value)) {
+ array_push($creditCardSignature[$key]['options'], 'updateExistingToken');
+ }
+ }
+
+ $signature = array(
+ 'id', 'company', 'email', 'fax', 'firstName',
+ 'lastName', 'phone', 'website', 'deviceData',
+ 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce',
+ array('creditCard' => $creditCardSignature),
+ array('customFields' => array('_anyKey_')),
+ );
+ return $signature;
+ }
+
+
+ /**
+ * find a customer by id
+ *
+ * @access public
+ * @param string id customer Id
+ * @return object Braintree_Customer
+ * @throws Braintree_Exception_NotFound
+ */
+ public function find($id)
+ {
+ $this->_validateId($id);
+ try {
+ $path = $this->_config->merchantPath() . '/customers/' . $id;
+ $response = $this->_http->get($path);
+ return Braintree_Customer::factory($response['customer']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'customer with id ' . $id . ' not found'
+ );
+ }
+
+ }
+
+ /**
+ * credit a customer for the passed transaction
+ *
+ * @access public
+ * @param int $customerId
+ * @param array $transactionAttribs
+ * @return Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public function credit($customerId, $transactionAttribs)
+ {
+ $this->_validateId($customerId);
+ return Braintree_Transaction::credit(
+ array_merge($transactionAttribs,
+ array('customerId' => $customerId)
+ )
+ );
+ }
+
+ /**
+ * credit a customer, assuming validations will pass
+ *
+ * returns a Braintree_Transaction object on success
+ *
+ * @access public
+ * @param int $customerId
+ * @param array $transactionAttribs
+ * @return Braintree_Transaction
+ * @throws Braintree_Exception_ValidationError
+ */
+ public function creditNoValidate($customerId, $transactionAttribs)
+ {
+ $result = $this->credit($customerId, $transactionAttribs);
+ return Braintree_Util::returnObjectOrThrowException('Braintree_Transaction', $result);
+ }
+
+ /**
+ * delete a customer by id
+ *
+ * @param string $customerId
+ */
+ public function delete($customerId)
+ {
+ $this->_validateId($customerId);
+ $path = $this->_config->merchantPath() . '/customers/' . $customerId;
+ $this->_http->delete($path);
+ return new Braintree_Result_Successful();
+ }
+
+ /**
+ * create a new sale for a customer
+ *
+ * @param string $customerId
+ * @param array $transactionAttribs
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ * @see Braintree_Transaction::sale()
+ */
+ public function sale($customerId, $transactionAttribs)
+ {
+ $this->_validateId($customerId);
+ return Braintree_Transaction::sale(
+ array_merge($transactionAttribs,
+ array('customerId' => $customerId)
+ )
+ );
+ }
+
+ /**
+ * create a new sale for a customer, assuming validations will pass
+ *
+ * returns a Braintree_Transaction object on success
+ * @access public
+ * @param string $customerId
+ * @param array $transactionAttribs
+ * @return object Braintree_Transaction
+ * @throws Braintree_Exception_ValidationsFailed
+ * @see Braintree_Transaction::sale()
+ */
+ public function saleNoValidate($customerId, $transactionAttribs)
+ {
+ $result = $this->sale($customerId, $transactionAttribs);
+ return Braintree_Util::returnObjectOrThrowException('Braintree_Transaction', $result);
+ }
+
+ /**
+ * Returns a ResourceCollection of customers matching the search query.
+ *
+ * If <b>query</b> is a string, the search will be a basic search.
+ * If <b>query</b> is a hash, the search will be an advanced search.
+ * For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/customer-api#searching http://www.braintreepaymentsolutions.com/gateway/customer-api}
+ *
+ * @param mixed $query search query
+ * @return object Braintree_ResourceCollection
+ * @throws InvalidArgumentException
+ */
+ public function search($query)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $result = $term->toparam();
+ if(is_null($result) || empty($result)) {
+ throw new InvalidArgumentException('Operator must be provided');
+ }
+
+ $criteria[$term->name] = $term->toparam();
+ }
+
+ $path = $this->_config->merchantPath() . '/customers/advanced_search_ids';
+ $response = $this->_http->post($path, array('search' => $criteria));
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetch',
+ 'methodArgs' => array($query)
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ }
+
+ /**
+ * updates the customer record
+ *
+ * if calling this method in static context, customerId
+ * is the 2nd attribute. customerId is not sent in object context.
+ *
+ * @access public
+ * @param string $customerId (optional)
+ * @param array $attributes
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ */
+ public function update($customerId, $attributes)
+ {
+ Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
+ $this->_validateId($customerId);
+ return $this->_doUpdate(
+ 'put',
+ '/customers/' . $customerId,
+ array('customer' => $attributes)
+ );
+ }
+
+ /**
+ * update a customer record, assuming validations will pass
+ *
+ * if calling this method in static context, customerId
+ * is the 2nd attribute. customerId is not sent in object context.
+ * returns a Braintree_Customer object on success
+ *
+ * @access public
+ * @param string $customerId
+ * @param array $attributes
+ * @return object Braintree_Customer
+ * @throws Braintree_Exception_ValidationsFailed
+ */
+ public function updateNoValidate($customerId, $attributes)
+ {
+ $result = $this->update($customerId, $attributes);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+ /**
+ *
+ * @deprecated since version 2.3.0
+ * @access public
+ * @return string
+ */
+ public function updateCustomerUrl()
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
+ return $this->_config->baseUrl() . $this->_config->merchantPath() .
+ '/customers/all/update_via_transparent_redirect_request';
+ }
+
+ /**
+ * update a customer from a TransparentRedirect operation
+ *
+ * @deprecated since version 2.3.0
+ * @access public
+ * @param string $queryString
+ * @return object
+ */
+ public function updateFromTransparentRedirect($queryString)
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
+ $params = Braintree_TransparentRedirect::parseAndValidateQueryString(
+ $queryString
+ );
+ return $this->_doUpdate(
+ 'post',
+ '/customers/all/confirm_transparent_redirect_request',
+ array('id' => $params['id'])
+ );
+ }
+
+ /* instance methods */
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @ignore
+ * @access protected
+ * @param array $customerAttribs array of customer data
+ * @return none
+ */
+ protected function _initialize($customerAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $customerAttribs;
+
+ // map each address into its own object
+ $addressArray = array();
+ if (isset($customerAttribs['addresses'])) {
+
+ foreach ($customerAttribs['addresses'] AS $address) {
+ $addressArray[] = Braintree_Address::factory($address);
+ }
+ }
+ $this->_set('addresses', $addressArray);
+
+ // map each creditCard into its own object
+ $creditCardArray = array();
+ if (isset($customerAttribs['creditCards'])) {
+ foreach ($customerAttribs['creditCards'] AS $creditCard) {
+ $creditCardArray[] = Braintree_CreditCard::factory($creditCard);
+ }
+ }
+ $this->_set('creditCards', $creditCardArray);
+
+ // map each coinbaseAccount into its own object
+ $coinbaseAccountArray = array();
+ if (isset($customerAttribs['coinbaseAccounts'])) {
+ foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) {
+ $coinbaseAccountArray[] = Braintree_CoinbaseAccount::factory($coinbaseAccount);
+ }
+ }
+ $this->_set('coinbaseAccounts', $coinbaseAccountArray);
+
+ // map each paypalAccount into its own object
+ $paypalAccountArray = array();
+ if (isset($customerAttribs['paypalAccounts'])) {
+ foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) {
+ $paypalAccountArray[] = Braintree_PayPalAccount::factory($paypalAccount);
+ }
+ }
+ $this->_set('paypalAccounts', $paypalAccountArray);
+
+ // map each applePayCard into its own object
+ $applePayCardArray = array();
+ if (isset($customerAttribs['applePayCards'])) {
+ foreach ($customerAttribs['applePayCards'] AS $applePayCard) {
+ $applePayCardArray[] = Braintree_applePayCard::factory($applePayCard);
+ }
+ }
+ $this->_set('applePayCards', $applePayCardArray);
+
+ // map each androidPayCard into its own object
+ $androidPayCardArray = array();
+ if (isset($customerAttribs['androidPayCards'])) {
+ foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) {
+ $androidPayCardArray[] = Braintree_AndroidPayCard::factory($androidPayCard);
+ }
+ }
+ $this->_set('androidPayCards', $androidPayCardArray);
+
+ $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->coinbaseAccounts, $this->androidPayCards));
+ }
+
+ /**
+ * returns a string representation of the customer
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+ /**
+ * returns false if comparing object is not a Braintree_Customer,
+ * or is a Braintree_Customer with a different id
+ *
+ * @param object $otherCust customer to compare against
+ * @return boolean
+ */
+ public function isEqual($otherCust)
+ {
+ return !($otherCust instanceof Braintree_Customer) ? false : $this->id === $otherCust->id;
+ }
+
+ /**
+ * returns an array containt all of the customer's payment methods
+ *
+ * @return array
+ */
+ public function paymentMethods()
+ {
+ return $this->paymentMethods;
+ }
+
+ /**
+ * returns the customer's default payment method
+ *
+ * @return object Braintree_CreditCard | Braintree_PayPalAccount | Braintree_ApplePayCard | Braintree_AndroidPayCard
+ */
+ public function defaultPaymentMethod()
+ {
+ $defaultPaymentMethods = array_filter($this->paymentMethods, 'Braintree_Customer::_defaultPaymentMethodFilter');
+ return current($defaultPaymentMethods);
+ }
+
+ public static function _defaultPaymentMethodFilter($paymentMethod)
+ {
+ return $paymentMethod->isDefault();
+ }
+
+ /* private class properties */
+
+ /**
+ * @access protected
+ * @var array registry of customer data
+ */
+ protected $_attributes = array(
+ 'addresses' => '',
+ 'company' => '',
+ 'creditCards' => '',
+ 'email' => '',
+ 'fax' => '',
+ 'firstName' => '',
+ 'id' => '',
+ 'lastName' => '',
+ 'phone' => '',
+ 'createdAt' => '',
+ 'updatedAt' => '',
+ 'website' => '',
+ );
+
+ /**
+ * sends the create request to the gateway
+ *
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ public function _doCreate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * verifies that a valid customer id is being used
+ * @ignore
+ * @param string customer id
+ * @throws InvalidArgumentException
+ */
+ private function _validateId($id = null) {
+ if (empty($id)) {
+ throw new InvalidArgumentException(
+ 'expected customer id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
+ throw new InvalidArgumentException(
+ $id . ' is an invalid customer id.'
+ );
+ }
+ }
+
+
+ /* private class methods */
+
+ /**
+ * sends the update request to the gateway
+ *
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ private function _doUpdate($httpVerb, $subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->$httpVerb($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * creates a new Braintree_Customer object and encapsulates
+ * it inside a Braintree_Result_Successful object, or
+ * encapsulates a Braintree_Errors object inside a Result_Error
+ * alternatively, throws an Unexpected exception if the response is invalid.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return object Result_Successful or Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['customer'])) {
+ // return a populated instance of Braintree_Customer
+ return new Braintree_Result_Successful(
+ Braintree_Customer::factory($response['customer'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected customer or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerSearch.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerSearch.php
new file mode 100644
index 0000000..b550c84
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/CustomerSearch.php
@@ -0,0 +1,31 @@
+<?php
+class Braintree_CustomerSearch
+{
+ static function addressCountryName() { return new Braintree_TextNode('address_country_name'); }
+ static function addressExtendedAddress() { return new Braintree_TextNode('address_extended_address'); }
+ static function addressFirstName() { return new Braintree_TextNode('address_first_name'); }
+ static function addressLastName() { return new Braintree_TextNode('address_last_name'); }
+ static function addressLocality() { return new Braintree_TextNode('address_locality'); }
+ static function addressPostalCode() { return new Braintree_TextNode('address_postal_code'); }
+ static function addressRegion() { return new Braintree_TextNode('address_region'); }
+ static function addressStreetAddress() { return new Braintree_TextNode('address_street_address'); }
+ static function cardholderName() { return new Braintree_TextNode('cardholder_name'); }
+ static function company() { return new Braintree_TextNode('company'); }
+ static function email() { return new Braintree_TextNode('email'); }
+ static function fax() { return new Braintree_TextNode('fax'); }
+ static function firstName() { return new Braintree_TextNode('first_name'); }
+ static function id() { return new Braintree_TextNode('id'); }
+ static function lastName() { return new Braintree_TextNode('last_name'); }
+ static function paymentMethodToken() { return new Braintree_TextNode('payment_method_token'); }
+ static function paymentMethodTokenWithDuplicates() { return new Braintree_IsNode('payment_method_token_with_duplicates'); }
+ static function paypalAccountEmail() { return new Braintree_IsNode('paypal_account_email'); }
+ static function phone() { return new Braintree_TextNode('phone'); }
+ static function website() { return new Braintree_TextNode('website'); }
+
+ static function creditCardExpirationDate() { return new Braintree_EqualityNode('credit_card_expiration_date'); }
+ static function creditCardNumber() { return new Braintree_PartialMatchNode('credit_card_number'); }
+
+ static function ids() { return new Braintree_MultipleValueNode('ids'); }
+
+ static function createdAt() { return new Braintree_RangeNode("created_at"); }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Descriptor.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Descriptor.php
new file mode 100644
index 0000000..f20cd8c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Descriptor.php
@@ -0,0 +1,4 @@
+<?php
+class Braintree_Descriptor extends Braintree_Instance
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Digest.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Digest.php
new file mode 100644
index 0000000..2008210
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Digest.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Digest encryption module
+ * Digest creates an HMAC-SHA1 hash for encrypting messages
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Digest
+{
+ public static function hexDigestSha1($key, $string)
+ {
+ if(function_exists('hash_hmac')) {
+ return self::_builtInHmacSha1($string, $key);
+ } else {
+ return self::_hmacSha1($string, $key);
+ }
+ }
+
+ public static function hexDigestSha256($key, $string)
+ {
+ return hash_hmac('sha256', $string, hash('sha256', $key, true));
+ }
+
+ public static function secureCompare($left, $right)
+ {
+ if (strlen($left) != strlen($right)) {
+ return false;
+ }
+
+ $leftBytes = unpack("C*", $left);
+ $rightBytes = unpack("C*", $right);
+
+ $result = 0;
+ for ($i = 1; $i <= count($leftBytes); $i++) {
+ $result = $result | ($leftBytes[$i] ^ $rightBytes[$i]);
+ }
+ return $result == 0;
+ }
+
+ public static function _builtInHmacSha1($message, $key)
+ {
+ return hash_hmac('sha1', $message, sha1($key, true));
+ }
+
+ public static function _hmacSha1($message, $key)
+ {
+ $pack = 'H40';
+ $keyDigest = sha1($key,true);
+ $innerPad = str_repeat(chr(0x36), 64);
+ $outerPad = str_repeat(chr(0x5C), 64);
+
+ for ($i = 0; $i < 20; $i++) {
+ $innerPad{$i} = $keyDigest{$i} ^ $innerPad{$i};
+ $outerPad{$i} = $keyDigest{$i} ^ $outerPad{$i};
+ }
+
+ return sha1($outerPad.pack($pack, sha1($innerPad.$message)));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Disbursement.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Disbursement.php
new file mode 100644
index 0000000..c6748dc
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Disbursement.php
@@ -0,0 +1,49 @@
+<?php
+final class Braintree_Disbursement extends Braintree_Base
+{
+ private $_merchantAccount;
+
+ protected function _initialize($disbursementAttribs)
+ {
+ $this->_attributes = $disbursementAttribs;
+ $this->merchantAccountDetails = $disbursementAttribs['merchantAccount'];
+
+ if (isset($disbursementAttribs['merchantAccount'])) {
+ $this->_set('merchantAccount',
+ Braintree_MerchantAccount::factory($disbursementAttribs['merchantAccount'])
+ );
+ }
+ }
+
+ public function transactions()
+ {
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::ids()->in($this->transactionIds)
+ ));
+
+ return $collection;
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ public function __toString()
+ {
+ $display = array(
+ 'id', 'merchantAccountDetails', 'exceptionMessage', 'amount',
+ 'disbursementDate', 'followUpAction', 'retry', 'success',
+ 'transactionIds'
+ );
+
+ $displayAttributes = array();
+ foreach ($display AS $attrib) {
+ $displayAttributes[$attrib] = $this->$attrib;
+ }
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($displayAttributes) .']';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DisbursementDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DisbursementDetails.php
new file mode 100644
index 0000000..8a01f61
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DisbursementDetails.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Disbursement details from a transaction
+ * Creates an instance of DisbursementDetails as returned from a transaction
+ *
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $settlementAmount
+ * @property-read string $settlementCurrencyIsoCode
+ * @property-read string $settlementCurrencyExchangeRate
+ * @property-read string $fundsHeld
+ * @property-read string $success
+ * @property-read string $disbursementDate
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_DisbursementDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+
+ function isValid() {
+ return !is_null($this->disbursementDate);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Discount.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Discount.php
new file mode 100644
index 0000000..7150d9e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Discount.php
@@ -0,0 +1,18 @@
+<?php
+class Braintree_Discount extends Braintree_Modification
+{
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function all()
+ {
+ return Braintree_Configuration::gateway()->discount()->all();
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DiscountGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DiscountGateway.php
new file mode 100644
index 0000000..8db639c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/DiscountGateway.php
@@ -0,0 +1,28 @@
+<?php
+class Braintree_DiscountGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function all()
+ {
+ $path = $this->_config->merchantPath() . '/discounts';
+ $response = $this->_http->get($path);
+
+ $discounts = array("discount" => $response['discounts']);
+
+ return Braintree_Util::extractAttributeAsArray(
+ $discounts,
+ 'discount'
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute.php
new file mode 100644
index 0000000..298dc03
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Creates an instance of Dispute as returned from a transaction
+ *
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $amount
+ * @property-read string $currencyIsoCode
+ * @property-read date $receivedDate
+ * @property-read string $reason
+ * @property-read string $status
+ * @property-read string $disbursementDate
+ * @property-read object $transactionDetails
+ */
+final class Braintree_Dispute extends Braintree_Base
+{
+ protected $_attributes = array();
+
+ /* Dispute Status */
+ const OPEN = 'open';
+ const WON = 'won';
+ const LOST = 'lost';
+
+ /* deprecated; for backwards compatibilty */
+ const Open = 'open';
+
+ /* Dispute Reason */
+ const CANCELLED_RECURRING_TRANSACTION = "cancelled_recurring_transaction";
+ const CREDIT_NOT_PROCESSED = "credit_not_processed";
+ const DUPLICATE = "duplicate";
+ const FRAUD = "fraud";
+ const GENERAL = "general";
+ const INVALID_ACCOUNT = "invalid_account";
+ const NOT_RECOGNIZED = "not_recognized";
+ const PRODUCT_NOT_RECEIVED = "product_not_received";
+ const PRODUCT_UNSATISFACTORY = "product_unsatisfactory";
+ const TRANSACTION_AMOUNT_DIFFERS = "transaction_amount_differs";
+ const RETRIEVAL = "retrieval";
+
+
+ protected function _initialize($disputeAttribs)
+ {
+ $this->_attributes = $disputeAttribs;
+
+ if (isset($disputeAttribs['transaction'])) {
+ $this->_set('transactionDetails',
+ new Braintree_Dispute_TransactionDetails($disputeAttribs['transaction'])
+ );
+ }
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ public function __toString()
+ {
+ $display = array(
+ 'amount', 'reason', 'status',
+ 'replyByDate', 'receivedDate', 'currencyIsoCode'
+ );
+
+ $displayAttributes = array();
+ foreach ($display AS $attrib) {
+ $displayAttributes[$attrib] = $this->$attrib;
+ }
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($displayAttributes) .']';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute/TransactionDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute/TransactionDetails.php
new file mode 100644
index 0000000..e0bbbf2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Dispute/TransactionDetails.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Transaction details for a dispute
+ *
+ * @package Braintree
+ * @copyright 2010 Braintree Payment Solutions
+ */
+
+/**
+ * Creates an instance of DisbursementDetails as returned from a transaction
+ *
+ *
+ * @package Braintree
+ * @copyright 2010 Braintree Payment Solutions
+ *
+ * @property-read string $amount
+ * @property-read string $id
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Dispute_TransactionDetails extends Braintree_Instance
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/EqualityNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/EqualityNode.php
new file mode 100644
index 0000000..68c10b5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/EqualityNode.php
@@ -0,0 +1,10 @@
+<?php
+
+class Braintree_EqualityNode extends Braintree_IsNode
+{
+ function isNot($value)
+ {
+ $this->searchTerms['is_not'] = strval($value);
+ return $this;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Codes.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Codes.php
new file mode 100644
index 0000000..f52a3cc
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Codes.php
@@ -0,0 +1,492 @@
+<?php
+/**
+ *
+ * Validation Error codes and messages
+ *
+ * ErrorCodes class provides constants for validation errors.
+ * The constants should be used to check for a specific validation
+ * error in a ValidationErrorCollection.
+ * The error messages returned from the server may change;
+ * but the codes will remain the same.
+ *
+ * @package Braintree
+ * @subpackage Errors
+ * @category Validation
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Error_Codes
+{
+ const ADDRESS_CANNOT_BE_BLANK = '81801';
+ const ADDRESS_COMPANY_IS_INVALID = '91821';
+ const ADDRESS_COMPANY_IS_TOO_LONG = '81802';
+ const ADDRESS_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED = '91814';
+ const ADDRESS_COUNTRY_CODE_ALPHA3_IS_NOT_ACCEPTED = '91816';
+ const ADDRESS_COUNTRY_CODE_NUMERIC_IS_NOT_ACCEPTED = '91817';
+ const ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED = '91803';
+ const ADDRESS_EXTENDED_ADDRESS_IS_INVALID = '91823';
+ const ADDRESS_EXTENDED_ADDRESS_IS_TOO_LONG = '81804';
+ const ADDRESS_FIRST_NAME_IS_INVALID = '91819';
+ const ADDRESS_FIRST_NAME_IS_TOO_LONG = '81805';
+ const ADDRESS_INCONSISTENT_COUNTRY = '91815';
+ const ADDRESS_LAST_NAME_IS_INVALID = '91820';
+ const ADDRESS_LAST_NAME_IS_TOO_LONG = '81806';
+ const ADDRESS_LOCALITY_IS_INVALID = '91824';
+ const ADDRESS_LOCALITY_IS_TOO_LONG = '81807';
+ const ADDRESS_POSTAL_CODE_INVALID_CHARACTERS = '81813';
+ const ADDRESS_POSTAL_CODE_IS_INVALID = '91826';
+ const ADDRESS_POSTAL_CODE_IS_REQUIRED = '81808';
+ const ADDRESS_POSTAL_CODE_IS_TOO_LONG = '81809';
+ const ADDRESS_REGION_IS_INVALID = '91825';
+ const ADDRESS_REGION_IS_TOO_LONG = '81810';
+ const ADDRESS_STATE_IS_INVALID_FOR_SELLER_PROTECTION = '81827';
+ const ADDRESS_STREET_ADDRESS_IS_INVALID = '91822';
+ const ADDRESS_STREET_ADDRESS_IS_REQUIRED = '81811';
+ const ADDRESS_STREET_ADDRESS_IS_TOO_LONG = '81812';
+ const ADDRESS_TOO_MANY_ADDRESSES_PER_CUSTOMER = '91818';
+
+ const APPLE_PAY_CARDS_ARE_NOT_ACCEPTED = '83501';
+ const APPLE_PAY_CUSTOMER_ID_IS_REQUIRED_FOR_VAULTING = '83502';
+ const APPLE_PAY_TOKEN_IS_IN_USE = '93503';
+ const APPLE_PAY_PAYMENT_METHOD_NONCE_CONSUMED = '93504';
+ const APPLE_PAY_PAYMENT_METHOD_NONCE_UNKNOWN = '93505';
+ const APPLE_PAY_PAYMENT_METHOD_NONCE_UNLOCKED = '93506';
+ const APPLE_PAY_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '83518';
+ const APPLE_PAY_CANNOT_UPDATE_APPLE_PAY_CARD_USING_PAYMENT_METHOD_NONCE = '93507';
+ const APPLE_PAY_NUMBER_IS_REQUIRED = '93508';
+ const APPLE_PAY_EXPIRATION_MONTH_IS_REQUIRED = '93509';
+ const APPLE_PAY_EXPIRATION_YEAR_IS_REQUIRED = '93510';
+ const APPLE_PAY_CRYPTOGRAM_IS_REQUIRED = '93511';
+ const APPLE_PAY_DECRYPTION_FAILED = '83512';
+ const APPLE_PAY_DISABLED = '93513';
+ const APPLE_PAY_MERCHANT_NOT_CONFIGURED = '93514';
+ const APPLE_PAY_MERCHANT_KEYS_ALREADY_CONFIGURED = '93515';
+ const APPLE_PAY_MERCHANT_KEYS_NOT_CONFIGURED = '93516';
+ const APPLE_PAY_CERTIFICATE_INVALID = '93517';
+ const APPLE_PAY_CERTIFICATE_MISMATCH = '93519';
+ const APPLE_PAY_INVALID_TOKEN = '83520';
+ const APPLE_PAY_PRIVATE_KEY_MISMATCH = '93521';
+ const APPLE_PAY_KEY_MISMATCH_STORING_CERTIFICATE = '93522';
+
+ const AUTHORIZATION_FINGERPRINT_INVALID_CREATED_AT = '93204';
+ const AUTHORIZATION_FINGERPRINT_INVALID_FORMAT = '93202';
+ const AUTHORIZATION_FINGERPRINT_INVALID_PUBLIC_KEY = '93205';
+ const AUTHORIZATION_FINGERPRINT_INVALID_SIGNATURE = '93206';
+ const AUTHORIZATION_FINGERPRINT_MISSING_FINGERPRINT = '93201';
+ const AUTHORIZATION_FINGERPRINT_OPTIONS_NOT_ALLOWED_WITHOUT_CUSTOMER = '93207';
+ const AUTHORIZATION_FINGERPRINT_SIGNATURE_REVOKED = '93203';
+
+ const CLIENT_TOKEN_CUSTOMER_DOES_NOT_EXIST = '92804';
+ const CLIENT_TOKEN_FAIL_ON_DUPLICATE_PAYMENT_METHOD_REQUIRES_CUSTOMER_ID = '92803';
+ const CLIENT_TOKEN_MAKE_DEFAULT_REQUIRES_CUSTOMER_ID = '92801';
+ const CLIENT_TOKEN_PROXY_MERCHANT_DOES_NOT_EXIST = '92805';
+ const CLIENT_TOKEN_UNSUPPORTED_VERSION = '92806';
+ const CLIENT_TOKEN_VERIFY_CARD_REQUIRES_CUSTOMER_ID = '92802';
+ const CLIENT_TOKEN_MERCHANT_ACCOUNT_DOES_NOT_EXIST = '92807';
+
+ const CREDIT_CARD_BILLING_ADDRESS_CONFLICT = '91701';
+ const CREDIT_CARD_BILLING_ADDRESS_FORMAT_IS_INVALID = '91744';
+ const CREDIT_CARD_BILLING_ADDRESS_ID_IS_INVALID = '91702';
+ const CREDIT_CARD_CANNOT_UPDATE_CARD_USING_PAYMENT_METHOD_NONCE = '91735';
+ const CREDIT_CARD_CARDHOLDER_NAME_IS_TOO_LONG = '81723';
+ const CREDIT_CARD_CREDIT_CARD_TYPE_IS_NOT_ACCEPTED = '81703';
+ const CREDIT_CARD_CREDIT_CARD_TYPE_IS_NOT_ACCEPTED_BY_SUBSCRIPTION_MERCHANT_ACCOUNT = '81718';
+ const CREDIT_CARD_CUSTOMER_ID_IS_INVALID = '91705';
+ const CREDIT_CARD_CUSTOMER_ID_IS_REQUIRED = '91704';
+ const CREDIT_CARD_CVV_IS_INVALID = '81707';
+ const CREDIT_CARD_CVV_IS_REQUIRED = '81706';
+ const CREDIT_CARD_CVV_VERIFICATION_FAILED = '81736';
+ const CREDIT_CARD_DUPLICATE_CARD_EXISTS = '81724';
+ const CREDIT_CARD_EXPIRATION_DATE_CONFLICT = '91708';
+ const CREDIT_CARD_EXPIRATION_DATE_IS_INVALID = '81710';
+ const CREDIT_CARD_EXPIRATION_DATE_IS_REQUIRED = '81709';
+ const CREDIT_CARD_EXPIRATION_DATE_YEAR_IS_INVALID = '81711';
+ const CREDIT_CARD_EXPIRATION_MONTH_IS_INVALID = '81712';
+ const CREDIT_CARD_EXPIRATION_YEAR_IS_INVALID = '81713';
+ const CREDIT_CARD_INVALID_PARAMS_FOR_CREDIT_CARD_UPDATE = '91745';
+ const CREDIT_CARD_INVALID_VENMO_SDK_PAYMENT_METHOD_CODE = '91727';
+ const CREDIT_CARD_NUMBER_INVALID_LENGTH = '81716';
+ const CREDIT_CARD_NUMBER_IS_INVALID = '81715';
+ const CREDIT_CARD_NUMBER_IS_REQUIRED = '81714';
+ const CREDIT_CARD_NUMBER_LENGTH_IS_INVALID = '81716';
+ const CREDIT_CARD_NUMBER_MUST_BE_TEST_NUMBER = '81717';
+ const CREDIT_CARD_OPTIONS_UPDATE_EXISTING_TOKEN_IS_INVALID = '91723';
+ const CREDIT_CARD_OPTIONS_UPDATE_EXISTING_TOKEN_NOT_ALLOWED = '91729';
+ const CREDIT_CARD_OPTIONS_VERIFICATION_AMOUNT_CANNOT_BE_NEGATIVE = '91739';
+ const CREDIT_CARD_OPTIONS_VERIFICATION_AMOUNT_FORMAT_IS_INVALID = '91740';
+ const CREDIT_CARD_OPTIONS_VERIFICATION_AMOUNT_NOT_SUPPORTED_BY_PROCESSOR = '91741';
+ const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91728';
+ const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_IS_FORBIDDEN = '91743';
+ const CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_IS_SUSPENDED = '91742';
+ const CREDIT_CARD_PAYMENT_METHOD_CONFLICT = '81725';
+ const CREDIT_CARD_PAYMENT_METHOD_IS_NOT_A_CREDIT_CARD = '91738';
+ const CREDIT_CARD_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91734';
+ const CREDIT_CARD_PAYMENT_METHOD_NONCE_CONSUMED = '91731';
+ const CREDIT_CARD_PAYMENT_METHOD_NONCE_LOCKED = '91733';
+ const CREDIT_CARD_PAYMENT_METHOD_NONCE_UNKNOWN = '91732';
+ const CREDIT_CARD_POSTAL_CODE_VERIFICATION_FAILED = '81737';
+ const CREDIT_CARD_TOKEN_FORMAT_IS_INVALID = '91718';
+ const CREDIT_CARD_TOKEN_INVALID = '91718';
+ const CREDIT_CARD_TOKEN_IS_IN_USE = '91719';
+ const CREDIT_CARD_TOKEN_IS_NOT_ALLOWED = '91721';
+ const CREDIT_CARD_TOKEN_IS_REQUIRED = '91722';
+ const CREDIT_CARD_TOKEN_IS_TOO_LONG = '91720';
+ const CREDIT_CARD_VENMO_SDK_PAYMENT_METHOD_CODE_CARD_TYPE_IS_NOT_ACCEPTED = '91726';
+ const CREDIT_CARD_VERIFICATION_NOT_SUPPORTED_ON_THIS_MERCHANT_ACCOUNT = '91730';
+
+ const CUSTOMER_COMPANY_IS_TOO_LONG = '81601';
+ const CUSTOMER_CUSTOM_FIELD_IS_INVALID = '91602';
+ const CUSTOMER_CUSTOM_FIELD_IS_TOO_LONG = '81603';
+ const CUSTOMER_EMAIL_FORMAT_IS_INVALID = '81604';
+ const CUSTOMER_EMAIL_IS_INVALID = '81604';
+ const CUSTOMER_EMAIL_IS_REQUIRED = '81606';
+ const CUSTOMER_EMAIL_IS_TOO_LONG = '81605';
+ const CUSTOMER_FAX_IS_TOO_LONG = '81607';
+ const CUSTOMER_FIRST_NAME_IS_TOO_LONG = '81608';
+ const CUSTOMER_ID_IS_INVAILD = '91610'; //Deprecated
+ const CUSTOMER_ID_IS_INVALID = '91610';
+ const CUSTOMER_ID_IS_IN_USE = '91609';
+ const CUSTOMER_ID_IS_NOT_ALLOWED = '91611';
+ const CUSTOMER_ID_IS_REQUIRED = '91613';
+ const CUSTOMER_ID_IS_TOO_LONG = '91612';
+ const CUSTOMER_LAST_NAME_IS_TOO_LONG = '81613';
+ const CUSTOMER_PHONE_IS_TOO_LONG = '81614';
+ const CUSTOMER_VAULTED_PAYMENT_INSTRUMENT_NONCE_BELONGS_TO_DIFFERENT_CUSTOMER = '91617';
+ const CUSTOMER_WEBSITE_FORMAT_IS_INVALID = '81616';
+ const CUSTOMER_WEBSITE_IS_INVALID = '81616';
+ const CUSTOMER_WEBSITE_IS_TOO_LONG = '81615';
+
+ const DESCRIPTOR_NAME_FORMAT_IS_INVALID = '92201';
+ const DESCRIPTOR_PHONE_FORMAT_IS_INVALID = '92202';
+ const DESCRIPTOR_INTERNATIONAL_NAME_FORMAT_IS_INVALID = '92204';
+ const DESCRIPTOR_DYNAMIC_DESCRIPTORS_DISABLED = '92203';
+ const DESCRIPTOR_INTERNATIONAL_PHONE_FORMAT_IS_INVALID = '92205';
+ const DESCRIPTOR_URL_FORMAT_IS_INVALID = '92206';
+
+ const INDUSTRY_DATA_INDUSTRY_TYPE_IS_INVALID = '93401';
+ const INDUSTRY_DATA_LODGING_EMPTY_DATA = '93402';
+ const INDUSTRY_DATA_LODGING_FOLIO_NUMBER_IS_INVALID = '93403';
+ const INDUSTRY_DATA_LODGING_CHECK_IN_DATE_IS_INVALID = '93404';
+ const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_IS_INVALID = '93405';
+ const INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_MUST_FOLLOW_CHECK_IN_DATE = '93406';
+ const INDUSTRY_DATA_LODGING_UNKNOWN_DATA_FIELD = '93407';
+ const INDUSTRY_DATA_TRAVEL_CRUISE_EMPTY_DATA = '93408';
+ const INDUSTRY_DATA_TRAVEL_CRUISE_UNKNOWN_DATA_FIELD = '93409';
+ const INDUSTRY_DATA_TRAVEL_CRUISE_TRAVEL_PACKAGE_IS_INVALID = '93410';
+ const INDUSTRY_DATA_TRAVEL_CRUISE_DEPARTURE_DATE_IS_INVALID = '93411';
+ const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_IN_DATE_IS_INVALID = '93412';
+ const INDUSTRY_DATA_TRAVEL_CRUISE_LODGING_CHECK_OUT_DATE_IS_INVALID = '93413';
+
+ const MERCHANT_COUNTRY_CANNOT_BE_BLANK = '83603';
+ const MERCHANT_COUNTRY_CODE_ALPHA2_IS_INVALID = '93607';
+ const MERCHANT_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED = '93606';
+ const MERCHANT_COUNTRY_CODE_ALPHA3_IS_INVALID = '93605';
+ const MERCHANT_COUNTRY_CODE_ALPHA3_IS_NOT_ACCEPTED = '93604';
+ const MERCHANT_COUNTRY_CODE_NUMERIC_IS_INVALID = '93609';
+ const MERCHANT_COUNTRY_CODE_NUMERIC_IS_NOT_ACCEPTED = '93608';
+ const MERCHANT_COUNTRY_NAME_IS_INVALID = '93611';
+ const MERCHANT_COUNTRY_NAME_IS_NOT_ACCEPTED = '93610';
+ const MERCHANT_EMAIL_FORMAT_IS_INVALID = '93602';
+ const MERCHANT_EMAIL_IS_REQUIRED = '83601';
+ const MERCHANT_INCONSISTENT_COUNTRY = '93612';
+ const MERCHANT_ACCOUNT_PAYMENT_METHODS_ARE_INVALID = '93613';
+
+ const MERCHANT_ACCOUNT_ID_FORMAT_IS_INVALID = '82603';
+ const MERCHANT_ACCOUNT_ID_IS_IN_USE = '82604';
+ const MERCHANT_ACCOUNT_ID_IS_NOT_ALLOWED = '82605';
+ const MERCHANT_ACCOUNT_ID_IS_TOO_LONG = '82602';
+ const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_IS_INVALID = '82607';
+ const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_IS_REQUIRED = '82606';
+ const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_MUST_BE_ACTIVE = '82608';
+ const MERCHANT_ACCOUNT_TOS_ACCEPTED_IS_REQUIRED = '82610';
+ const MERCHANT_ACCOUNT_CANNOT_BE_UPDATED = '82674';
+ const MERCHANT_ACCOUNT_DECLINED = '82626';
+ const MERCHANT_ACCOUNT_DECLINED_MASTER_CARD_MATCH = '82622';
+ const MERCHANT_ACCOUNT_DECLINED_OFAC = '82621';
+ const MERCHANT_ACCOUNT_DECLINED_FAILED_KYC = '82623';
+ const MERCHANT_ACCOUNT_DECLINED_SSN_INVALID = '82624';
+ const MERCHANT_ACCOUNT_DECLINED_SSN_MATCHES_DECEASED = '82625';
+ const MERCHANT_ACCOUNT_ID_CANNOT_BE_UPDATED = '82675';
+ const MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_CANNOT_BE_UPDATED = '82676';
+
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ACCOUNT_NUMBER_IS_REQUIRED = '82614';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_COMPANY_NAME_IS_INVALID = '82631';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_COMPANY_NAME_IS_REQUIRED_WITH_TAX_ID = '82633';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DATE_OF_BIRTH_IS_REQUIRED = '82612';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED = '82626'; // Keep for backwards compatibility
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_MASTER_CARD_MATCH = '82622'; // Keep for backwards compatibility
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_OFAC = '82621'; // Keep for backwards compatibility
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_FAILED_KYC = '82623'; // Keep for backwards compatibility
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_SSN_INVALID = '82624'; // Keep for backwards compatibility
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DECLINED_SSN_MATCHES_DECEASED = '82625'; // Keep for backwards compatibility
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_EMAIL_ADDRESS_IS_INVALID = '82616';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_FIRST_NAME_IS_INVALID = '82627';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_FIRST_NAME_IS_REQUIRED = '82609';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_LAST_NAME_IS_INVALID = '82628';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_LAST_NAME_IS_REQUIRED = '82611';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_PHONE_IS_INVALID = '82636';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ROUTING_NUMBER_IS_INVALID = '82635';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ROUTING_NUMBER_IS_REQUIRED = '82613';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_SSN_IS_INVALID = '82615';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_TAX_ID_IS_INVALID = '82632';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_TAX_ID_IS_REQUIRED_WITH_COMPANY_NAME = '82634';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_DATE_OF_BIRTH_IS_INVALID = '82663';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_REGION_IS_INVALID = '82664';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_EMAIL_ADDRESS_IS_REQUIRED = '82665';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ACCOUNT_NUMBER_IS_INVALID = '82670';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_TAX_ID_MUST_BE_BLANK = '82673';
+
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_LOCALITY_IS_REQUIRED = '82618';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_POSTAL_CODE_IS_INVALID = '82630';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_POSTAL_CODE_IS_REQUIRED = '82619';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_REGION_IS_REQUIRED = '82620';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_STREET_ADDRESS_IS_INVALID = '82629';
+ const MERCHANT_ACCOUNT_APPLICANT_DETAILS_ADDRESS_STREET_ADDRESS_IS_REQUIRED = '82617';
+
+ const MERCHANT_ACCOUNT_BUSINESS_DBA_NAME_IS_INVALID = '82646';
+ const MERCHANT_ACCOUNT_BUSINESS_TAX_ID_IS_INVALID = '82647';
+ const MERCHANT_ACCOUNT_BUSINESS_TAX_ID_IS_REQUIRED_WITH_LEGAL_NAME = '82648';
+ const MERCHANT_ACCOUNT_BUSINESS_LEGAL_NAME_IS_REQUIRED_WITH_TAX_ID = '82669';
+ const MERCHANT_ACCOUNT_BUSINESS_TAX_ID_MUST_BE_BLANK = '82672';
+ const MERCHANT_ACCOUNT_BUSINESS_LEGAL_NAME_IS_INVALID = '82677';
+ const MERCHANT_ACCOUNT_BUSINESS_ADDRESS_REGION_IS_INVALID = '82684';
+ const MERCHANT_ACCOUNT_BUSINESS_ADDRESS_STREET_ADDRESS_IS_INVALID = '82685';
+ const MERCHANT_ACCOUNT_BUSINESS_ADDRESS_POSTAL_CODE_IS_INVALID = '82686';
+
+ const MERCHANT_ACCOUNT_INDIVIDUAL_FIRST_NAME_IS_REQUIRED = '82637';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_LAST_NAME_IS_REQUIRED = '82638';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_DATE_OF_BIRTH_IS_REQUIRED = '82639';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_SSN_IS_INVALID = '82642';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_EMAIL_IS_INVALID = '82643';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_FIRST_NAME_IS_INVALID = '82644';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_LAST_NAME_IS_INVALID = '82645';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_PHONE_IS_INVALID = '82656';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_DATE_OF_BIRTH_IS_INVALID = '82666';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_EMAIL_IS_REQUIRED = '82667';
+
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_STREET_ADDRESS_IS_REQUIRED = '82657';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_LOCALITY_IS_REQUIRED = '82658';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_POSTAL_CODE_IS_REQUIRED = '82659';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_REGION_IS_REQUIRED = '82660';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_STREET_ADDRESS_IS_INVALID = '82661';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_POSTAL_CODE_IS_INVALID = '82662';
+ const MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_REGION_IS_INVALID = '82668';
+
+ const MERCHANT_ACCOUNT_FUNDING_ROUTING_NUMBER_IS_REQUIRED = '82640';
+ const MERCHANT_ACCOUNT_FUNDING_ACCOUNT_NUMBER_IS_REQUIRED = '82641';
+ const MERCHANT_ACCOUNT_FUNDING_ROUTING_NUMBER_IS_INVALID = '82649';
+ const MERCHANT_ACCOUNT_FUNDING_ACCOUNT_NUMBER_IS_INVALID = '82671';
+ const MERCHANT_ACCOUNT_FUNDING_DESTINATION_IS_REQUIRED = '82678';
+ const MERCHANT_ACCOUNT_FUNDING_DESTINATION_IS_INVALID = '82679';
+ const MERCHANT_ACCOUNT_FUNDING_EMAIL_IS_REQUIRED = '82680';
+ const MERCHANT_ACCOUNT_FUNDING_EMAIL_IS_INVALID = '82681';
+ const MERCHANT_ACCOUNT_FUNDING_MOBILE_PHONE_IS_REQUIRED = '82682';
+ const MERCHANT_ACCOUNT_FUNDING_MOBILE_PHONE_IS_INVALID = '82683';
+
+ const OAUTH_INVALID_GRANT = '93801';
+ const OAUTH_INVALID_CREDENTIALS = '93802';
+ const OAUTH_INVALID_SCOPE = '93803';
+ const OAUTH_INVALID_REQUEST = '93804';
+ const OAUTH_UNSUPPORTED_GRANT_TYPE = '93805';
+
+ const PAYMENT_METHOD_CANNOT_FORWARD_PAYMENT_METHOD_TYPE = '93106';
+ const PAYMENT_METHOD_CUSTOMER_ID_IS_INVALID = '93105';
+ const PAYMENT_METHOD_CUSTOMER_ID_IS_REQUIRED = '93104';
+ const PAYMENT_METHOD_NONCE_IS_INVALID = '93102';
+ const PAYMENT_METHOD_NONCE_IS_REQUIRED = '93103';
+ const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_CONSUMED = '93107';
+ const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_UNKNOWN = '93108';
+ const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_LOCKED = '93109';
+ const PAYMENT_METHOD_PAYMENT_METHOD_PARAMS_ARE_REQUIRED = '93101';
+
+ const PAYPAL_ACCOUNT_AUTH_EXPIRED = '92911';
+ const PAYPAL_ACCOUNT_CANNOT_HAVE_BOTH_ACCESS_TOKEN_AND_CONSENT_CODE = '82903';
+ const PAYPAL_ACCOUNT_CANNOT_HAVE_FUNDING_SOURCE_WITHOUT_ACCESS_TOKEN = '92912';
+ const PAYPAL_ACCOUNT_CANNOT_UPDATE_PAYPAL_ACCOUNT_USING_PAYMENT_METHOD_NONCE = '92914';
+ const PAYPAL_ACCOUNT_CANNOT_VAULT_ONE_TIME_USE_PAYPAL_ACCOUNT = '82902';
+ const PAYPAL_ACCOUNT_CONSENT_CODE_OR_ACCESS_TOKEN_IS_REQUIRED = '82901';
+ const PAYPAL_ACCOUNT_CUSTOMER_ID_IS_REQUIRED_FOR_VAULTING = '82905';
+ const PAYPAL_ACCOUNT_INVALID_FUNDING_SOURCE_SELECTION = '92913';
+ const PAYPAL_ACCOUNT_INVALID_PARAMS_FOR_PAYPAL_ACCOUNT_UPDATE = '92915';
+ const PAYPAL_ACCOUNT_PAYMENT_METHOD_NONCE_CONSUMED = '92907';
+ const PAYPAL_ACCOUNT_PAYMENT_METHOD_NONCE_LOCKED = '92909';
+ const PAYPAL_ACCOUNT_PAYMENT_METHOD_NONCE_UNKNOWN = '92908';
+ const PAYPAL_ACCOUNT_PAYPAL_ACCOUNTS_ARE_NOT_ACCEPTED = '82904';
+ const PAYPAL_ACCOUNT_PAYPAL_COMMUNICATION_ERROR = '92910';
+ const PAYPAL_ACCOUNT_TOKEN_IS_IN_USE = '92906';
+
+ const SEPA_BANK_ACCOUNT_ACCOUNT_HOLDER_NAME_IS_REQUIRED = '93003';
+ const SEPA_BANK_ACCOUNT_BIC_IS_REQUIRED = '93002';
+ const SEPA_BANK_ACCOUNT_IBAN_IS_REQUIRED = '93001';
+
+ const SEPA_MANDATE_ACCOUNT_HOLDER_NAME_IS_REQUIRED = '83301';
+ const SEPA_MANDATE_BIC_INVALID_CHARACTER = '83306';
+ const SEPA_MANDATE_BIC_IS_REQUIRED = '83302';
+ const SEPA_MANDATE_BIC_LENGTH_IS_INVALID = '83307';
+ const SEPA_MANDATE_BIC_UNSUPPORTED_COUNTRY = '83308';
+ const SEPA_MANDATE_BILLING_ADDRESS_CONFLICT = '93311';
+ const SEPA_MANDATE_BILLING_ADDRESS_ID_IS_INVALID = '93312';
+ const SEPA_MANDATE_IBAN_INVALID_CHARACTER = '83305';
+ const SEPA_MANDATE_IBAN_INVALID_FORMAT = '83310';
+ const SEPA_MANDATE_IBAN_IS_REQUIRED = '83303';
+ const SEPA_MANDATE_IBAN_UNSUPPORTED_COUNTRY = '83309';
+ const SEPA_MANDATE_TYPE_IS_REQUIRED = '93304';
+ const SEPA_MANDATE_TYPE_IS_INVALID = '93313';
+
+ const SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_INVALID = '82302';
+ const SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_REQUIRED = '82301';
+ const SETTLEMENT_BATCH_SUMMARY_CUSTOM_FIELD_IS_INVALID = '82303';
+
+ const SUBSCRIPTION_BILLING_DAY_OF_MONTH_CANNOT_BE_UPDATED = '91918';
+ const SUBSCRIPTION_BILLING_DAY_OF_MONTH_IS_INVALID = '91914';
+ const SUBSCRIPTION_BILLING_DAY_OF_MONTH_MUST_BE_NUMERIC = '91913';
+ const SUBSCRIPTION_CANNOT_ADD_DUPLICATE_ADDON_OR_DISCOUNT = '91911';
+ const SUBSCRIPTION_CANNOT_EDIT_CANCELED_SUBSCRIPTION = '81901';
+ const SUBSCRIPTION_CANNOT_EDIT_EXPIRED_SUBSCRIPTION = '81910';
+ const SUBSCRIPTION_CANNOT_EDIT_PRICE_CHANGING_FIELDS_ON_PAST_DUE_SUBSCRIPTION = '91920';
+ const SUBSCRIPTION_FIRST_BILLING_DATE_CANNOT_BE_IN_THE_PAST = '91916';
+ const SUBSCRIPTION_FIRST_BILLING_DATE_CANNOT_BE_UPDATED = '91919';
+ const SUBSCRIPTION_FIRST_BILLING_DATE_IS_INVALID = '91915';
+ const SUBSCRIPTION_ID_IS_IN_USE = '81902';
+ const SUBSCRIPTION_INCONSISTENT_NUMBER_OF_BILLING_CYCLES = '91908';
+ const SUBSCRIPTION_INCONSISTENT_START_DATE = '91917';
+ const SUBSCRIPTION_INVALID_REQUEST_FORMAT = '91921';
+ const SUBSCRIPTION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91901';
+ const SUBSCRIPTION_MISMATCH_CURRENCY_ISO_CODE = '91923';
+ const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_CANNOT_BE_BLANK = '91912';
+ const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_IS_TOO_SMALL = '91909';
+ const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_MUST_BE_GREATER_THAN_ZERO = '91907';
+ const SUBSCRIPTION_NUMBER_OF_BILLING_CYCLES_MUST_BE_NUMERIC = '91906';
+ const SUBSCRIPTION_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91924';
+ const SUBSCRIPTION_PAYMENT_METHOD_NONCE_IS_INVALID = '91925';
+ const SUBSCRIPTION_PAYMENT_METHOD_NONCE_NOT_ASSOCIATED_WITH_CUSTOMER = '91926';
+ const SUBSCRIPTION_PAYMENT_METHOD_NONCE_UNVAULTED_CARD_IS_NOT_ACCEPTED = '91927';
+ const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_CARD_TYPE_IS_NOT_ACCEPTED = '91902';
+ const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_IS_INVALID = '91903';
+ const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_NOT_ASSOCIATED_WITH_CUSTOMER = '91905';
+ const SUBSCRIPTION_PLAN_BILLING_FREQUENCY_CANNOT_BE_UPDATED = '91922';
+ const SUBSCRIPTION_PLAN_ID_IS_INVALID = '91904';
+ const SUBSCRIPTION_PRICE_CANNOT_BE_BLANK = '81903';
+ const SUBSCRIPTION_PRICE_FORMAT_IS_INVALID = '81904';
+ const SUBSCRIPTION_PRICE_IS_TOO_LARGE = '81923';
+ const SUBSCRIPTION_STATUS_IS_CANCELED = '81905';
+ const SUBSCRIPTION_TOKEN_FORMAT_IS_INVALID = '81906';
+ const SUBSCRIPTION_TRIAL_DURATION_FORMAT_IS_INVALID = '81907';
+ const SUBSCRIPTION_TRIAL_DURATION_IS_REQUIRED = '81908';
+ const SUBSCRIPTION_TRIAL_DURATION_UNIT_IS_INVALID = '81909';
+ const SUBSCRIPTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_INSTRUMENT_TYPE = '91930';
+ const SUBSCRIPTION_PAYMENT_METHOD_NONCE_INSTRUMENT_TYPE_DOES_NOT_SUPPORT_SUBSCRIPTIONS = '91929';
+ const SUBSCRIPTION_PAYMENT_METHOD_TOKEN_INSTRUMENT_TYPE_DOES_NOT_SUPPORT_SUBSCRIPTIONS = '91928';
+
+ const SUBSCRIPTION_MODIFICATION_AMOUNT_CANNOT_BE_BLANK = '92003';
+ const SUBSCRIPTION_MODIFICATION_AMOUNT_IS_INVALID = '92002';
+ const SUBSCRIPTION_MODIFICATION_AMOUNT_IS_TOO_LARGE = '92023';
+ const SUBSCRIPTION_MODIFICATION_CANNOT_EDIT_MODIFICATIONS_ON_PAST_DUE_SUBSCRIPTION = '92022';
+ const SUBSCRIPTION_MODIFICATION_CANNOT_UPDATE_AND_REMOVE = '92015';
+ const SUBSCRIPTION_MODIFICATION_EXISTING_ID_IS_INCORRECT_KIND = '92020';
+ const SUBSCRIPTION_MODIFICATION_EXISTING_ID_IS_INVALID = '92011';
+ const SUBSCRIPTION_MODIFICATION_EXISTING_ID_IS_REQUIRED = '92012';
+ const SUBSCRIPTION_MODIFICATION_ID_TO_REMOVE_IS_INCORRECT_KIND = '92021';
+ const SUBSCRIPTION_MODIFICATION_ID_TO_REMOVE_IS_INVALID = '92025';
+ const SUBSCRIPTION_MODIFICATION_ID_TO_REMOVE_IS_NOT_PRESENT = '92016';
+ const SUBSCRIPTION_MODIFICATION_INCONSISTENT_NUMBER_OF_BILLING_CYCLES = '92018';
+ const SUBSCRIPTION_MODIFICATION_INHERITED_FROM_ID_IS_INVALID = '92013';
+ const SUBSCRIPTION_MODIFICATION_INHERITED_FROM_ID_IS_REQUIRED = '92014';
+ const SUBSCRIPTION_MODIFICATION_MISSING = '92024';
+ const SUBSCRIPTION_MODIFICATION_NUMBER_OF_BILLING_CYCLES_CANNOT_BE_BLANK = '92017';
+ const SUBSCRIPTION_MODIFICATION_NUMBER_OF_BILLING_CYCLES_IS_INVALID = '92005';
+ const SUBSCRIPTION_MODIFICATION_NUMBER_OF_BILLING_CYCLES_MUST_BE_GREATER_THAN_ZERO = '92019';
+ const SUBSCRIPTION_MODIFICATION_QUANTITY_CANNOT_BE_BLANK = '92004';
+ const SUBSCRIPTION_MODIFICATION_QUANTITY_IS_INVALID = '92001';
+ const SUBSCRIPTION_MODIFICATION_QUANTITY_MUST_BE_GREATER_THAN_ZERO = '92010';
+
+ const TRANSACTION_AMOUNT_CANNOT_BE_NEGATIVE = '81501';
+ const TRANSACTION_AMOUNT_DOES_NOT_MATCH3_D_SECURE_AMOUNT = '91585';
+ const TRANSACTION_AMOUNT_FORMAT_IS_INVALID = '81503';
+ const TRANSACTION_AMOUNT_IS_INVALID = '81503';
+ const TRANSACTION_AMOUNT_IS_REQUIRED = '81502';
+ const TRANSACTION_AMOUNT_IS_TOO_LARGE = '81528';
+ const TRANSACTION_AMOUNT_MUST_BE_GREATER_THAN_ZERO = '81531';
+ const TRANSACTION_BILLING_ADDRESS_CONFLICT = '91530';
+ const TRANSACTION_CANNOT_BE_VOIDED = '91504';
+ const TRANSACTION_CANNOT_CANCEL_RELEASE = '91562';
+ const TRANSACTION_CANNOT_CLONE_CREDIT = '91543';
+ const TRANSACTION_CANNOT_CLONE_TRANSACTION_WITH_PAYPAL_ACCOUNT = '91573';
+ const TRANSACTION_CANNOT_CLONE_TRANSACTION_WITH_VAULT_CREDIT_CARD = '91540';
+ const TRANSACTION_CANNOT_CLONE_UNSUCCESSFUL_TRANSACTION = '91542';
+ const TRANSACTION_CANNOT_CLONE_VOICE_AUTHORIZATIONS = '91541';
+ const TRANSACTION_CANNOT_HOLD_IN_ESCROW = '91560';
+ const TRANSACTION_CANNOT_PARTIALLY_REFUND_ESCROWED_TRANSACTION = '91563';
+ const TRANSACTION_CANNOT_REFUND_CREDIT = '91505';
+ const TRANSACTION_CANNOT_REFUND_SETTLING_TRANSACTION = '91574';
+ const TRANSACTION_CANNOT_REFUND_UNLESS_SETTLED = '91506';
+ const TRANSACTION_CANNOT_REFUND_WITH_PENDING_MERCHANT_ACCOUNT = '91559';
+ const TRANSACTION_CANNOT_REFUND_WITH_SUSPENDED_MERCHANT_ACCOUNT = '91538';
+ const TRANSACTION_CANNOT_RELEASE_FROM_ESCROW = '91561';
+ const TRANSACTION_CANNOT_SIMULATE_SETTLEMENT = '91575';
+ const TRANSACTION_CANNOT_SUBMIT_FOR_SETTLEMENT = '91507';
+ const TRANSACTION_CHANNEL_IS_TOO_LONG = '91550';
+ const TRANSACTION_CREDIT_CARD_IS_REQUIRED = '91508';
+ const TRANSACTION_CUSTOMER_DEFAULT_PAYMENT_METHOD_CARD_TYPE_IS_NOT_ACCEPTED = '81509';
+ const TRANSACTION_CUSTOMER_DOES_NOT_HAVE_CREDIT_CARD = '91511';
+ const TRANSACTION_CUSTOMER_ID_IS_INVALID = '91510';
+ const TRANSACTION_CUSTOM_FIELD_IS_INVALID = '91526';
+ const TRANSACTION_CUSTOM_FIELD_IS_TOO_LONG = '81527';
+ const TRANSACTION_HAS_ALREADY_BEEN_REFUNDED = '91512';
+ const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_MATCH3_D_SECURE_MERCHANT_ACCOUNT = '91584';
+ const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_MOTO = '91558';
+ const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_REFUNDS = '91547';
+ const TRANSACTION_MERCHANT_ACCOUNT_ID_IS_INVALID = '91513';
+ const TRANSACTION_MERCHANT_ACCOUNT_IS_SUSPENDED = '91514';
+ const TRANSACTION_MERCHANT_ACCOUNT_NAME_IS_INVALID = '91513'; //Deprecated
+ const TRANSACTION_OPTIONS_PAY_PAL_CUSTOM_FIELD_TOO_LONG = '91580';
+ const TRANSACTION_OPTIONS_SUBMIT_FOR_SETTLEMENT_IS_REQUIRED_FOR_CLONING = '91544';
+ const TRANSACTION_OPTIONS_SUBMIT_FOR_SETTLEMENT_IS_REQUIRED_FOR_PAYPAL_UNILATERAL = '91582';
+ const TRANSACTION_OPTIONS_USE_BILLING_FOR_SHIPPING_DISABLED = '91572';
+ const TRANSACTION_OPTIONS_VAULT_IS_DISABLED = '91525';
+ const TRANSACTION_ORDER_ID_IS_TOO_LONG = '91501';
+ const TRANSACTION_PAYMENT_INSTRUMENT_NOT_SUPPORTED_BY_MERCHANT_ACCOUNT = '91577';
+ const TRANSACTION_PAYMENT_METHOD_CONFLICT = '91515';
+ const TRANSACTION_PAYMENT_METHOD_CONFLICT_WITH_VENMO_SDK = '91549';
+ const TRANSACTION_PAYMENT_METHOD_DOES_NOT_BELONG_TO_CUSTOMER = '91516';
+ const TRANSACTION_PAYMENT_METHOD_DOES_NOT_BELONG_TO_SUBSCRIPTION = '91527';
+ const TRANSACTION_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = '91567';
+ const TRANSACTION_PAYMENT_METHOD_NONCE_CONSUMED = '91564';
+ const TRANSACTION_PAYMENT_METHOD_NONCE_HAS_NO_VALID_PAYMENT_INSTRUMENT_TYPE = '91569';
+ const TRANSACTION_PAYMENT_METHOD_NONCE_LOCKED = '91566';
+ const TRANSACTION_PAYMENT_METHOD_NONCE_UNKNOWN = '91565';
+ const TRANSACTION_PAYMENT_METHOD_TOKEN_CARD_TYPE_IS_NOT_ACCEPTED = '91517';
+ const TRANSACTION_PAYMENT_METHOD_TOKEN_IS_INVALID = '91518';
+ const TRANSACTION_PAYPAL_NOT_ENABLED = '91576';
+ const TRANSACTION_PAY_PAL_AUTH_EXPIRED = '91579';
+ const TRANSACTION_PAY_PAL_VAULT_RECORD_MISSING_DATA = '91583';
+ const TRANSACTION_PROCESSOR_AUTHORIZATION_CODE_CANNOT_BE_SET = '91519';
+ const TRANSACTION_PROCESSOR_AUTHORIZATION_CODE_IS_INVALID = '81520';
+ const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_CREDITS = '91546';
+ const TRANSACTION_PROCESSOR_DOES_NOT_SUPPORT_VOICE_AUTHORIZATIONS = '91545';
+ const TRANSACTION_PURCHASE_ORDER_NUMBER_IS_INVALID = '91548';
+ const TRANSACTION_PURCHASE_ORDER_NUMBER_IS_TOO_LONG = '91537';
+ const TRANSACTION_REFUND_AMOUNT_IS_TOO_LARGE = '91521';
+ const TRANSACTION_SERVICE_FEE_AMOUNT_CANNOT_BE_NEGATIVE = '91554';
+ const TRANSACTION_SERVICE_FEE_AMOUNT_FORMAT_IS_INVALID = '91555';
+ const TRANSACTION_SERVICE_FEE_AMOUNT_IS_TOO_LARGE = '91556';
+ const TRANSACTION_SERVICE_FEE_AMOUNT_NOT_ALLOWED_ON_MASTER_MERCHANT_ACCOUNT = '91557';
+ const TRANSACTION_SERVICE_FEE_IS_NOT_ALLOWED_ON_CREDITS = '91552';
+ const TRANSACTION_SERVICE_FEE_NOT_ACCEPTED_FOR_PAYPAL = '91578';
+ const TRANSACTION_SETTLEMENT_AMOUNT_IS_LESS_THAN_SERVICE_FEE_AMOUNT = '91551';
+ const TRANSACTION_SETTLEMENT_AMOUNT_IS_TOO_LARGE = '91522';
+ const TRANSACTION_SHIPPING_ADDRESS_DOESNT_MATCH_CUSTOMER = '91581';
+ const TRANSACTION_SUBSCRIPTION_DOES_NOT_BELONG_TO_CUSTOMER = '91529';
+ const TRANSACTION_SUBSCRIPTION_ID_IS_INVALID = '91528';
+ const TRANSACTION_SUBSCRIPTION_STATUS_MUST_BE_PAST_DUE = '91531';
+ const TRANSACTION_SUB_MERCHANT_ACCOUNT_REQUIRES_SERVICE_FEE_AMOUNT = '91553';
+ const TRANSACTION_TAX_AMOUNT_CANNOT_BE_NEGATIVE = '81534';
+ const TRANSACTION_TAX_AMOUNT_FORMAT_IS_INVALID = '81535';
+ const TRANSACTION_TAX_AMOUNT_IS_TOO_LARGE = '81536';
+
+ const TRANSACTION_THREE_D_SECURE_AUTHENTICATION_FAILED = '81571';
+ const TRANSACTION_THREE_D_SECURE_TOKEN_IS_INVALID = '91568';
+ const TRANSACTION_THREE_D_SECURE_TRANSACTION_DATA_DOESNT_MATCH_VERIFY = '91570';
+ const TRANSACTION_TYPE_IS_INVALID = '91523';
+ const TRANSACTION_TYPE_IS_REQUIRED = '91524';
+ const TRANSACTION_UNSUPPORTED_VOICE_AUTHORIZATION = '91539';
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ErrorCollection.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ErrorCollection.php
new file mode 100644
index 0000000..47cd384
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ErrorCollection.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ *
+ * Error handler
+ * Handles validation errors
+ *
+ * Contains a read-only property $error which is a ValidationErrorCollection
+ *
+ * @package Braintree
+ * @subpackage Errors
+ * @category Errors
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read object $errors
+ */
+class Braintree_Error_ErrorCollection
+{
+ private $_errors;
+
+ public function __construct($errorData)
+ {
+ $this->_errors =
+ new Braintree_Error_ValidationErrorCollection($errorData);
+ }
+
+
+ /**
+ * Returns all of the validation errors at all levels of nesting in a single, flat array.
+ */
+ public function deepAll()
+ {
+ return $this->_errors->deepAll();
+ }
+
+ /**
+ * Returns the total number of validation errors at all levels of nesting. For example,
+ *if creating a customer with a credit card and a billing address, and each of the customer,
+ * credit card, and billing address has 1 error, this method will return 3.
+ *
+ * @return int size
+ */
+ public function deepSize()
+ {
+ $size = $this->_errors->deepSize();
+ return $size;
+ }
+
+ /**
+ * return errors for the passed key name
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function forKey($key)
+ {
+ return $this->_errors->forKey($key);
+ }
+
+ /**
+ * return errors for the passed html field.
+ * For example, $result->errors->onHtmlField("transaction[customer][last_name]")
+ *
+ * @param string $field
+ * @return array
+ */
+ public function onHtmlField($field)
+ {
+ $pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY);
+ $errors = $this;
+ foreach(array_slice($pieces, 0, -1) as $key) {
+ $errors = $errors->forKey(Braintree_Util::delimiterToCamelCase($key));
+ if (!isset($errors)) { return array(); }
+ }
+ $finalKey = Braintree_Util::delimiterToCamelCase(end($pieces));
+ return $errors->onAttribute($finalKey);
+ }
+
+ /**
+ * Returns the errors at the given nesting level (see forKey) in a single, flat array:
+ *
+ * <code>
+ * $result = Braintree_Customer::create(...);
+ * $customerErrors = $result->errors->forKey('customer')->shallowAll();
+ * </code>
+ */
+ public function shallowAll()
+ {
+ return $this->_errors->shallowAll();
+ }
+
+ /**
+ *
+ * @ignore
+ */
+ public function __get($name)
+ {
+ $varName = "_$name";
+ return isset($this->$varName) ? $this->$varName : null;
+ }
+
+ /**
+ *
+ * @ignore
+ */
+ public function __toString()
+ {
+ return sprintf('%s', $this->_errors);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Validation.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Validation.php
new file mode 100644
index 0000000..2624f5c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/Validation.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * error object returned as part of a validation error collection
+ * provides read-only access to $attribute, $code, and $message
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Validation errors, see {@link http://www.braintreepayments.com/gateway/validation-errors http://www.braintreepaymentsolutions.com/gateway/validation-errors}
+ *
+ * @package Braintree
+ * @subpackage Error
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $attribute
+ * @property-read string $code
+ * @property-read string $message
+ */
+class Braintree_Error_Validation
+{
+ private $_attribute;
+ private $_code;
+ private $_message;
+
+ /**
+ * @ignore
+ * @param array $attributes
+ */
+ public function __construct($attributes)
+ {
+ $this->_initializeFromArray($attributes);
+ }
+ /**
+ * initializes instance properties from the keys/values of an array
+ * @ignore
+ * @access protected
+ * @param array $attributes array of properties to set - single level
+ * @return none
+ */
+ private function _initializeFromArray($attributes)
+ {
+ foreach($attributes AS $name => $value) {
+ $varName = "_$name";
+ $this->$varName = Braintree_Util::delimiterToCamelCase($value, '_');
+ }
+ }
+
+ /**
+ *
+ * @ignore
+ */
+ public function __get($name)
+ {
+ $varName = "_$name";
+ return isset($this->$varName) ? $this->$varName : null;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ValidationErrorCollection.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ValidationErrorCollection.php
new file mode 100644
index 0000000..2bd2297
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Error/ValidationErrorCollection.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * collection of errors enumerating all validation errors for a given request
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Validation errors, see {@link http://www.braintreepayments.com/gateway/validation-errors http://www.braintreepaymentsolutions.com/gateway/validation-errors}
+ *
+ * @package Braintree
+ * @subpackage Error
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read array $errors
+ * @property-read array $nested
+ */
+class Braintree_Error_ValidationErrorCollection extends Braintree_Collection
+{
+ private $_errors = array();
+ private $_nested = array();
+
+ /**
+ * @ignore
+ */
+ public function __construct($data)
+ {
+ foreach($data AS $key => $errorData)
+ // map errors to new collections recursively
+ if ($key == 'errors') {
+ foreach ($errorData AS $error) {
+ $this->_errors[] = new Braintree_Error_Validation($error);
+ }
+ } else {
+ $this->_nested[$key] = new Braintree_Error_ValidationErrorCollection($errorData);
+ }
+
+ }
+
+ public function deepAll()
+ {
+ $validationErrors = array_merge(array(), $this->_errors);
+ foreach($this->_nested as $nestedErrors)
+ {
+ $validationErrors = array_merge($validationErrors, $nestedErrors->deepAll());
+ }
+ return $validationErrors;
+ }
+
+ public function deepSize()
+ {
+ $total = sizeof($this->_errors);
+ foreach($this->_nested as $_nestedErrors)
+ {
+ $total = $total + $_nestedErrors->deepSize();
+ }
+ return $total;
+ }
+
+ public function forIndex($index)
+ {
+ return $this->forKey("index" . $index);
+ }
+
+ public function forKey($key)
+ {
+ return isset($this->_nested[$key]) ? $this->_nested[$key] : null;
+ }
+
+ public function onAttribute($attribute)
+ {
+ $matches = array();
+ foreach ($this->_errors AS $key => $error) {
+ if($error->attribute == $attribute) {
+ $matches[] = $error;
+ }
+ }
+ return $matches;
+ }
+
+
+ public function shallowAll()
+ {
+ return $this->_errors;
+ }
+
+ /**
+ *
+ * @ignore
+ */
+ public function __get($name)
+ {
+ $varName = "_$name";
+ return isset($this->$varName) ? $this->$varName : null;
+ }
+
+ /**
+ * @ignore
+ */
+ public function __toString()
+ {
+ $output = array();
+
+ // TODO: implement scope
+ if (!empty($this->_errors)) {
+ $output[] = $this->_inspect($this->_errors);
+ }
+ if (!empty($this->_nested)) {
+ foreach ($this->_nested AS $key => $values) {
+ $output[] = $this->_inspect($this->_nested);
+ }
+ }
+ return join(', ', $output);
+ }
+
+ /**
+ * @ignore
+ */
+ private function _inspect($errors, $scope = null)
+ {
+ $eOutput = '[' . __CLASS__ . '/errors:[';
+ foreach($errors AS $error => $errorObj) {
+ $outputErrs[] = "({$errorObj->error['code']} {$errorObj->error['message']})";
+ }
+ $eOutput .= join(', ', $outputErrs) . ']]';
+
+ return $eOutput;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception.php
new file mode 100644
index 0000000..0e2b920
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * super class for all Braintree exceptions
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception extends Exception
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authentication.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authentication.php
new file mode 100644
index 0000000..41930c3
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authentication.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Raised when authentication fails.
+ * This may be caused by an incorrect Braintree_Configuration
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_Authentication extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authorization.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authorization.php
new file mode 100644
index 0000000..eaed638
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Authorization.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Raised when authorization fails
+ * Raised when the API key being used is not authorized to perform
+ * the attempted action according to the roles assigned to the user
+ * who owns the API key.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_Authorization extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Configuration.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Configuration.php
new file mode 100644
index 0000000..22c6594
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Configuration.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when the Braintree library is not completely configured.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @see Braintree_Configuration
+ */
+class Braintree_Exception_Configuration extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/DownForMaintenance.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/DownForMaintenance.php
new file mode 100644
index 0000000..9d0a897
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/DownForMaintenance.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when the gateway is down for maintenance.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_DownForMaintenance extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ForgedQueryString.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ForgedQueryString.php
new file mode 100644
index 0000000..8851230
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ForgedQueryString.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Raised when a suspected forged query string is present
+ * Raised from methods that confirm transparent redirect requests
+ * when the given query string cannot be verified. This may indicate
+ * an attempted hack on the merchant's transparent redirect
+ * confirmation URL.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_ForgedQueryString extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidChallenge.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidChallenge.php
new file mode 100644
index 0000000..a27ff0a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidChallenge.php
@@ -0,0 +1,5 @@
+<?php
+class Braintree_Exception_InvalidChallenge extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidSignature.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidSignature.php
new file mode 100644
index 0000000..0c31a2d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/InvalidSignature.php
@@ -0,0 +1,5 @@
+<?php
+class Braintree_Exception_InvalidSignature extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/NotFound.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/NotFound.php
new file mode 100644
index 0000000..5f96b86
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/NotFound.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when a record could not be found.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_NotFound extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCaFileNotFound.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCaFileNotFound.php
new file mode 100644
index 0000000..ad42f03
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCaFileNotFound.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when the SSL CaFile is not found.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_SSLCaFileNotFound extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCertificate.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCertificate.php
new file mode 100644
index 0000000..a50b807
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/SSLCertificate.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when the SSL certificate fails verification.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_SSLCertificate extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ServerError.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ServerError.php
new file mode 100644
index 0000000..57e2815
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ServerError.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when an unexpected server error occurs.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_ServerError extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Unexpected.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Unexpected.php
new file mode 100644
index 0000000..c30ec28
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/Unexpected.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Raised when an error occurs that the client library is not built to handle.
+ * This shouldn't happen.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_Unexpected extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/UpgradeRequired.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/UpgradeRequired.php
new file mode 100644
index 0000000..95a22fa
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/UpgradeRequired.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised when a client library must be upgraded.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_UpgradeRequired extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ValidationsFailed.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ValidationsFailed.php
new file mode 100644
index 0000000..aa58e18
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Exception/ValidationsFailed.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Raised from non-validating methods when gateway validations fail.
+ *
+ * @package Braintree
+ * @subpackage Exception
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Exception_ValidationsFailed extends Braintree_Exception
+{
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Gateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Gateway.php
new file mode 100644
index 0000000..cba3455
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Gateway.php
@@ -0,0 +1,186 @@
+<?php
+/**
+ * Braintree Gateway module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Gateway
+{
+ /**
+ *
+ * @var Braintree_Configuration
+ */
+ public $config;
+
+ public function __construct($config)
+ {
+ if (is_array($config)) {
+ $config = new Braintree_Configuration($config);
+ }
+ $this->config = $config;
+ }
+
+ /**
+ *
+ * @return \Braintree_AddOnGateway
+ */
+ public function addOn()
+ {
+ return new Braintree_AddOnGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_AddressGateway
+ */
+ public function address()
+ {
+ return new Braintree_AddressGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_ClientTokenGateway
+ */
+ public function clientToken()
+ {
+ return new Braintree_ClientTokenGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_CreditCardGateway
+ */
+ public function creditCard()
+ {
+ return new Braintree_CreditCardGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_CreditCardVerificationGateway
+ */
+ public function creditCardVerification()
+ {
+ return new Braintree_CreditCardVerificationGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_CustomerGateway
+ */
+ public function customer()
+ {
+ return new Braintree_CustomerGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_DiscountGateway
+ */
+ public function discount()
+ {
+ return new Braintree_DiscountGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_MerchantGateway
+ */
+ public function merchant()
+ {
+ return new Braintree_MerchantGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_MerchantAccountGateway
+ */
+ public function merchantAccount()
+ {
+ return new Braintree_MerchantAccountGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_OAuthGateway
+ */
+ public function oauth()
+ {
+ return new Braintree_OAuthGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_PaymentMethodGateway
+ */
+ public function paymentMethod()
+ {
+ return new Braintree_PaymentMethodGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_PaymentMethodNonceGateway
+ */
+ public function paymentMethodNonce()
+ {
+ return new Braintree_PaymentMethodNonceGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_PayPalAccountGateway
+ */
+ public function payPalAccount()
+ {
+ return new Braintree_PayPalAccountGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_PlanGateway
+ */
+ public function plan()
+ {
+ return new Braintree_PlanGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_SettlementBatchSummaryGateway
+ */
+ public function settlementBatchSummary()
+ {
+ return new Braintree_SettlementBatchSummaryGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_SubscriptionGateway
+ */
+ public function subscription()
+ {
+ return new Braintree_SubscriptionGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_TransactionGateway
+ */
+ public function transaction()
+ {
+ return new Braintree_TransactionGateway($this);
+ }
+
+ /**
+ *
+ * @return \Braintree_TransparentRedirectGateway
+ */
+ public function transparentRedirect()
+ {
+ return new Braintree_TransparentRedirectGateway($this);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Http.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Http.php
new file mode 100644
index 0000000..8c2d065
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Http.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Braintree HTTP Client
+ * processes Http requests using curl
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Http
+{
+ protected $_config;
+ private $_useClientCredentials = false;
+
+ public function __construct($config)
+ {
+ $this->_config = $config;
+ }
+
+ public function delete($path)
+ {
+ $response = $this->_doRequest('DELETE', $path);
+ if($response['status'] === 200) {
+ return true;
+ } else {
+ Braintree_Util::throwStatusCodeException($response['status']);
+ }
+ }
+
+ public function get($path)
+ {
+ $response = $this->_doRequest('GET', $path);
+ if($response['status'] === 200) {
+ return Braintree_Xml::buildArrayFromXml($response['body']);
+ } else {
+ Braintree_Util::throwStatusCodeException($response['status']);
+ }
+ }
+
+ public function post($path, $params = null)
+ {
+ $response = $this->_doRequest('POST', $path, $this->_buildXml($params));
+ $responseCode = $response['status'];
+ if($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) {
+ return Braintree_Xml::buildArrayFromXml($response['body']);
+ } else {
+ Braintree_Util::throwStatusCodeException($responseCode);
+ }
+ }
+
+ public function put($path, $params = null)
+ {
+ $response = $this->_doRequest('PUT', $path, $this->_buildXml($params));
+ $responseCode = $response['status'];
+ if($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) {
+ return Braintree_Xml::buildArrayFromXml($response['body']);
+ } else {
+ Braintree_Util::throwStatusCodeException($responseCode);
+ }
+ }
+
+ private function _buildXml($params)
+ {
+ return empty($params) ? null : Braintree_Xml::buildXmlFromArray($params);
+ }
+
+ private function _getHeaders()
+ {
+ return array(
+ 'Accept: application/xml',
+ 'Content-Type: application/xml',
+ );
+ }
+
+ private function _getAuthorization()
+ {
+ if ($this->_useClientCredentials) {
+ return array(
+ 'user' => $this->_config->getClientId(),
+ 'password' => $this->_config->getClientSecret(),
+ );
+ } else if ($this->_config->isAccessToken()) {
+ return array(
+ 'token' => $this->_config->getAccessToken(),
+ );
+ } else {
+ return array(
+ 'user' => $this->_config->getPublicKey(),
+ 'password' => $this->_config->getPrivateKey(),
+ );
+ }
+ }
+
+ public function useClientCredentials()
+ {
+ $this->_useClientCredentials = true;
+ }
+
+ private function _doRequest($httpVerb, $path, $requestBody = null)
+ {
+ return $this->_doUrlRequest($httpVerb, $this->_config->baseUrl() . $path, $requestBody);
+ }
+
+ public function _doUrlRequest($httpVerb, $url, $requestBody = null)
+ {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_TIMEOUT, 60);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpVerb);
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
+
+ $headers = $this->_getHeaders($curl);
+ $headers[] = 'User-Agent: Braintree PHP Library ' . Braintree_Version::get();
+ $headers[] = 'X-ApiVersion: ' . Braintree_Configuration::API_VERSION;
+
+ $authorization = $this->_getAuthorization();
+ if (isset($authorization['user'])) {
+ curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ curl_setopt($curl, CURLOPT_USERPWD, $authorization['user'] . ':' . $authorization['password']);
+ } else if (isset($authorization['token'])) {
+ $headers[] = 'Authorization: Bearer ' . $authorization['token'];
+ }
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+
+ // curl_setopt($curl, CURLOPT_VERBOSE, true);
+ if ($this->_config->sslOn()) {
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($curl, CURLOPT_CAINFO, $this->_config->caFile());
+ }
+
+ if(!empty($requestBody)) {
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody);
+ }
+
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($curl);
+ $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ curl_close($curl);
+ if ($this->_config->sslOn()) {
+ if ($httpStatus == 0) {
+ throw new Braintree_Exception_SSLCertificate();
+ }
+ }
+ return array('status' => $httpStatus, 'body' => $response);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Instance.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Instance.php
new file mode 100644
index 0000000..821ff05
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Instance.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Braintree Class Instance template
+ * @package Braintree
+ * @subpackage Utility
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ * @abstract
+ */
+abstract class Braintree_Instance
+{
+ /**
+ *
+ * @param array $aAttribs
+ */
+ public function __construct($attributes)
+ {
+ if (!empty($attributes)) {
+ $this->_initializeFromArray($attributes);
+ }
+ }
+
+
+ /**
+ * returns private/nonexistent instance properties
+ * @access public
+ * @param var $name property name
+ * @return mixed contents of instance properties
+ */
+ public function __get($name)
+ {
+ if (array_key_exists($name, $this->_attributes)) {
+ return $this->_attributes[$name];
+ } else {
+ trigger_error('Undefined property on ' . get_class($this) . ': ' . $name, E_USER_NOTICE);
+ return null;
+ }
+ }
+
+ /**
+ * used by isset() and empty()
+ * @access public
+ * @param string $name property name
+ * @return boolean
+ */
+ public function __isset($name)
+ {
+ return array_key_exists($name, $this->_attributes);
+ }
+
+ /**
+ * create a printable representation of the object as:
+ * ClassName[property=value, property=value]
+ * @return var
+ */
+ public function __toString()
+ {
+ $objOutput = Braintree_Util::implodeAssociativeArray($this->_attributes);
+ return get_class($this) .'['.$objOutput.']';
+ }
+ /**
+ * initializes instance properties from the keys/values of an array
+ * @ignore
+ * @access protected
+ * @param <type> $aAttribs array of properties to set - single level
+ * @return none
+ */
+ private function _initializeFromArray($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/IsNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/IsNode.php
new file mode 100644
index 0000000..321fbb3
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/IsNode.php
@@ -0,0 +1,21 @@
+<?php
+
+class Braintree_IsNode
+{
+ function __construct($name)
+ {
+ $this->name = $name;
+ $this->searchTerms = array();
+ }
+
+ function is($value)
+ {
+ $this->searchTerms['is'] = strval($value);
+ return $this;
+ }
+
+ function toParam()
+ {
+ return $this->searchTerms;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/KeyValueNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/KeyValueNode.php
new file mode 100644
index 0000000..ec0cb94
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/KeyValueNode.php
@@ -0,0 +1,22 @@
+<?php
+
+class Braintree_KeyValueNode
+{
+ function __construct($name)
+ {
+ $this->name = $name;
+ $this->searchTerm = True;
+
+ }
+
+ function is($value)
+ {
+ $this->searchTerm = $value;
+ return $this;
+ }
+
+ function toParam()
+ {
+ return $this->searchTerm;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Merchant.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Merchant.php
new file mode 100644
index 0000000..670b61a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Merchant.php
@@ -0,0 +1,26 @@
+<?php
+
+final class Braintree_Merchant extends Braintree_Base
+{
+ protected function _initialize($attribs)
+ {
+ $this->_attributes = $attribs;
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ /**
+ * returns a string representation of the merchant
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount.php
new file mode 100644
index 0000000..6e23baa
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount.php
@@ -0,0 +1,62 @@
+<?php
+
+final class Braintree_MerchantAccount extends Braintree_Base
+{
+ const STATUS_ACTIVE = 'active';
+ const STATUS_PENDING = 'pending';
+ const STATUS_SUSPENDED = 'suspended';
+
+ const FUNDING_DESTINATION_BANK = 'bank';
+ const FUNDING_DESTINATION_EMAIL = 'email';
+ const FUNDING_DESTINATION_MOBILE_PHONE = 'mobile_phone';
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ protected function _initialize($merchantAccountAttribs)
+ {
+ $this->_attributes = $merchantAccountAttribs;
+
+ if (isset($merchantAccountAttribs['individual'])) {
+ $individual = $merchantAccountAttribs['individual'];
+ $this->_set('individualDetails', Braintree_MerchantAccount_IndividualDetails::Factory($individual));
+ }
+
+ if (isset($merchantAccountAttribs['business'])) {
+ $business = $merchantAccountAttribs['business'];
+ $this->_set('businessDetails', Braintree_MerchantAccount_BusinessDetails::Factory($business));
+ }
+
+ if (isset($merchantAccountAttribs['funding'])) {
+ $funding = $merchantAccountAttribs['funding'];
+ $this->_set('fundingDetails', new Braintree_MerchantAccount_FundingDetails($funding));
+ }
+
+ if (isset($merchantAccountAttribs['masterMerchantAccount'])) {
+ $masterMerchantAccount = $merchantAccountAttribs['masterMerchantAccount'];
+ $this->_set('masterMerchantAccount', Braintree_MerchantAccount::Factory($masterMerchantAccount));
+ }
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function create($attribs)
+ {
+ return Braintree_Configuration::gateway()->merchantAccount()->create($attribs);
+ }
+
+ public static function find($merchant_account_id)
+ {
+ return Braintree_Configuration::gateway()->merchantAccount()->find($merchant_account_id);
+ }
+
+ public static function update($merchant_account_id, $attributes)
+ {
+ return Braintree_Configuration::gateway()->merchantAccount()->update($merchant_account_id, $attributes);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/AddressDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/AddressDetails.php
new file mode 100644
index 0000000..15349f6
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/AddressDetails.php
@@ -0,0 +1,5 @@
+<?php
+
+final class Braintree_MerchantAccount_AddressDetails extends Braintree_Instance {
+ protected $_attributes = array();
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/BusinessDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/BusinessDetails.php
new file mode 100644
index 0000000..a25fe9f
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/BusinessDetails.php
@@ -0,0 +1,19 @@
+<?php
+
+final class Braintree_MerchantAccount_BusinessDetails extends Braintree_Base
+{
+ protected function _initialize($businessAttribs)
+ {
+ $this->_attributes = $businessAttribs;
+ if (isset($businessAttribs['address'])) {
+ $this->_set('addressDetails', new Braintree_MerchantAccount_AddressDetails($businessAttribs['address']));
+ }
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/FundingDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/FundingDetails.php
new file mode 100644
index 0000000..f33e595
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/FundingDetails.php
@@ -0,0 +1,6 @@
+<?php
+
+final class Braintree_MerchantAccount_FundingDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/IndividualDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/IndividualDetails.php
new file mode 100644
index 0000000..2f8f4fc
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccount/IndividualDetails.php
@@ -0,0 +1,19 @@
+<?php
+
+final class Braintree_MerchantAccount_IndividualDetails extends Braintree_Base
+{
+ protected function _initialize($individualAttribs)
+ {
+ $this->_attributes = $individualAttribs;
+ if (isset($individualAttribs['address'])) {
+ $this->_set('addressDetails', new Braintree_MerchantAccount_AddressDetails($individualAttribs['address']));
+ }
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccountGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccountGateway.php
new file mode 100644
index 0000000..4880579
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantAccountGateway.php
@@ -0,0 +1,152 @@
+<?php
+
+final class Braintree_MerchantAccountGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function create($attribs)
+ {
+ Braintree_Util::verifyKeys(self::detectSignature($attribs), $attribs);
+ return $this->_doCreate('/merchant_accounts/create_via_api', array('merchant_account' => $attribs));
+ }
+
+ public function find($merchant_account_id)
+ {
+ try {
+ $path = $this->_config->merchantPath() . '/merchant_accounts/' . $merchant_account_id;
+ $response = $this->_http->get($path);
+ return Braintree_MerchantAccount::factory($response['merchantAccount']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound('merchant account with id ' . $merchant_account_id . ' not found');
+ }
+ }
+
+ public function update($merchant_account_id, $attributes)
+ {
+ Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
+ return $this->_doUpdate('/merchant_accounts/' . $merchant_account_id . '/update_via_api', array('merchant_account' => $attributes));
+ }
+
+ public static function detectSignature($attribs)
+ {
+ if (isset($attribs['applicantDetails'])) {
+ trigger_error("DEPRECATED: Passing applicantDetails to create is deprecated. Please use individual, business, and funding", E_USER_NOTICE);
+ return self::createDeprecatedSignature();
+ } else {
+ return self::createSignature();
+ }
+ }
+
+ public static function updateSignature()
+ {
+ $signature = self::createSignature();
+ unset($signature['tosAccepted']);
+ return $signature;
+ }
+
+ public static function createSignature()
+ {
+ $addressSignature = array('streetAddress', 'postalCode', 'locality', 'region');
+ $individualSignature = array(
+ 'firstName',
+ 'lastName',
+ 'email',
+ 'phone',
+ 'dateOfBirth',
+ 'ssn',
+ array('address' => $addressSignature)
+ );
+
+ $businessSignature = array(
+ 'dbaName',
+ 'legalName',
+ 'taxId',
+ array('address' => $addressSignature)
+ );
+
+ $fundingSignature = array(
+ 'routingNumber',
+ 'accountNumber',
+ 'destination',
+ 'email',
+ 'mobilePhone',
+ 'descriptor',
+ );
+
+ return array(
+ 'id',
+ 'tosAccepted',
+ 'masterMerchantAccountId',
+ array('individual' => $individualSignature),
+ array('funding' => $fundingSignature),
+ array('business' => $businessSignature)
+ );
+ }
+
+ public static function createDeprecatedSignature()
+ {
+ $applicantDetailsAddressSignature = array('streetAddress', 'postalCode', 'locality', 'region');
+ $applicantDetailsSignature = array(
+ 'companyName',
+ 'firstName',
+ 'lastName',
+ 'email',
+ 'phone',
+ 'dateOfBirth',
+ 'ssn',
+ 'taxId',
+ 'routingNumber',
+ 'accountNumber',
+ array('address' => $applicantDetailsAddressSignature)
+ );
+
+ return array(
+ array('applicantDetails' => $applicantDetailsSignature),
+ 'id',
+ 'tosAccepted',
+ 'masterMerchantAccountId'
+ );
+ }
+
+ public function _doCreate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ private function _doUpdate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->put($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['merchantAccount'])) {
+ // return a populated instance of Braintree_merchantAccount
+ return new Braintree_Result_Successful(
+ Braintree_MerchantAccount::factory($response['merchantAccount'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected merchant account or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantGateway.php
new file mode 100644
index 0000000..9df1da6
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MerchantGateway.php
@@ -0,0 +1,40 @@
+<?php
+
+final class Braintree_MerchantGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasClientCredentials();
+ $this->_http = new Braintree_Http($gateway->config);
+ $this->_http->useClientCredentials();
+ }
+
+ public function create($attribs)
+ {
+ $response = $this->_http->post('/merchants/create_via_api', array('merchant' => $attribs));
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['response']['merchant'])) {
+ // return a populated instance of Braintree_merchant
+ return new Braintree_Result_Successful(array(
+ Braintree_Merchant::factory($response['response']['merchant']),
+ Braintree_OAuthCredentials::factory($response['response']['credentials']),
+ ));
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected merchant or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Modification.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Modification.php
new file mode 100644
index 0000000..55b4291
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Modification.php
@@ -0,0 +1,19 @@
+<?php
+class Braintree_Modification extends Braintree_Base
+{
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ public function __toString() {
+ return get_called_class() . '[' . Braintree_Util::attributesToString($this->_attributes) . ']';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueNode.php
new file mode 100644
index 0000000..3100e4d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueNode.php
@@ -0,0 +1,37 @@
+<?php
+
+class Braintree_MultipleValueNode
+{
+ function __construct($name, $allowedValues = array())
+ {
+ $this->name = $name;
+ $this->items = array();
+ $this->allowedValues = $allowedValues;
+ }
+
+ function in($values)
+ {
+ $bad_values = array_diff($values, $this->allowedValues);
+ if (count($this->allowedValues) > 0 && count($bad_values) > 0) {
+ $message = 'Invalid argument(s) for ' . $this->name . ':';
+ foreach ($bad_values AS $bad_value) {
+ $message .= ' ' . $bad_value;
+ }
+
+ throw new InvalidArgumentException($message);
+ }
+
+ $this->items = $values;
+ return $this;
+ }
+
+ function is($value)
+ {
+ return $this->in(array($value));
+ }
+
+ function toParam()
+ {
+ return $this->items;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueOrTextNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueOrTextNode.php
new file mode 100644
index 0000000..e0faca4
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/MultipleValueOrTextNode.php
@@ -0,0 +1,45 @@
+<?php
+
+class Braintree_MultipleValueOrTextNode extends Braintree_MultipleValueNode
+{
+ function __construct($name)
+ {
+ parent::__construct($name);
+ $this->textNode = new Braintree_TextNode($name);
+ }
+
+ function contains($value)
+ {
+ $this->textNode->contains($value);
+ return $this;
+ }
+
+ function endsWith($value)
+ {
+ $this->textNode->endsWith($value);
+ return $this;
+ }
+
+ function is($value)
+ {
+ $this->textNode->is($value);
+ return $this;
+ }
+
+ function isNot($value)
+ {
+ $this->textNode->isNot($value);
+ return $this;
+ }
+
+ function startsWith($value)
+ {
+ $this->textNode->startsWith($value);
+ return $this;
+ }
+
+ function toParam()
+ {
+ return array_merge(parent::toParam(), $this->textNode->toParam());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthCredentials.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthCredentials.php
new file mode 100644
index 0000000..dc89eb2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthCredentials.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Braintree OAuthCredentials module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ */
+class Braintree_OAuthCredentials extends Braintree_Base
+{
+ protected function _initialize($attribs)
+ {
+ $this->_attributes = $attribs;
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ /**
+ * returns a string representation of the access token
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthGateway.php
new file mode 100644
index 0000000..5197b11
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/OAuthGateway.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Braintree OAuthGateway module
+ * PHP Version 5
+ * Creates and manages Braintree Addresses
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_OAuthGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_http = new Braintree_Http($gateway->config);
+ $this->_http->useClientCredentials();
+
+ $this->_config->assertHasClientCredentials();
+ }
+
+ public function createTokenFromCode($params)
+ {
+ $params['grantType'] = "authorization_code";
+ return $this->_createToken($params);
+ }
+
+ public function createTokenFromRefreshToken($params)
+ {
+ $params['grantType'] = "refresh_token";
+ return $this->_createToken($params);
+ }
+
+ private function _createToken($params)
+ {
+ $params = array('credentials' => $params);
+ $response = $this->_http->post('/oauth/access_tokens', $params);
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['credentials'])) {
+ $result = new Braintree_Result_Successful(
+ Braintree_OAuthCredentials::factory($response['credentials'])
+ );
+ return $this->_mapSuccess($result);
+ } else if (isset($response['apiErrorResponse'])) {
+ $result = new Braintree_Result_Error($response['apiErrorResponse']);
+ return $this->_mapError($result);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected credentials or apiErrorResponse"
+ );
+ }
+ }
+
+ public function _mapError($result)
+ {
+ $error = $result->errors->deepAll()[0];
+
+ if ($error->code == Braintree_Error_Codes::OAUTH_INVALID_GRANT) {
+ $result->error = 'invalid_grant';
+ } else if ($error->code == Braintree_Error_Codes::OAUTH_INVALID_CREDENTIALS) {
+ $result->error = 'invalid_credentials';
+ } else if ($error->code == Braintree_Error_Codes::OAUTH_INVALID_SCOPE) {
+ $result->error = 'invalid_scope';
+ }
+ $result->errorDescription = explode(': ', $error->message)[1];
+ return $result;
+ }
+
+ public function _mapSuccess($result)
+ {
+ $credentials = $result->credentials;
+ $result->accessToken = $credentials->accessToken;
+ $result->refreshToken = $credentials->refreshToken;
+ $result->tokenType = $credentials->tokenType;
+ $result->expiresAt = $credentials->expiresAt;
+ return $result;
+ }
+
+ public function connectUrl($params = array())
+ {
+ $query = Braintree_Util::camelCaseToDelimiterArray($params, '_');
+ $query['client_id'] = $this->_config->getClientId();
+ $queryString = preg_replace('/\%5B\d+\%5D/', '%5B%5D', http_build_query($query));
+ $url = $this->_config->baseUrl() . '/oauth/connect?' . $queryString;
+
+ return $this->signUrl($url);
+ }
+
+ private function signUrl($url)
+ {
+ $key = hash('sha256', $this->_config->getClientSecret(), true);
+ return $url . '&signature=' . hash_hmac('sha256', $url, $key) . '&algorithm=SHA256';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartialMatchNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartialMatchNode.php
new file mode 100644
index 0000000..076204a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartialMatchNode.php
@@ -0,0 +1,16 @@
+<?php
+
+class Braintree_PartialMatchNode extends Braintree_EqualityNode
+{
+ function startsWith($value)
+ {
+ $this->searchTerms["starts_with"] = strval($value);
+ return $this;
+ }
+
+ function endsWith($value)
+ {
+ $this->searchTerms["ends_with"] = strval($value);
+ return $this;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartnerMerchant.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartnerMerchant.php
new file mode 100644
index 0000000..c5a3ba5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PartnerMerchant.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Partner Merchant information that is generated when a partner is connected
+ * to or disconnected from a user.
+ *
+ * Creates an instance of PartnerMerchants
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $merchantPublicId
+ * @property-read string $publicKey
+ * @property-read string $privateKey
+ * @property-read string $clientSideEncryptionKey
+ * @property-read string $partnerMerchantId
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_PartnerMerchant extends Braintree_Base
+{
+ protected $_attributes = array();
+
+ /**
+ * @ignore
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+
+ return $instance;
+ }
+
+ /**
+ * @ignore
+ */
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccount.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccount.php
new file mode 100644
index 0000000..38ffedc
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccount.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Braintree PayPalAccount module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Manages Braintree PayPalAccounts
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $email
+ * @property-read string $token
+ * @property-read string $imageUrl
+ */
+class Braintree_PayPalAccount extends Braintree_Base
+{
+ /**
+ * factory method: returns an instance of Braintree_PayPalAccount
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_PayPalAccount
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ /* instance methods */
+
+ /**
+ * returns false if default is null or false
+ *
+ * @return boolean
+ */
+ public function isDefault()
+ {
+ return $this->default;
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @access protected
+ * @param array $paypalAccountAttribs array of paypalAccount data
+ * @return none
+ */
+ protected function _initialize($paypalAccountAttribs)
+ {
+ // set the attributes
+ $this->_attributes = $paypalAccountAttribs;
+
+ $subscriptionArray = array();
+ if (isset($paypalAccountAttribs['subscriptions'])) {
+ foreach ($paypalAccountAttribs['subscriptions'] AS $subscription) {
+ $subscriptionArray[] = Braintree_Subscription::factory($subscription);
+ }
+ }
+
+ $this->_set('subscriptions', $subscriptionArray);
+ }
+
+ /**
+ * create a printable representation of the object as:
+ * ClassName[property=value, property=value]
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function find($token)
+ {
+ return Braintree_Configuration::gateway()->payPalAccount()->find($token);
+ }
+
+ public static function update($token, $attributes)
+ {
+ return Braintree_Configuration::gateway()->payPalAccount()->update($token, $attributes);
+ }
+
+ public static function delete($token)
+ {
+ return Braintree_Configuration::gateway()->payPalAccount()->delete($token);
+ }
+
+ public static function sale($token, $transactionAttribs)
+ {
+ return Braintree_Configuration::gateway()->payPalAccount()->sale($token, $transactionAttribs);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccountGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccountGateway.php
new file mode 100644
index 0000000..fafe46a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PayPalAccountGateway.php
@@ -0,0 +1,175 @@
+<?php
+/**
+ * Braintree PayPalAccountGateway module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Manages Braintree PayPalAccounts
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_PayPalAccountGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+
+ /**
+ * find a paypalAccount by token
+ *
+ * @access public
+ * @param string $token paypal accountunique id
+ * @return object Braintree_PayPalAccount
+ * @throws Braintree_Exception_NotFound
+ */
+ public function find($token)
+ {
+ $this->_validateId($token);
+ try {
+ $path = $this->_config->merchantPath() . '/payment_methods/paypal_account/' . $token;
+ $response = $this->_http->get($path);
+ return Braintree_PayPalAccount::factory($response['paypalAccount']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'paypal account with token ' . $token . ' not found'
+ );
+ }
+
+ }
+
+ /**
+ * updates the paypalAccount record
+ *
+ * if calling this method in context, $token
+ * is the 2nd attribute. $token is not sent in object context.
+ *
+ * @access public
+ * @param array $attributes
+ * @param string $token (optional)
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ */
+ public function update($token, $attributes)
+ {
+ Braintree_Util::verifyKeys(self::updateSignature(), $attributes);
+ $this->_validateId($token);
+ return $this->_doUpdate('put', '/payment_methods/paypal_account/' . $token, array('paypalAccount' => $attributes));
+ }
+
+ public function delete($token)
+ {
+ $this->_validateId($token);
+ $path = $this->_config->merchantPath() . '/payment_methods/paypal_account/' . $token;
+ $this->_http->delete($path);
+ return new Braintree_Result_Successful();
+ }
+
+ /**
+ * create a new sale for the current PayPal account
+ *
+ * @param string $token
+ * @param array $transactionAttribs
+ * @return object Braintree_Result_Successful or Braintree_Result_Error
+ * @see Braintree_Transaction::sale()
+ */
+ public function sale($token, $transactionAttribs)
+ {
+ $this->_validateId($token);
+ return Braintree_Transaction::sale(
+ array_merge(
+ $transactionAttribs,
+ array('paymentMethodToken' => $token)
+ )
+ );
+ }
+
+ public static function updateSignature()
+ {
+ return array(
+ 'token',
+ array('options' => array('makeDefault'))
+ );
+ }
+
+ /**
+ * sends the update request to the gateway
+ *
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ private function _doUpdate($httpVerb, $subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->$httpVerb($fullPath, $params);
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * creates a new Braintree_PayPalAccount object and encapsulates
+ * it inside a Braintree_Result_Successful object, or
+ * encapsulates a Braintree_Errors object inside a Result_Error
+ * alternatively, throws an Unexpected exception if the response is invalid.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return object Result_Successful or Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['paypalAccount'])) {
+ // return a populated instance of Braintree_PayPalAccount
+ return new Braintree_Result_Successful(
+ Braintree_PayPalAccount::factory($response['paypalAccount'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ 'Expected paypal account or apiErrorResponse'
+ );
+ }
+ }
+
+ /**
+ * verifies that a valid paypal account identifier is being used
+ * @ignore
+ * @param string $identifier
+ * @param Optional $string $identifierType type of identifier supplied, default 'token'
+ * @throws InvalidArgumentException
+ */
+ private function _validateId($identifier = null, $identifierType = 'token')
+ {
+ if (empty($identifier)) {
+ throw new InvalidArgumentException(
+ 'expected paypal account id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
+ throw new InvalidArgumentException(
+ $identifier . ' is an invalid paypal account ' . $identifierType . '.'
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentInstrumentType.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentInstrumentType.php
new file mode 100644
index 0000000..2dbf8c2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentInstrumentType.php
@@ -0,0 +1,11 @@
+<?php
+
+final class Braintree_PaymentInstrumentType
+{
+ const PAYPAL_ACCOUNT = 'paypal_account';
+ const COINBASE_ACCOUNT = 'coinbase_account';
+ const EUROPE_BANK_ACCOUNT = 'europe_bank_account';
+ const CREDIT_CARD = 'credit_card';
+ const APPLE_PAY_CARD = 'apple_pay_card';
+ const ANDROID_PAY_CARD = 'android_pay_card';
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethod.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethod.php
new file mode 100644
index 0000000..73aebaf
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethod.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Braintree PaymentMethod module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Creates and manages Braintree PaymentMethods
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ */
+class Braintree_PaymentMethod extends Braintree_Base
+{
+ // static methods redirecting to gateway
+
+ public static function create($attribs)
+ {
+ return Braintree_Configuration::gateway()->paymentMethod()->create($attribs);
+ }
+
+ public static function find($token)
+ {
+ return Braintree_Configuration::gateway()->paymentMethod()->find($token);
+ }
+
+ public static function update($token, $attribs)
+ {
+ return Braintree_Configuration::gateway()->paymentMethod()->update($token, $attribs);
+ }
+
+ public static function delete($token)
+ {
+ return Braintree_Configuration::gateway()->paymentMethod()->delete($token);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodGateway.php
new file mode 100644
index 0000000..79b70d0
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodGateway.php
@@ -0,0 +1,250 @@
+<?php
+/**
+ * Braintree PaymentMethodGateway module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Creates and manages Braintree PaymentMethods
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ */
+class Braintree_PaymentMethodGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+
+ public function create($attribs)
+ {
+ Braintree_Util::verifyKeys(self::createSignature(), $attribs);
+ return $this->_doCreate('/payment_methods', array('payment_method' => $attribs));
+ }
+
+ /**
+ * find a PaymentMethod by token
+ *
+ * @access public
+ * @param string $token payment method unique id
+ * @return object Braintree_CreditCard or Braintree_PayPalAccount
+ * @throws Braintree_Exception_NotFound
+ */
+ public function find($token)
+ {
+ $this->_validateId($token);
+ try {
+ $path = $this->_config->merchantPath() . '/payment_methods/any/' . $token;
+ $response = $this->_http->get($path);
+ if (isset($response['creditCard'])) {
+ return Braintree_CreditCard::factory($response['creditCard']);
+ } else if (isset($response['paypalAccount'])) {
+ return Braintree_PayPalAccount::factory($response['paypalAccount']);
+ } else if (isset($response['coinbaseAccount'])) {
+ return Braintree_CoinbaseAccount::factory($response['coinbaseAccount']);
+ } else if (isset($response['applePayCard'])) {
+ return Braintree_ApplePayCard::factory($response['applePayCard']);
+ } else if (isset($response['androidPayCard'])) {
+ return Braintree_AndroidPayCard::factory($response['androidPayCard']);
+ } else if (is_array($response)) {
+ return Braintree_UnknownPaymentMethod::factory($response);
+ }
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'payment method with token ' . $token . ' not found'
+ );
+ }
+
+ }
+
+ public function update($token, $attribs)
+ {
+ Braintree_Util::verifyKeys(self::updateSignature(), $attribs);
+ return $this->_doUpdate('/payment_methods/any/' . $token, array('payment_method' => $attribs));
+ }
+
+ public function delete($token)
+ {
+ $this->_validateId($token);
+ $path = $this->_config->merchantPath() . '/payment_methods/any/' . $token;
+ $this->_http->delete($path);
+ return new Braintree_Result_Successful();
+ }
+
+ private static function baseSignature()
+ {
+ $billingAddressSignature = Braintree_AddressGateway::createSignature();
+ $optionsSignature = array(
+ 'failOnDuplicatePaymentMethod',
+ 'makeDefault',
+ 'verificationMerchantAccountId',
+ 'verifyCard'
+ );
+ return array(
+ 'billingAddressId',
+ 'cardholderName',
+ 'cvv',
+ 'deviceData',
+ 'expirationDate',
+ 'expirationMonth',
+ 'expirationYear',
+ 'number',
+ 'paymentMethodNonce',
+ 'token',
+ array('options' => $optionsSignature),
+ array('billingAddress' => $billingAddressSignature)
+ );
+ }
+
+ public static function createSignature()
+ {
+ $signature = array_merge(self::baseSignature(), array('customerId'));
+ return $signature;
+ }
+
+ public static function updateSignature()
+ {
+ $billingAddressSignature = Braintree_AddressGateway::updateSignature();
+ array_push($billingAddressSignature, array(
+ 'options' => array(
+ 'updateExisting'
+ )
+ ));
+ $signature = array_merge(self::baseSignature(), array(
+ 'deviceSessionId',
+ 'venmoSdkPaymentMethodCode',
+ 'fraudMerchantId',
+ array('billingAddress' => $billingAddressSignature)
+ ));
+ return $signature;
+ }
+
+ /**
+ * sends the create request to the gateway
+ *
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ public function _doCreate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * sends the update request to the gateway
+ *
+ * @ignore
+ * @param string $subPath
+ * @param array $params
+ * @return mixed
+ */
+ public function _doUpdate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->put($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * creates a new Braintree_CreditCard or Braintree_PayPalAccount object
+ * and encapsulates it inside a Braintree_Result_Successful object, or
+ * encapsulates a Braintree_Errors object inside a Result_Error
+ * alternatively, throws an Unexpected exception if the response is invalid.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return object Result_Successful or Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['creditCard'])) {
+ // return a populated instance of Braintree_CreditCard
+ return new Braintree_Result_Successful(
+ Braintree_CreditCard::factory($response['creditCard']),
+ "paymentMethod"
+ );
+ } else if (isset($response['paypalAccount'])) {
+ // return a populated instance of Braintree_PayPalAccount
+ return new Braintree_Result_Successful(
+ Braintree_PayPalAccount::factory($response['paypalAccount']),
+ "paymentMethod"
+ );
+ } else if (isset($response['coinbaseAccount'])) {
+ // return a populated instance of Braintree_CoinbaseAccount
+ return new Braintree_Result_Successful(
+ Braintree_CoinbaseAccount::factory($response['coinbaseAccount']),
+ "paymentMethod"
+ );
+ } else if (isset($response['applePayCard'])) {
+ // return a populated instance of Braintree_ApplePayCard
+ return new Braintree_Result_Successful(
+ Braintree_ApplePayCard::factory($response['applePayCard']),
+ "paymentMethod"
+ );
+ } else if (isset($response['androidPayCard'])) {
+ // return a populated instance of Braintree_AndroidPayCard
+ return new Braintree_Result_Successful(
+ Braintree_AndroidPayCard::factory($response['androidPayCard']),
+ "paymentMethod"
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else if (is_array($response)) {
+ return new Braintree_Result_Successful(
+ Braintree_UnknownPaymentMethod::factory($response),
+ "paymentMethod"
+ );
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ 'Expected payment method or apiErrorResponse'
+ );
+ }
+ }
+
+ /**
+ * verifies that a valid payment method identifier is being used
+ * @ignore
+ * @param string $identifier
+ * @param Optional $string $identifierType type of identifier supplied, default 'token'
+ * @throws InvalidArgumentException
+ */
+ private function _validateId($identifier = null, $identifierType = 'token')
+ {
+ if (empty($identifier)) {
+ throw new InvalidArgumentException(
+ 'expected payment method id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
+ throw new InvalidArgumentException(
+ $identifier . ' is an invalid payment method ' . $identifierType . '.'
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonce.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonce.php
new file mode 100644
index 0000000..f5f62a0
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonce.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Braintree PaymentMethodNonce module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Creates and manages Braintree PaymentMethodNonces
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ */
+class Braintree_PaymentMethodNonce extends Braintree_Base
+{
+ // static methods redirecting to gateway
+
+ public static function create($token)
+ {
+ return Braintree_Configuration::gateway()->paymentMethodNonce()->create($token);
+ }
+
+ public static function find($nonce)
+ {
+ return Braintree_Configuration::gateway()->paymentMethodNonce()->find($nonce);
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ protected function _initialize($nonceAttributes)
+ {
+ $this->_attributes = $nonceAttributes;
+ $this->_set('nonce', $nonceAttributes['nonce']);
+ $this->_set('type', $nonceAttributes['type']);
+
+ if(isset($nonceAttributes['threeDSecureInfo'])) {
+ $this->_set('threeDSecureInfo', Braintree_ThreeDSecureInfo::factory($nonceAttributes['threeDSecureInfo']));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonceGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonceGateway.php
new file mode 100644
index 0000000..bb73c75
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PaymentMethodNonceGateway.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Braintree PaymentMethodNonceGateway module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Creates and manages Braintree PaymentMethodNonces
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ */
+class Braintree_PaymentMethodNonceGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+
+ public function create($token)
+ {
+ $subPath = '/payment_methods/' . $token . '/nonces';
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath);
+
+ return new Braintree_Result_Successful(
+ Braintree_PaymentMethodNonce::factory($response['paymentMethodNonce']),
+ "paymentMethodNonce"
+ );
+ }
+
+ /**
+ * @access public
+ *
+ */
+ public function find($nonce)
+ {
+ try {
+ $path = $this->_config->merchantPath() . '/payment_method_nonces/' . $nonce;
+ $response = $this->_http->get($path);
+ return Braintree_PaymentMethodNonce::factory($response['paymentMethodNonce']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'payment method nonce with id ' . $nonce . ' not found'
+ );
+ }
+
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Plan.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Plan.php
new file mode 100644
index 0000000..8b60286
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Plan.php
@@ -0,0 +1,48 @@
+<?php
+class Braintree_Plan extends Braintree_Base
+{
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+
+ return $instance;
+ }
+
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+
+ $addOnArray = array();
+ if (isset($attributes['addOns'])) {
+ foreach ($attributes['addOns'] AS $addOn) {
+ $addOnArray[] = Braintree_AddOn::factory($addOn);
+ }
+ }
+ $this->_attributes['addOns'] = $addOnArray;
+
+ $discountArray = array();
+ if (isset($attributes['discounts'])) {
+ foreach ($attributes['discounts'] AS $discount) {
+ $discountArray[] = Braintree_Discount::factory($discount);
+ }
+ }
+ $this->_attributes['discounts'] = $discountArray;
+
+ $planArray = array();
+ if (isset($attributes['plans'])) {
+ foreach ($attributes['plans'] AS $plan) {
+ $planArray[] = Braintree_Plan::factory($plan);
+ }
+ }
+ $this->_attributes['plans'] = $planArray;
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function all()
+ {
+ return Braintree_Configuration::gateway()->plan()->all();
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PlanGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PlanGateway.php
new file mode 100644
index 0000000..b889526
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/PlanGateway.php
@@ -0,0 +1,31 @@
+<?php
+class Braintree_PlanGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function all()
+ {
+ $path = $this->_config->merchantPath() . '/plans';
+ $response = $this->_http->get($path);
+ if (key_exists('plans', $response)){
+ $plans = array("plan" => $response['plans']);
+ } else {
+ $plans = array("plan" => array());
+ }
+
+ return Braintree_Util::extractAttributeAsArray(
+ $plans,
+ 'plan'
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RangeNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RangeNode.php
new file mode 100644
index 0000000..fdc4307
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RangeNode.php
@@ -0,0 +1,38 @@
+<?php
+
+class Braintree_RangeNode
+{
+ function __construct($name)
+ {
+ $this->name = $name;
+ $this->searchTerms = array();
+ }
+
+ function greaterThanOrEqualTo($value)
+ {
+ $this->searchTerms['min'] = $value;
+ return $this;
+ }
+
+ function lessThanOrEqualTo($value)
+ {
+ $this->searchTerms['max'] = $value;
+ return $this;
+ }
+
+ function is($value)
+ {
+ $this->searchTerms['is'] = $value;
+ return $this;
+ }
+
+ function between($min, $max)
+ {
+ return $this->greaterThanOrEqualTo($min)->lessThanOrEqualTo($max);
+ }
+
+ function toParam()
+ {
+ return $this->searchTerms;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ResourceCollection.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ResourceCollection.php
new file mode 100644
index 0000000..a08cc44
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ResourceCollection.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Braintree ResourceCollection
+ * ResourceCollection is a container object for result data
+ *
+ * stores and retrieves search results and aggregate data
+ *
+ * example:
+ * <code>
+ * $result = Braintree_Customer::all();
+ *
+ * foreach($result as $transaction) {
+ * print_r($transaction->id);
+ * }
+ * </code>
+ *
+ * @package Braintree
+ * @subpackage Utility
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_ResourceCollection implements Iterator
+{
+ private $_index;
+ private $_batchIndex;
+ private $_items;
+ private $_pageSize;
+ private $_pager;
+
+ /**
+ * set up the resource collection
+ *
+ * expects an array of attributes with literal keys
+ *
+ * @param array $attributes
+ * @param array $pagerAttribs
+ */
+ public function __construct($response, $pager)
+ {
+ $this->_pageSize = $response["searchResults"]["pageSize"];
+ $this->_ids = $response["searchResults"]["ids"];
+ $this->_pager = $pager;
+ }
+
+ /**
+ * returns the current item when iterating with foreach
+ */
+ public function current()
+ {
+ return $this->_items[$this->_index];
+ }
+
+ /**
+ * returns the first item in the collection
+ *
+ * @return mixed
+ */
+ public function firstItem()
+ {
+ $ids = $this->_ids;
+ $page = $this->_getPage(array($ids[0]));
+ return $page[0];
+ }
+
+ public function key()
+ {
+ return null;
+ }
+
+ /**
+ * advances to the next item in the collection when iterating with foreach
+ */
+ public function next()
+ {
+ ++$this->_index;
+ }
+
+ /**
+ * rewinds the testIterateOverResults collection to the first item when iterating with foreach
+ */
+ public function rewind()
+ {
+ $this->_batchIndex = 0;
+ $this->_getNextPage();
+ }
+
+ /**
+ * returns whether the current item is valid when iterating with foreach
+ */
+ public function valid()
+ {
+ if ($this->_index == count($this->_items) && $this->_batchIndex < count($this->_ids)) {
+ $this->_getNextPage();
+ }
+
+ if ($this->_index < count($this->_items)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function maximumCount()
+ {
+ return count($this->_ids);
+ }
+
+ private function _getNextPage()
+ {
+ if (empty($this->_ids))
+ {
+ $this->_items = array();
+ }
+ else
+ {
+ $this->_items = $this->_getPage(array_slice($this->_ids, $this->_batchIndex, $this->_pageSize));
+ $this->_batchIndex += $this->_pageSize;
+ $this->_index = 0;
+ }
+ }
+
+ /**
+ * requests the next page of results for the collection
+ *
+ * @return none
+ */
+ private function _getPage($ids)
+ {
+ $object = $this->_pager['object'];
+ $method = $this->_pager['method'];
+ $methodArgs = array();
+ foreach ($this->_pager['methodArgs'] as $arg) {
+ array_push($methodArgs, $arg);
+ }
+ array_push($methodArgs, $ids);
+
+ return call_user_func_array(
+ array($object, $method),
+ $methodArgs
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/CreditCardVerification.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/CreditCardVerification.php
new file mode 100644
index 0000000..ab155b2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/CreditCardVerification.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Braintree Credit Card Verification Result
+ *
+ * This object is returned as part of an Error Result; it provides
+ * access to the credit card verification data from the gateway
+ *
+ *
+ * @package Braintree
+ * @subpackage Result
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $avsErrorResponseCode
+ * @property-read string $avsPostalCodeResponseCode
+ * @property-read string $avsStreetAddressResponseCode
+ * @property-read string $cvvResponseCode
+ * @property-read string $status
+ *
+ */
+class Braintree_Result_CreditCardVerification
+{
+ // Status
+ const FAILED = 'failed';
+ const GATEWAY_REJECTED = 'gateway_rejected';
+ const PROCESSOR_DECLINED = 'processor_declined';
+ const VERIFIED = 'verified';
+
+ private $_attributes;
+ private $_avsErrorResponseCode;
+ private $_avsPostalCodeResponseCode;
+ private $_avsStreetAddressResponseCode;
+ private $_cvvResponseCode;
+ private $_gatewayRejectionReason;
+ private $_status;
+
+ /**
+ * @ignore
+ */
+ public function __construct($attributes)
+ {
+ $this->_initializeFromArray($attributes);
+ }
+
+ /**
+ * initializes instance properties from the keys/values of an array
+ * @ignore
+ * @access protected
+ * @param <type> $aAttribs array of properties to set - single level
+ * @return none
+ */
+ private function _initializeFromArray($attributes)
+ {
+ if(isset($attributes['riskData']))
+ {
+ $attributes['riskData'] = Braintree_RiskData::factory($attributes['riskData']);
+ }
+
+ $this->_attributes = $attributes;
+ foreach($attributes AS $name => $value) {
+ $varName = "_$name";
+ $this->$varName = $value;
+ }
+ }
+
+ /**
+ *
+ * @ignore
+ */
+ public function __get($name)
+ {
+ $varName = "_$name";
+ return isset($this->$varName) ? $this->$varName : null;
+ }
+
+ /**
+ * returns a string representation of the customer
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+ public static function allStatuses()
+ {
+ return array(
+ Braintree_Result_creditCardVerification::FAILED,
+ Braintree_Result_creditCardVerification::GATEWAY_REJECTED,
+ Braintree_Result_creditCardVerification::PROCESSOR_DECLINED,
+ Braintree_Result_creditCardVerification::VERIFIED,
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Error.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Error.php
new file mode 100644
index 0000000..92b5386
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Error.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Braintree Error Result
+ *
+ * An Error Result will be returned from gateway methods when
+ * the gateway responds with an error. It will provide access
+ * to the original request.
+ * For example, when voiding a transaction, Error Result will
+ * respond to the void request if it failed:
+ *
+ * <code>
+ * $result = Braintree_Transaction::void('abc123');
+ * if ($result->success) {
+ * // Successful Result
+ * } else {
+ * // Braintree_Result_Error
+ * }
+ * </code>
+ *
+ * @package Braintree
+ * @subpackage Result
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read array $params original passed params
+ * @property-read object $errors Braintree_Error_ErrorCollection
+ * @property-read object $creditCardVerification credit card verification data
+ */
+class Braintree_Result_Error extends Braintree_Base
+{
+ /**
+ *
+ * @var boolean always false
+ */
+ public $success = false;
+
+ /**
+ * return original value for a field
+ * For example, if a user tried to submit 'invalid-email' in the html field transaction[customer][email],
+ * $result->valueForHtmlField("transaction[customer][email]") would yield "invalid-email"
+ *
+ * @param string $field
+ * @return string
+ */
+ public function valueForHtmlField($field)
+ {
+ $pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY);
+ $params = $this->params;
+ foreach(array_slice($pieces, 0, -1) as $key) {
+ $params = $params[Braintree_Util::delimiterToCamelCase($key)];
+ }
+ if ($key != 'custom_fields') {
+ $finalKey = Braintree_Util::delimiterToCamelCase(end($pieces));
+ } else {
+ $finalKey = end($pieces);
+ }
+ $fieldValue = isset($params[$finalKey]) ? $params[$finalKey] : null;
+ return $fieldValue;
+ }
+
+ /**
+ * overrides default constructor
+ * @ignore
+ * @param array $response gateway response array
+ */
+ public function __construct($response)
+ {
+ $this->_attributes = $response;
+ $this->_set('errors', new Braintree_Error_ErrorCollection($response['errors']));
+
+ if(isset($response['verification'])) {
+ $this->_set('creditCardVerification', new Braintree_Result_CreditCardVerification($response['verification']));
+ } else {
+ $this->_set('creditCardVerification', null);
+ }
+
+ if(isset($response['transaction'])) {
+ $this->_set('transaction', Braintree_Transaction::factory($response['transaction']));
+ } else {
+ $this->_set('transaction', null);
+ }
+
+ if(isset($response['subscription'])) {
+ $this->_set('subscription', Braintree_Subscription::factory($response['subscription']));
+ } else {
+ $this->_set('subscription', null);
+ }
+
+ if(isset($response['merchantAccount'])) {
+ $this->_set('merchantAccount', Braintree_MerchantAccount::factory($response['merchantAccount']));
+ } else {
+ $this->_set('merchantAccount', null);
+ }
+ }
+
+ /**
+ * create a printable representation of the object as:
+ * ClassName[property=value, property=value]
+ * @ignore
+ * @return var
+ */
+ public function __toString()
+ {
+ $output = Braintree_Util::attributesToString($this->_attributes);
+ if (isset($this->_creditCardVerification)) {
+ $output .= sprintf('%s', $this->_creditCardVerification);
+ }
+ return __CLASS__ .'['.$output.']';
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Successful.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Successful.php
new file mode 100644
index 0000000..72a373b
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Result/Successful.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Braintree Successful Result
+ *
+ * A Successful Result will be returned from gateway methods when
+ * validations pass. It will provide access to the created resource.
+ *
+ * For example, when creating a customer, Braintree_Result_Successful will
+ * respond to <b>customer</b> like so:
+ *
+ * <code>
+ * $result = Braintree_Customer::create(array('first_name' => "John"));
+ * if ($result->success) {
+ * // Braintree_Result_Successful
+ * echo "Created customer {$result->customer->id}";
+ * } else {
+ * // Braintree_Result_Error
+ * }
+ * </code>
+ *
+ *
+ * @package Braintree
+ * @subpackage Result
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Result_Successful extends Braintree_Instance
+{
+ /**
+ *
+ * @var boolean always true
+ */
+ public $success = true;
+ /**
+ *
+ * @var string stores the internal name of the object providing access to
+ */
+ private $_returnObjectNames;
+
+ /**
+ * @ignore
+ * @param string $classToReturn name of class to instantiate
+ */
+ public function __construct($objsToReturn = array(), $propertyNames = array())
+ {
+ // Sanitize arguments (preserves backwards compatibility)
+ if (!is_array($objsToReturn)) { $objsToReturn = array($objsToReturn); }
+ if (!is_array($propertyNames)) { $propertyNames = array($propertyNames); }
+
+ $objects = $this->_mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn);
+ $this->_attributes = array();
+ $this->_returnObjectNames = array();
+
+ foreach ($objects as $propertyName => $objToReturn) {
+
+ // save the name for indirect access
+ array_push($this->_returnObjectNames, $propertyName);
+
+ // create the property!
+ $this->$propertyName = $objToReturn;
+ }
+ }
+
+ /**
+ *
+ * @ignore
+ * @return string string representation of the object's structure
+ */
+ public function __toString()
+ {
+ $objects = array();
+ foreach ($this->_returnObjectNames as $returnObjectName) {
+ array_push($objects, $this->$returnObjectName);
+ }
+ return __CLASS__ . '[' . implode(', ', $objects) . ']';
+ }
+
+ private function _mapPropertyNamesToObjsToReturn($propertyNames, $objsToReturn) {
+ if(count($objsToReturn) != count($propertyNames)) {
+ $propertyNames = array();
+ foreach ($objsToReturn as $obj) {
+ array_push($propertyNames, Braintree_Util::cleanClassName(get_class($obj)));
+ }
+ }
+ return array_combine($propertyNames, $objsToReturn);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RiskData.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RiskData.php
new file mode 100644
index 0000000..b6ad7d5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/RiskData.php
@@ -0,0 +1,27 @@
+<?php
+class Braintree_RiskData extends Braintree_Base
+{
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+
+ return $instance;
+ }
+
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+
+ /**
+ * returns a string representation of the risk data
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummary.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummary.php
new file mode 100644
index 0000000..7d28453
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummary.php
@@ -0,0 +1,42 @@
+<?php
+class Braintree_SettlementBatchSummary extends Braintree_Base
+{
+ /**
+ *
+ * @param array $attributes
+ * @return Braintree_SettlementBatchSummary
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ /**
+ * @ignore
+ * @param array $attributes
+ */
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+
+ public function records()
+ {
+ return $this->_attributes['records'];
+ }
+
+
+ /**
+ * static method redirecting to gateway
+ *
+ * @param string $settlement_date Date YYYY-MM-DD
+ * @param string $groupByCustomField
+ * @return Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public static function generate($settlement_date, $groupByCustomField = NULL)
+ {
+ return Braintree_Configuration::gateway()->settlementBatchSummary()->generate($settlement_date, $groupByCustomField);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummaryGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummaryGateway.php
new file mode 100644
index 0000000..16f18e2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SettlementBatchSummaryGateway.php
@@ -0,0 +1,104 @@
+<?php
+
+class Braintree_SettlementBatchSummaryGateway
+{
+ /**
+ *
+ * @var Braintree_Gateway
+ */
+ private $_gateway;
+
+ /**
+ *
+ * @var Braintree_Configuration
+ */
+ private $_config;
+
+ /**
+ *
+ * @var Braintree_Http
+ */
+ private $_http;
+
+ /**
+ *
+ * @param Braintree_Gateway $gateway
+ */
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ /**
+ *
+ * @param string $settlement_date
+ * @param string $groupByCustomField
+ * @return Braintree_SettlementBatchSummary|Braintree_Result_Error
+ */
+ public function generate($settlement_date, $groupByCustomField = NULL)
+ {
+ $criteria = array('settlement_date' => $settlement_date);
+ if (isset($groupByCustomField))
+ {
+ $criteria['group_by_custom_field'] = $groupByCustomField;
+ }
+ $params = array('settlement_batch_summary' => $criteria);
+ $path = $this->_config->merchantPath() . '/settlement_batch_summary';
+ $response = $this->_http->post($path, $params);
+
+ if (isset($groupByCustomField))
+ {
+ $response['settlementBatchSummary']['records'] = $this->_underscoreCustomField(
+ $groupByCustomField,
+ $response['settlementBatchSummary']['records']
+ );
+ }
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ *
+ * @param string $groupByCustomField
+ * @param array $records
+ * @return array
+ */
+ private function _underscoreCustomField($groupByCustomField, $records)
+ {
+ $updatedRecords = array();
+
+ foreach ($records as $record)
+ {
+ $camelized = Braintree_Util::delimiterToCamelCase($groupByCustomField);
+ $record[$groupByCustomField] = $record[$camelized];
+ unset($record[$camelized]);
+ $updatedRecords[] = $record;
+ }
+
+ return $updatedRecords;
+ }
+
+ /**
+ *
+ * @param array $response
+ * @return \Braintree_Result_Successful|\Braintree_Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['settlementBatchSummary'])) {
+ return new Braintree_Result_Successful(
+ Braintree_SettlementBatchSummary::factory($response['settlementBatchSummary'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected settlementBatchSummary or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SignatureService.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SignatureService.php
new file mode 100644
index 0000000..2a31fda
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SignatureService.php
@@ -0,0 +1,22 @@
+<?php
+
+class Braintree_SignatureService
+{
+
+ public function __construct($key, $digest)
+ {
+ $this->key = $key;
+ $this->digest = $digest;
+ }
+
+ public function sign($payload)
+ {
+ return $this->hash($payload) . "|" . $payload;
+ }
+
+ public function hash($data)
+ {
+ return call_user_func($this->digest, $this->key, $data);
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription.php
new file mode 100644
index 0000000..c5e9b5d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Braintree Subscription module
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Subscriptions, see {@link http://www.braintreepayments.com/gateway/subscription-api http://www.braintreepaymentsolutions.com/gateway/subscription-api}
+ *
+ * PHP Version 5
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Subscription extends Braintree_Base
+{
+ const ACTIVE = 'Active';
+ const CANCELED = 'Canceled';
+ const EXPIRED = 'Expired';
+ const PAST_DUE = 'Past Due';
+ const PENDING = 'Pending';
+
+ // Subscription Sources
+ const API = 'api';
+ const CONTROL_PANEL = 'control_panel';
+ const RECURRING = 'recurring';
+
+ /**
+ * @ignore
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+
+ return $instance;
+ }
+
+ /**
+ * @ignore
+ */
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+
+ $addOnArray = array();
+ if (isset($attributes['addOns'])) {
+ foreach ($attributes['addOns'] AS $addOn) {
+ $addOnArray[] = Braintree_AddOn::factory($addOn);
+ }
+ }
+ $this->_attributes['addOns'] = $addOnArray;
+
+ $discountArray = array();
+ if (isset($attributes['discounts'])) {
+ foreach ($attributes['discounts'] AS $discount) {
+ $discountArray[] = Braintree_Discount::factory($discount);
+ }
+ }
+ $this->_attributes['discounts'] = $discountArray;
+
+ if (isset($attributes['descriptor'])) {
+ $this->_set('descriptor', new Braintree_Descriptor($attributes['descriptor']));
+ }
+
+ $statusHistory = array();
+ if (isset($attributes['statusHistory'])) {
+ foreach ($attributes['statusHistory'] AS $history) {
+ $statusHistory[] = new Braintree_Subscription_StatusDetails($history);
+ }
+ }
+ $this->_attributes['statusHistory'] = $statusHistory;
+
+ $transactionArray = array();
+ if (isset($attributes['transactions'])) {
+ foreach ($attributes['transactions'] AS $transaction) {
+ $transactionArray[] = Braintree_Transaction::factory($transaction);
+ }
+ }
+ $this->_attributes['transactions'] = $transactionArray;
+ }
+
+ /**
+ * returns a string representation of the customer
+ * @return string
+ */
+ public function __toString()
+ {
+ $excludedAttributes = array('statusHistory');
+
+ $displayAttributes = array();
+ foreach($this->_attributes as $key => $val) {
+ if (!in_array($key, $excludedAttributes)) {
+ $displayAttributes[$key] = $val;
+ }
+ }
+
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($displayAttributes) .']';
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function create($attributes)
+ {
+ return Braintree_Configuration::gateway()->subscription()->create($attributes);
+ }
+
+ public static function find($id)
+ {
+ return Braintree_Configuration::gateway()->subscription()->find($id);
+ }
+
+ public static function search($query)
+ {
+ return Braintree_Configuration::gateway()->subscription()->search($query);
+ }
+
+ public static function fetch($query, $ids)
+ {
+ return Braintree_Configuration::gateway()->subscription()->fetch($query, $ids);
+ }
+
+ public static function update($subscriptionId, $attributes)
+ {
+ return Braintree_Configuration::gateway()->subscription()->update($subscriptionId, $attributes);
+ }
+
+ public static function retryCharge($subscriptionId, $amount = null)
+ {
+ return Braintree_Configuration::gateway()->subscription()->retryCharge($subscriptionId, $amount);
+ }
+
+ public static function cancel($subscriptionId)
+ {
+ return Braintree_Configuration::gateway()->subscription()->cancel($subscriptionId);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription/StatusDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription/StatusDetails.php
new file mode 100644
index 0000000..573ac53
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Subscription/StatusDetails.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Status details from a subscription
+ * Creates an instance of StatusDetails, as part of a subscription response
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $price
+ * @property-read string $balance
+ * @property-read string $status
+ * @property-read string $timestamp
+ * @property-read string $subscriptionSource
+ * @property-read string $user
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Subscription_StatusDetails extends Braintree_Instance
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionGateway.php
new file mode 100644
index 0000000..d1981a2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionGateway.php
@@ -0,0 +1,210 @@
+<?php
+/**
+ * Braintree SubscriptionGateway module
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Subscriptions, see {@link http://www.braintreepayments.com/gateway/subscription-api http://www.braintreepaymentsolutions.com/gateway/subscription-api}
+ *
+ * PHP Version 5
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_SubscriptionGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function create($attributes)
+ {
+ Braintree_Util::verifyKeys(self::_createSignature(), $attributes);
+ $path = $this->_config->merchantPath() . '/subscriptions';
+ $response = $this->_http->post($path, array('subscription' => $attributes));
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function find($id)
+ {
+ $this->_validateId($id);
+
+ try {
+ $path = $this->_config->merchantPath() . '/subscriptions/' . $id;
+ $response = $this->_http->get($path);
+ return Braintree_Subscription::factory($response['subscription']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound('subscription with id ' . $id . ' not found');
+ }
+
+ }
+
+ public function search($query)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+
+
+ $path = $this->_config->merchantPath() . '/subscriptions/advanced_search_ids';
+ $response = $this->_http->post($path, array('search' => $criteria));
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetch',
+ 'methodArgs' => array($query)
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ }
+
+ public function fetch($query, $ids)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+ $criteria["ids"] = Braintree_SubscriptionSearch::ids()->in($ids)->toparam();
+ $path = $this->_config->merchantPath() . '/subscriptions/advanced_search';
+ $response = $this->_http->post($path, array('search' => $criteria));
+
+ return Braintree_Util::extractAttributeAsArray(
+ $response['subscriptions'],
+ 'subscription'
+ );
+ }
+
+ public function update($subscriptionId, $attributes)
+ {
+ Braintree_Util::verifyKeys(self::_updateSignature(), $attributes);
+ $path = $this->_config->merchantPath() . '/subscriptions/' . $subscriptionId;
+ $response = $this->_http->put($path, array('subscription' => $attributes));
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function retryCharge($subscriptionId, $amount = null)
+ {
+ $transaction_params = array('type' => Braintree_Transaction::SALE,
+ 'subscriptionId' => $subscriptionId);
+ if (isset($amount)) {
+ $transaction_params['amount'] = $amount;
+ }
+
+ $path = $this->_config->merchantPath() . '/transactions';
+ $response = $this->_http->post($path, array('transaction' => $transaction_params));
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function cancel($subscriptionId)
+ {
+ $path = $this->_config->merchantPath() . '/subscriptions/' . $subscriptionId . '/cancel';
+ $response = $this->_http->put($path);
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ private static function _createSignature()
+ {
+ return array_merge(
+ array(
+ 'billingDayOfMonth',
+ 'firstBillingDate',
+ 'createdAt',
+ 'updatedAt',
+ 'id',
+ 'merchantAccountId',
+ 'neverExpires',
+ 'numberOfBillingCycles',
+ 'paymentMethodToken',
+ 'paymentMethodNonce',
+ 'planId',
+ 'price',
+ 'trialDuration',
+ 'trialDurationUnit',
+ 'trialPeriod',
+ array('descriptor' => array('name', 'phone', 'url')),
+ array('options' => array('doNotInheritAddOnsOrDiscounts', 'startImmediately')),
+ ),
+ self::_addOnDiscountSignature()
+ );
+ }
+
+ private static function _updateSignature()
+ {
+ return array_merge(
+ array(
+ 'merchantAccountId', 'numberOfBillingCycles', 'paymentMethodToken', 'planId',
+ 'paymentMethodNonce', 'id', 'neverExpires', 'price',
+ array('descriptor' => array('name', 'phone', 'url')),
+ array('options' => array('prorateCharges', 'replaceAllAddOnsAndDiscounts', 'revertSubscriptionOnProrationFailure')),
+ ),
+ self::_addOnDiscountSignature()
+ );
+ }
+
+ private static function _addOnDiscountSignature()
+ {
+ return array(
+ array(
+ 'addOns' => array(
+ array('add' => array('amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
+ array('update' => array('amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
+ array('remove' => array('_anyKey_')),
+ )
+ ),
+ array(
+ 'discounts' => array(
+ array('add' => array('amount', 'inheritedFromId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
+ array('update' => array('amount', 'existingId', 'neverExpires', 'numberOfBillingCycles', 'quantity')),
+ array('remove' => array('_anyKey_')),
+ )
+ )
+ );
+ }
+
+ /**
+ * @ignore
+ */
+ private function _validateId($id = null) {
+ if (empty($id)) {
+ throw new InvalidArgumentException(
+ 'expected subscription id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) {
+ throw new InvalidArgumentException(
+ $id . ' is an invalid subscription id.'
+ );
+ }
+ }
+
+ /**
+ * @ignore
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['subscription'])) {
+ return new Braintree_Result_Successful(
+ Braintree_Subscription::factory($response['subscription'])
+ );
+ } else if (isset($response['transaction'])) {
+ // return a populated instance of Braintree_Transaction, for subscription retryCharge
+ return new Braintree_Result_Successful(
+ Braintree_Transaction::factory($response['transaction'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected subscription, transaction, or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionSearch.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionSearch.php
new file mode 100644
index 0000000..01cba1a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/SubscriptionSearch.php
@@ -0,0 +1,64 @@
+<?php
+class Braintree_SubscriptionSearch
+{
+ static function billingCyclesRemaining()
+ {
+ return new Braintree_RangeNode('billing_cycles_remaining');
+ }
+
+ static function daysPastDue()
+ {
+ return new Braintree_RangeNode('days_past_due');
+ }
+
+ static function id()
+ {
+ return new Braintree_TextNode('id');
+ }
+
+ static function inTrialPeriod()
+ {
+ return new Braintree_MultipleValueNode('in_trial_period', array(true, false));
+ }
+
+ static function merchantAccountId()
+ {
+ return new Braintree_MultipleValueNode('merchant_account_id');
+ }
+
+ static function nextBillingDate()
+ {
+ return new Braintree_RangeNode('next_billing_date');
+ }
+
+ static function planId()
+ {
+ return new Braintree_MultipleValueOrTextNode('plan_id');
+ }
+
+ static function price()
+ {
+ return new Braintree_RangeNode('price');
+ }
+
+ static function status()
+ {
+ return new Braintree_MultipleValueNode("status", array(
+ Braintree_Subscription::ACTIVE,
+ Braintree_Subscription::CANCELED,
+ Braintree_Subscription::EXPIRED,
+ Braintree_Subscription::PAST_DUE,
+ Braintree_Subscription::PENDING
+ ));
+ }
+
+ static function transactionId()
+ {
+ return new Braintree_TextNode('transaction_id');
+ }
+
+ static function ids()
+ {
+ return new Braintree_MultipleValueNode('ids');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/CreditCardNumbers.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/CreditCardNumbers.php
new file mode 100644
index 0000000..2420423
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/CreditCardNumbers.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * Credit card information used for testing purposes
+ *
+ * The constants contained in the Braintree_Test_CreditCardNumbers class provide
+ * credit card numbers that should be used when working in the sandbox environment.
+ * The sandbox will not accept any credit card numbers other than the ones listed below.
+ *
+ * @package Braintree
+ * @subpackage Test
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Test_CreditCardNumbers
+{
+ public static $amExes = array(
+ '378282246310005',
+ '371449635398431',
+ '378734493671000',
+ );
+ public static $carteBlanches = array('30569309025904',);
+ public static $dinersClubs = array('38520000023237',);
+ public static $discoverCards = array(
+ '6011111111111117',
+ '6011000990139424',
+ );
+ public static $JCBs = array(
+ '3530111333300000',
+ '3566002020360505',
+ );
+
+ public static $masterCard = '5555555555554444';
+ public static $masterCardInternational = '5105105105105100';
+ public static $masterCards = array(
+ '5105105105105100',
+ '5555555555554444',
+ );
+
+ public static $visa = '4012888888881881';
+ public static $visaInternational = '4009348888881881';
+ public static $visas = array(
+ '4009348888881881',
+ '4012888888881881',
+ '4111111111111111',
+ '4000111111111115',
+ );
+
+ public static $unknowns = array(
+ '1000000000000008',
+ );
+
+ public static $failsSandboxVerification = array(
+ 'AmEx' => '378734493671000',
+ 'Discover' => '6011000990139424',
+ 'MasterCard' => '5105105105105100',
+ 'Visa' => '4000111111111115',
+ );
+
+
+ public static function getAll()
+ {
+ return array_merge(
+ self::$amExes,
+ self::$discoverCards,
+ self::$masterCards,
+ self::$visas
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/MerchantAccount.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/MerchantAccount.php
new file mode 100644
index 0000000..3932a57
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/MerchantAccount.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Merchant Account constants used for testing purposes
+ *
+ * @package Braintree
+ * @subpackage Test
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Test_MerchantAccount
+{
+ public static $approve = "approve_me";
+
+ public static $insufficientFundsContactUs = "insufficient_funds__contact";
+ public static $accountNotAuthorizedContactUs = "account_not_authorized__contact";
+ public static $bankRejectedUpdateFundingInformation = "bank_rejected__update";
+ public static $bankRejectedNone = "bank_rejected__none";
+
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/Nonces.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/Nonces.php
new file mode 100644
index 0000000..f1b576d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/Nonces.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Nonces used for testing purposes
+ *
+ * @package Braintree
+ * @subpackage Test
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Nonces used for testing purposes
+ *
+ * The constants in this class can be used to perform nonce operations
+ * with the desired status in the sandbox environment.
+ *
+ * @package Braintree
+ * @subpackage Test
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Test_Nonces
+{
+ public static $transactable = "fake-valid-nonce";
+ public static $consumed = "fake-consumed-nonce";
+ public static $paypalOneTimePayment = "fake-paypal-one-time-nonce";
+ public static $paypalFuturePayment = "fake-paypal-future-nonce";
+ public static $applePayVisa = "fake-apple-pay-visa-nonce";
+ public static $applePayMasterCard = "fake-apple-pay-visa-nonce";
+ public static $applePayAmEx = "fake-apple-pay-amex-nonce";
+ public static $androidPay = "fake-android-pay-nonce";
+ public static $abstractTransactable = "fake-abstract-transactable-nonce";
+ public static $europe = "fake-europe-bank-account-nonce";
+ public static $coinbase = "fake-coinbase-nonce";
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/TransactionAmounts.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/TransactionAmounts.php
new file mode 100644
index 0000000..b1b5abb
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/TransactionAmounts.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * Transaction amounts used for testing purposes
+ *
+ * The constants in this class can be used to create transactions with
+ * the desired status in the sandbox environment.
+ *
+ * @package Braintree
+ * @subpackage Test
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Test_TransactionAmounts
+{
+ public static $authorize = '1000.00';
+ public static $decline = '2000.00';
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/VenmoSdk.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/VenmoSdk.php
new file mode 100644
index 0000000..53d6104
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Test/VenmoSdk.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * VenmoSdk payment method codes used for testing purposes
+ *
+ * @package Braintree
+ * @subpackage Test
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Test_VenmoSdk
+{
+ public static $visaPaymentMethodCode = "stub-4111111111111111";
+
+ public static function generateTestPaymentMethodCode($number) {
+ return "stub-" . $number;
+ }
+
+ public static function getInvalidPaymentMethodCode() {
+ return "stub-invalid-payment-method-code";
+ }
+
+ public static function getTestSession() {
+ return "stub-session";
+ }
+
+ public static function getInvalidTestSession() {
+ return "stub-invalid-session";
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TextNode.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TextNode.php
new file mode 100644
index 0000000..f193d1d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TextNode.php
@@ -0,0 +1,10 @@
+<?php
+
+class Braintree_TextNode extends Braintree_PartialMatchNode
+{
+ function contains($value)
+ {
+ $this->searchTerms["contains"] = strval($value);
+ return $this;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ThreeDSecureInfo.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ThreeDSecureInfo.php
new file mode 100644
index 0000000..608d70d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/ThreeDSecureInfo.php
@@ -0,0 +1,27 @@
+<?php
+class Braintree_ThreeDSecureInfo extends Braintree_Base
+{
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+
+ return $instance;
+ }
+
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+ }
+
+ /**
+ * returns a string representation of the three d secure info
+ * @return string
+ */
+ public function __toString()
+ {
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($this->_attributes) .']';
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction.php
new file mode 100644
index 0000000..1832e2a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction.php
@@ -0,0 +1,517 @@
+<?php
+/**
+ * Braintree Transaction processor
+ * Creates and manages transactions
+ *
+ * At minimum, an amount, credit card number, and
+ * credit card expiration date are required.
+ *
+ * <b>Minimalistic example:</b>
+ * <code>
+ * Braintree_Transaction::saleNoValidate(array(
+ * 'amount' => '100.00',
+ * 'creditCard' => array(
+ * 'number' => '5105105105105100',
+ * 'expirationDate' => '05/12',
+ * ),
+ * ));
+ * </code>
+ *
+ * <b>Full example:</b>
+ * <code>
+ * Braintree_Transaction::saleNoValidate(array(
+ * 'amount' => '100.00',
+ * 'orderId' => '123',
+ * 'channel' => 'MyShoppingCardProvider',
+ * 'creditCard' => array(
+ * // if token is omitted, the gateway will generate a token
+ * 'token' => 'credit_card_123',
+ * 'number' => '5105105105105100',
+ * 'expirationDate' => '05/2011',
+ * 'cvv' => '123',
+ * ),
+ * 'customer' => array(
+ * // if id is omitted, the gateway will generate an id
+ * 'id' => 'customer_123',
+ * 'firstName' => 'Dan',
+ * 'lastName' => 'Smith',
+ * 'company' => 'Braintree',
+ * 'email' => 'dan@example.com',
+ * 'phone' => '419-555-1234',
+ * 'fax' => '419-555-1235',
+ * 'website' => 'http://braintreepayments.com'
+ * ),
+ * 'billing' => array(
+ * 'firstName' => 'Carl',
+ * 'lastName' => 'Jones',
+ * 'company' => 'Braintree',
+ * 'streetAddress' => '123 E Main St',
+ * 'extendedAddress' => 'Suite 403',
+ * 'locality' => 'Chicago',
+ * 'region' => 'IL',
+ * 'postalCode' => '60622',
+ * 'countryName' => 'United States of America'
+ * ),
+ * 'shipping' => array(
+ * 'firstName' => 'Andrew',
+ * 'lastName' => 'Mason',
+ * 'company' => 'Braintree',
+ * 'streetAddress' => '456 W Main St',
+ * 'extendedAddress' => 'Apt 2F',
+ * 'locality' => 'Bartlett',
+ * 'region' => 'IL',
+ * 'postalCode' => '60103',
+ * 'countryName' => 'United States of America'
+ * ),
+ * 'customFields' => array(
+ * 'birthdate' => '11/13/1954'
+ * )
+ * )
+ * </code>
+ *
+ * <b>== Storing in the Vault ==</b>
+ *
+ * The customer and credit card information used for
+ * a transaction can be stored in the vault by setting
+ * <i>transaction[options][storeInVault]</i> to true.
+ * <code>
+ * $transaction = Braintree_Transaction::saleNoValidate(array(
+ * 'customer' => array(
+ * 'firstName' => 'Adam',
+ * 'lastName' => 'Williams'
+ * ),
+ * 'creditCard' => array(
+ * 'number' => '5105105105105100',
+ * 'expirationDate' => '05/2012'
+ * ),
+ * 'options' => array(
+ * 'storeInVault' => true
+ * )
+ * ));
+ *
+ * echo $transaction->customerDetails->id
+ * // '865534'
+ * echo $transaction->creditCardDetails->token
+ * // '6b6m'
+ * </code>
+ *
+ * To also store the billing address in the vault, pass the
+ * <b>addBillingAddressToPaymentMethod</b> option.
+ * <code>
+ * Braintree_Transaction.saleNoValidate(array(
+ * ...
+ * 'options' => array(
+ * 'storeInVault' => true
+ * 'addBillingAddressToPaymentMethod' => true
+ * )
+ * ));
+ * </code>
+ *
+ * <b>== Submitting for Settlement==</b>
+ *
+ * This can only be done when the transction's
+ * status is <b>authorized</b>. If <b>amount</b> is not specified,
+ * the full authorized amount will be settled. If you would like to settle
+ * less than the full authorized amount, pass the desired amount.
+ * You cannot settle more than the authorized amount.
+ *
+ * A transaction can be submitted for settlement when created by setting
+ * $transaction[options][submitForSettlement] to true.
+ *
+ * <code>
+ * $transaction = Braintree_Transaction::saleNoValidate(array(
+ * 'amount' => '100.00',
+ * 'creditCard' => array(
+ * 'number' => '5105105105105100',
+ * 'expirationDate' => '05/2012'
+ * ),
+ * 'options' => array(
+ * 'submitForSettlement' => true
+ * )
+ * ));
+ * </code>
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Transactions, see {@link http://www.braintreepayments.com/gateway/transaction-api http://www.braintreepaymentsolutions.com/gateway/transaction-api}
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ *
+ * @property-read string $avsErrorResponseCode
+ * @property-read string $avsPostalCodeResponseCode
+ * @property-read string $avsStreetAddressResponseCode
+ * @property-read string $cvvResponseCode
+ * @property-read string $id transaction id
+ * @property-read string $amount transaction amount
+ * @property-read object $billingDetails transaction billing address
+ * @property-read string $createdAt transaction created timestamp
+ * @property-read object $applePayCardDetails transaction Apple Pay card info
+ * @property-read object $androidPayCardDetails transaction Android Pay card info
+ * @property-read object $creditCardDetails transaction credit card info
+ * @property-read object $coinbaseDetails transaction Coinbase account info
+ * @property-read object $paypalDetails transaction paypal account info
+ * @property-read object $customerDetails transaction customer info
+ * @property-read array $customFields custom fields passed with the request
+ * @property-read string $processorResponseCode gateway response code
+ * @property-read string $additionalProcessorResponse raw response from processor
+ * @property-read object $shippingDetails transaction shipping address
+ * @property-read string $status transaction status
+ * @property-read array $statusHistory array of StatusDetails objects
+ * @property-read string $type transaction type
+ * @property-read string $updatedAt transaction updated timestamp
+ * @property-read object $disbursementDetails populated when transaction is disbursed
+ * @property-read object $disputes populated when transaction is disputed
+ *
+ */
+
+final class Braintree_Transaction extends Braintree_Base
+{
+ // Transaction Status
+ const AUTHORIZATION_EXPIRED = 'authorization_expired';
+ const AUTHORIZING = 'authorizing';
+ const AUTHORIZED = 'authorized';
+ const GATEWAY_REJECTED = 'gateway_rejected';
+ const FAILED = 'failed';
+ const PROCESSOR_DECLINED = 'processor_declined';
+ const SETTLED = 'settled';
+ const SETTLING = 'settling';
+ const SUBMITTED_FOR_SETTLEMENT = 'submitted_for_settlement';
+ const VOIDED = 'voided';
+ const UNRECOGNIZED = 'unrecognized';
+ const SETTLEMENT_DECLINED = 'settlement_declined';
+ const SETTLEMENT_PENDING = 'settlement_pending';
+
+ // Transaction Escrow Status
+ const ESCROW_HOLD_PENDING = 'hold_pending';
+ const ESCROW_HELD = 'held';
+ const ESCROW_RELEASE_PENDING = 'release_pending';
+ const ESCROW_RELEASED = 'released';
+ const ESCROW_REFUNDED = 'refunded';
+
+ // Transaction Types
+ const SALE = 'sale';
+ const CREDIT = 'credit';
+
+ // Transaction Created Using
+ const FULL_INFORMATION = 'full_information';
+ const TOKEN = 'token';
+
+ // Transaction Sources
+ const API = 'api';
+ const CONTROL_PANEL = 'control_panel';
+ const RECURRING = 'recurring';
+
+ // Gateway Rejection Reason
+ const AVS = 'avs';
+ const AVS_AND_CVV = 'avs_and_cvv';
+ const CVV = 'cvv';
+ const DUPLICATE = 'duplicate';
+ const FRAUD = 'fraud';
+ const THREE_D_SECURE = 'three_d_secure';
+ const APPLICATION_INCOMPLETE = 'application_incomplete';
+
+ // Industry Types
+ const LODGING_INDUSTRY = 'lodging';
+ const TRAVEL_AND_CRUISE_INDUSTRY = 'travel_cruise';
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @ignore
+ * @access protected
+ * @param array $transactionAttribs array of transaction data
+ * @return none
+ */
+ protected function _initialize($transactionAttribs)
+ {
+ $this->_attributes = $transactionAttribs;
+
+ if (isset($transactionAttribs['applePay'])) {
+ $this->_set('applePayCardDetails',
+ new Braintree_Transaction_ApplePayCardDetails(
+ $transactionAttribs['applePay']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['androidPayCard'])) {
+ $this->_set('androidPayCardDetails',
+ new Braintree_Transaction_AndroidPayCardDetails(
+ $transactionAttribs['androidPayCard']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['creditCard'])) {
+ $this->_set('creditCardDetails',
+ new Braintree_Transaction_CreditCardDetails(
+ $transactionAttribs['creditCard']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['coinbaseAccount'])) {
+ $this->_set('coinbaseDetails',
+ new Braintree_Transaction_CoinbaseDetails(
+ $transactionAttribs['coinbaseAccount']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['paypal'])) {
+ $this->_set('paypalDetails',
+ new Braintree_Transaction_PayPalDetails(
+ $transactionAttribs['paypal']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['customer'])) {
+ $this->_set('customerDetails',
+ new Braintree_Transaction_CustomerDetails(
+ $transactionAttribs['customer']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['billing'])) {
+ $this->_set('billingDetails',
+ new Braintree_Transaction_AddressDetails(
+ $transactionAttribs['billing']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['shipping'])) {
+ $this->_set('shippingDetails',
+ new Braintree_Transaction_AddressDetails(
+ $transactionAttribs['shipping']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['subscription'])) {
+ $this->_set('subscriptionDetails',
+ new Braintree_Transaction_SubscriptionDetails(
+ $transactionAttribs['subscription']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['descriptor'])) {
+ $this->_set('descriptor',
+ new Braintree_Descriptor(
+ $transactionAttribs['descriptor']
+ )
+ );
+ }
+
+ if (isset($transactionAttribs['disbursementDetails'])) {
+ $this->_set('disbursementDetails',
+ new Braintree_DisbursementDetails($transactionAttribs['disbursementDetails'])
+ );
+ }
+
+ $disputes = array();
+ if (isset($transactionAttribs['disputes'])) {
+ foreach ($transactionAttribs['disputes'] AS $dispute) {
+ $disputes[] = Braintree_Dispute::factory($dispute);
+ }
+ }
+
+ $this->_set('disputes', $disputes);
+
+ $statusHistory = array();
+ if (isset($transactionAttribs['statusHistory'])) {
+ foreach ($transactionAttribs['statusHistory'] AS $history) {
+ $statusHistory[] = new Braintree_Transaction_StatusDetails($history);
+ }
+ }
+
+ $this->_set('statusHistory', $statusHistory);
+
+ $addOnArray = array();
+ if (isset($transactionAttribs['addOns'])) {
+ foreach ($transactionAttribs['addOns'] AS $addOn) {
+ $addOnArray[] = Braintree_AddOn::factory($addOn);
+ }
+ }
+ $this->_set('addOns', $addOnArray);
+
+ $discountArray = array();
+ if (isset($transactionAttribs['discounts'])) {
+ foreach ($transactionAttribs['discounts'] AS $discount) {
+ $discountArray[] = Braintree_Discount::factory($discount);
+ }
+ }
+ $this->_set('discounts', $discountArray);
+
+ if(isset($transactionAttribs['riskData'])) {
+ $this->_set('riskData', Braintree_RiskData::factory($transactionAttribs['riskData']));
+ }
+ if(isset($transactionAttribs['threeDSecureInfo'])) {
+ $this->_set('threeDSecureInfo', Braintree_ThreeDSecureInfo::factory($transactionAttribs['threeDSecureInfo']));
+ }
+ }
+
+ /**
+ * returns a string representation of the transaction
+ * @return string
+ */
+ public function __toString()
+ {
+ // array of attributes to print
+ $display = array(
+ 'id', 'type', 'amount', 'status',
+ 'createdAt', 'creditCardDetails', 'customerDetails'
+ );
+
+ $displayAttributes = array();
+ foreach ($display AS $attrib) {
+ $displayAttributes[$attrib] = $this->$attrib;
+ }
+ return __CLASS__ . '[' .
+ Braintree_Util::attributesToString($displayAttributes) .']';
+ }
+
+ public function isEqual($otherTx)
+ {
+ return $this->id === $otherTx->id;
+ }
+
+ public function vaultCreditCard()
+ {
+ $token = $this->creditCardDetails->token;
+ if (empty($token)) {
+ return null;
+ }
+ else {
+ return Braintree_CreditCard::find($token);
+ }
+ }
+
+ public function vaultCustomer()
+ {
+ $customerId = $this->customerDetails->id;
+ if (empty($customerId)) {
+ return null;
+ }
+ else {
+ return Braintree_Customer::find($customerId);
+ }
+ }
+
+ public function isDisbursed() {
+ return $this->disbursementDetails->isValid();
+ }
+
+ /**
+ * factory method: returns an instance of Braintree_Transaction
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_Transaction
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function cloneTransaction($transactionId, $attribs)
+ {
+ return Braintree_Configuration::gateway()->transaction()->cloneTransaction($transactionId, $attribs);
+ }
+
+ public static function createFromTransparentRedirect($queryString)
+ {
+ return Braintree_Configuration::gateway()->transaction()->createFromTransparentRedirect($queryString);
+ }
+
+ public static function createTransactionUrl()
+ {
+ return Braintree_Configuration::gateway()->transaction()->createTransactionUrl();
+ }
+
+ public static function credit($attribs)
+ {
+ return Braintree_Configuration::gateway()->transaction()->credit($attribs);
+ }
+
+ public static function creditNoValidate($attribs)
+ {
+ return Braintree_Configuration::gateway()->transaction()->creditNoValidate($attribs);
+ }
+
+ public static function find($id)
+ {
+ return Braintree_Configuration::gateway()->transaction()->find($id);
+ }
+
+ public static function sale($attribs)
+ {
+ return Braintree_Configuration::gateway()->transaction()->sale($attribs);
+ }
+
+ public static function saleNoValidate($attribs)
+ {
+ return Braintree_Configuration::gateway()->transaction()->saleNoValidate($attribs);
+ }
+
+ public static function search($query)
+ {
+ return Braintree_Configuration::gateway()->transaction()->search($query);
+ }
+
+ public static function fetch($query, $ids)
+ {
+ return Braintree_Configuration::gateway()->transaction()->fetch($query, $ids);
+ }
+
+ public static function void($transactionId)
+ {
+ return Braintree_Configuration::gateway()->transaction()->void($transactionId);
+ }
+
+ public static function voidNoValidate($transactionId)
+ {
+ return Braintree_Configuration::gateway()->transaction()->voidNoValidate($transactionId);
+ }
+
+ public static function submitForSettlement($transactionId, $amount = null)
+ {
+ return Braintree_Configuration::gateway()->transaction()->submitForSettlement($transactionId, $amount);
+ }
+
+ public static function submitForSettlementNoValidate($transactionId, $amount = null)
+ {
+ return Braintree_Configuration::gateway()->transaction()->submitForSettlementNoValidate($transactionId, $amount);
+ }
+
+ public static function holdInEscrow($transactionId)
+ {
+ return Braintree_Configuration::gateway()->transaction()->holdInEscrow($transactionId);
+ }
+
+ public static function releaseFromEscrow($transactionId)
+ {
+ return Braintree_Configuration::gateway()->transaction()->releaseFromEscrow($transactionId);
+ }
+
+ public static function cancelRelease($transactionId)
+ {
+ return Braintree_Configuration::gateway()->transaction()->cancelRelease($transactionId);
+ }
+
+ public static function refund($transactionId, $amount = null)
+ {
+ return Braintree_Configuration::gateway()->transaction()->refund($transactionId, $amount);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AddressDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AddressDetails.php
new file mode 100644
index 0000000..632df87
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AddressDetails.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Creates an instance of AddressDetails as returned from a transaction
+ *
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $firstName
+ * @property-read string $lastName
+ * @property-read string $company
+ * @property-read string $streetAddress
+ * @property-read string $extendedAddress
+ * @property-read string $locality
+ * @property-read string $region
+ * @property-read string $postalCode
+ * @property-read string $countryName
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_AddressDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AndroidPayCardDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AndroidPayCardDetails.php
new file mode 100644
index 0000000..f086346
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/AndroidPayCardDetails.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Android Pay card details from a transaction
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * creates an instance of AndroidPayCardDetails
+ *
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $bin
+ * @property-read string $default
+ * @property-read string $expirationMonth
+ * @property-read string $expirationYear
+ * @property-read string $googleTransactionId
+ * @property-read string $imageUrl
+ * @property-read string $sourceCardLast4
+ * @property-read string $sourceCardType
+ * @property-read string $token
+ * @property-read string $virtualCardLast4
+ * @property-read string $virtualCardType
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_AndroidPayCardDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+
+ /**
+ * @ignore
+ */
+ public function __construct($attributes)
+ {
+ parent::__construct($attributes);
+ $this->_attributes['cardType'] = $this->virtualCardType;
+ $this->_attributes['last4'] = $this->virtualCardLast4;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/ApplePayCardDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/ApplePayCardDetails.php
new file mode 100644
index 0000000..c5a56e3
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/ApplePayCardDetails.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Apple Pay card details from a transaction
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * creates an instance of ApplePayCardDetails
+ *
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $cardType
+ * @property-read string $paymentInstrumentName
+ * @property-read string $expirationMonth
+ * @property-read string $expirationYear
+ * @property-read string $cardholderName
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_ApplePayCardDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+
+ /**
+ * @ignore
+ */
+ public function __construct($attributes)
+ {
+ parent::__construct($attributes);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CoinbaseDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CoinbaseDetails.php
new file mode 100644
index 0000000..2ced02f
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CoinbaseDetails.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Coinbase details from a transaction
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * creates an instance of Coinbase
+ *
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $token
+ * @property-read string $userId
+ * @property-read string $userName
+ * @property-read string $userEmail
+ * @property-read string $imageUrl
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_CoinbaseDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+
+ /**
+ * @ignore
+ */
+ public function __construct($attributes)
+ {
+ parent::__construct($attributes);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CreditCardDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CreditCardDetails.php
new file mode 100644
index 0000000..4f2797e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CreditCardDetails.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * CreditCard details from a transaction
+ * creates an instance of CreditCardDetails
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $bin
+ * @property-read string $cardType
+ * @property-read string $expirationDate
+ * @property-read string $expirationMonth
+ * @property-read string $expirationYear
+ * @property-read string $issuerLocation
+ * @property-read string $last4
+ * @property-read string $maskedNumber
+ * @property-read string $token
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_CreditCardDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+
+ /**
+ * @ignore
+ */
+ public function __construct($attributes)
+ {
+ parent::__construct($attributes);
+ $this->_attributes['expirationDate'] = $this->expirationMonth . '/' . $this->expirationYear;
+ $this->_attributes['maskedNumber'] = $this->bin . '******' . $this->last4;
+
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CustomerDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CustomerDetails.php
new file mode 100644
index 0000000..80685c9
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/CustomerDetails.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Customer details from a transaction
+ * Creates an instance of customer details as returned from a transaction
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $company
+ * @property-read string $email
+ * @property-read string $fax
+ * @property-read string $firstName
+ * @property-read string $id
+ * @property-read string $lastName
+ * @property-read string $phone
+ * @property-read string $website
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_CustomerDetails extends Braintree_Instance
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/PayPalDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/PayPalDetails.php
new file mode 100644
index 0000000..059766f
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/PayPalDetails.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * PayPal details from a transaction
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * creates an instance of PayPalDetails
+ *
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $payerEmail
+ * @property-read string $paymentId
+ * @property-read string $authorizationId
+ * @property-read string $token
+ * @property-read string $imageUrl
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_PayPalDetails extends Braintree_Instance
+{
+ protected $_attributes = array();
+
+ /**
+ * @ignore
+ */
+ public function __construct($attributes)
+ {
+ parent::__construct($attributes);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/StatusDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/StatusDetails.php
new file mode 100644
index 0000000..ba525fe
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/StatusDetails.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Status details from a transaction
+ * Creates an instance of StatusDetails, as part of a transaction response
+ *
+ * @package Braintree
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $amount
+ * @property-read string $status
+ * @property-read string $timestamp
+ * @property-read string $transactionSource
+ * @property-read string $user
+ * @uses Braintree_Instance inherits methods
+ */
+class Braintree_Transaction_StatusDetails extends Braintree_Instance
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/SubscriptionDetails.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/SubscriptionDetails.php
new file mode 100644
index 0000000..311c909
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Transaction/SubscriptionDetails.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Customer details from a transaction
+ * Creates an instance of customer details as returned from a transaction
+ *
+ * @package Braintree
+ * @subpackage Transaction
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $billing_period_start_date
+ * @property-read string $billing_period_end_date
+ */
+class Braintree_Transaction_SubscriptionDetails extends Braintree_Instance
+{
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionGateway.php
new file mode 100644
index 0000000..eb006e4
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionGateway.php
@@ -0,0 +1,445 @@
+<?php
+/**
+ * Braintree TransactionGateway processor
+ * Creates and manages transactions
+ *
+ *
+ * <b>== More information ==</b>
+ *
+ * For more detailed information on Transactions, see {@link http://www.braintreepayments.com/gateway/transaction-api http://www.braintreepaymentsolutions.com/gateway/transaction-api}
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+final class Braintree_TransactionGateway
+{
+ private $_gateway;
+ private $_config;
+ private $_http;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ $this->_http = new Braintree_Http($gateway->config);
+ }
+
+ public function cloneTransaction($transactionId, $attribs)
+ {
+ Braintree_Util::verifyKeys(self::cloneSignature(), $attribs);
+ return $this->_doCreate('/transactions/' . $transactionId . '/clone', array('transactionClone' => $attribs));
+ }
+
+ /**
+ * @ignore
+ * @access private
+ * @param array $attribs
+ * @return object
+ */
+ private function create($attribs)
+ {
+ Braintree_Util::verifyKeys(self::createSignature(), $attribs);
+ return $this->_doCreate('/transactions', array('transaction' => $attribs));
+ }
+
+ /**
+ *
+ * @ignore
+ * @access private
+ * @param array $attribs
+ * @return object
+ * @throws Braintree_Exception_ValidationError
+ */
+ private function createNoValidate($attribs)
+ {
+ $result = $this->create($attribs);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+ /**
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ */
+ public function createFromTransparentRedirect($queryString)
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
+ $params = Braintree_TransparentRedirect::parseAndValidateQueryString(
+ $queryString
+ );
+ return $this->_doCreate(
+ '/transactions/all/confirm_transparent_redirect_request',
+ array('id' => $params['id'])
+ );
+ }
+ /**
+ *
+ * @access public
+ * @param none
+ * @return string
+ */
+ public function createTransactionUrl()
+ {
+ trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
+ return $this->_config->baseUrl() . $this->_config->merchantPath() .
+ '/transactions/all/create_via_transparent_redirect_request';
+ }
+
+ public static function cloneSignature()
+ {
+ return array('amount', 'channel', array('options' => array('submitForSettlement')));
+ }
+
+ /**
+ * creates a full array signature of a valid gateway request
+ * @return array gateway request signature format
+ */
+ public static function createSignature()
+ {
+ return array(
+ 'amount',
+ 'billingAddressId',
+ 'channel',
+ 'customerId',
+ 'deviceData',
+ 'deviceSessionId',
+ 'fraudMerchantId',
+ 'merchantAccountId',
+ 'orderId',
+ 'paymentMethodNonce',
+ 'paymentMethodToken',
+ 'purchaseOrderNumber',
+ 'recurring',
+ 'serviceFeeAmount',
+ 'shippingAddressId',
+ 'taxAmount',
+ 'taxExempt',
+ 'threeDSecureToken',
+ 'type',
+ 'venmoSdkPaymentMethodCode',
+ array('creditCard' =>
+ array('token', 'cardholderName', 'cvv', 'expirationDate', 'expirationMonth', 'expirationYear', 'number'),
+ ),
+ array('customer' =>
+ array(
+ 'id', 'company', 'email', 'fax', 'firstName',
+ 'lastName', 'phone', 'website'),
+ ),
+ array('billing' =>
+ array(
+ 'firstName', 'lastName', 'company', 'countryName',
+ 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric',
+ 'extendedAddress', 'locality', 'postalCode', 'region',
+ 'streetAddress'),
+ ),
+ array('shipping' =>
+ array(
+ 'firstName', 'lastName', 'company', 'countryName',
+ 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryCodeNumeric',
+ 'extendedAddress', 'locality', 'postalCode', 'region',
+ 'streetAddress'),
+ ),
+ array('options' =>
+ array(
+ 'holdInEscrow',
+ 'storeInVault',
+ 'storeInVaultOnSuccess',
+ 'submitForSettlement',
+ 'addBillingAddressToPaymentMethod',
+ 'venmoSdkSession',
+ 'storeShippingAddressInVault',
+ 'payeeEmail',
+ array('three_d_secure' =>
+ array('required')
+ ),
+ array('paypal' =>
+ array(
+ 'payeeEmail',
+ 'customField'
+ )
+ )
+ ),
+ ),
+ array('customFields' => array('_anyKey_')
+ ),
+ array('descriptor' => array('name', 'phone', 'url')),
+ array('paypalAccount' => array('payeeEmail')),
+ array('industry' =>
+ array('industryType',
+ array('data' =>
+ array(
+ 'folioNumber',
+ 'checkInDate',
+ 'checkOutDate',
+ 'travelPackage',
+ 'departureDate',
+ 'lodgingCheckInDate',
+ 'lodgingCheckOutDate',
+ 'lodgingName',
+ 'roomRate'
+ )
+ )
+ )
+ )
+ );
+ }
+
+ /**
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ */
+ public function credit($attribs)
+ {
+ return $this->create(array_merge($attribs, array('type' => Braintree_Transaction::CREDIT)));
+ }
+
+ /**
+ *
+ * @access public
+ * @param array $attribs
+ * @return object
+ * @throws Braintree_Exception_ValidationError
+ */
+ public function creditNoValidate($attribs)
+ {
+ $result = $this->credit($attribs);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+
+
+ /**
+ * @access public
+ *
+ */
+ public function find($id)
+ {
+ $this->_validateId($id);
+ try {
+ $path = $this->_config->merchantPath() . '/transactions/' . $id;
+ $response = $this->_http->get($path);
+ return Braintree_Transaction::factory($response['transaction']);
+ } catch (Braintree_Exception_NotFound $e) {
+ throw new Braintree_Exception_NotFound(
+ 'transaction with id ' . $id . ' not found'
+ );
+ }
+
+ }
+ /**
+ * new sale
+ * @param array $attribs
+ * @return array
+ */
+ public function sale($attribs)
+ {
+ return $this->create(array_merge(array('type' => Braintree_Transaction::SALE), $attribs));
+ }
+
+ /**
+ * roughly equivalent to the ruby bang method
+ * @access public
+ * @param array $attribs
+ * @return array
+ * @throws Braintree_Exception_ValidationsFailed
+ */
+ public function saleNoValidate($attribs)
+ {
+ $result = $this->sale($attribs);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+
+ /**
+ * Returns a ResourceCollection of transactions matching the search query.
+ *
+ * If <b>query</b> is a string, the search will be a basic search.
+ * If <b>query</b> is a hash, the search will be an advanced search.
+ * For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/transaction-api#searching http://www.braintreepaymentsolutions.com/gateway/transaction-api}
+ *
+ * @param mixed $query search query
+ * @param array $options options such as page number
+ * @return object Braintree_ResourceCollection
+ * @throws InvalidArgumentException
+ */
+ public function search($query)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+
+ $path = $this->_config->merchantPath() . '/transactions/advanced_search_ids';
+ $response = $this->_http->post($path, array('search' => $criteria));
+ if (array_key_exists('searchResults', $response)) {
+ $pager = array(
+ 'object' => $this,
+ 'method' => 'fetch',
+ 'methodArgs' => array($query)
+ );
+
+ return new Braintree_ResourceCollection($response, $pager);
+ } else {
+ throw new Braintree_Exception_DownForMaintenance();
+ }
+ }
+
+ public function fetch($query, $ids)
+ {
+ $criteria = array();
+ foreach ($query as $term) {
+ $criteria[$term->name] = $term->toparam();
+ }
+ $criteria["ids"] = Braintree_TransactionSearch::ids()->in($ids)->toparam();
+ $path = $this->_config->merchantPath() . '/transactions/advanced_search';
+ $response = $this->_http->post($path, array('search' => $criteria));
+
+ return Braintree_Util::extractattributeasarray(
+ $response['creditCardTransactions'],
+ 'transaction'
+ );
+ }
+
+ /**
+ * void a transaction by id
+ *
+ * @param string $id transaction id
+ * @return object Braintree_Result_Successful|Braintree_Result_Error
+ */
+ public function void($transactionId)
+ {
+ $this->_validateId($transactionId);
+
+ $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/void';
+ $response = $this->_http->put($path);
+ return $this->_verifyGatewayResponse($response);
+ }
+ /**
+ *
+ */
+ public function voidNoValidate($transactionId)
+ {
+ $result = $this->void($transactionId);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+
+ public function submitForSettlement($transactionId, $amount = null)
+ {
+ $this->_validateId($transactionId);
+
+ $path = $this->_config->merchantPath() . '/transactions/'. $transactionId . '/submit_for_settlement';
+ $response = $this->_http->put($path, array('transaction' => array('amount' => $amount)));
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function submitForSettlementNoValidate($transactionId, $amount = null)
+ {
+ $result = $this->submitForSettlement($transactionId, $amount);
+ return Braintree_Util::returnObjectOrThrowException(__CLASS__, $result);
+ }
+
+ public function holdInEscrow($transactionId)
+ {
+ $this->_validateId($transactionId);
+
+ $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/hold_in_escrow';
+ $response = $this->_http->put($path, array());
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function releaseFromEscrow($transactionId)
+ {
+ $this->_validateId($transactionId);
+
+ $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/release_from_escrow';
+ $response = $this->_http->put($path, array());
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function cancelRelease($transactionId)
+ {
+ $this->_validateId($transactionId);
+
+ $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/cancel_release';
+ $response = $this->_http->put($path, array());
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ public function refund($transactionId, $amount = null)
+ {
+ self::_validateId($transactionId);
+
+ $params = array('transaction' => array('amount' => $amount));
+ $path = $this->_config->merchantPath() . '/transactions/' . $transactionId . '/refund';
+ $response = $this->_http->post($path, $params);
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * sends the create request to the gateway
+ *
+ * @ignore
+ * @param var $subPath
+ * @param array $params
+ * @return mixed
+ */
+ public function _doCreate($subPath, $params)
+ {
+ $fullPath = $this->_config->merchantPath() . $subPath;
+ $response = $this->_http->post($fullPath, $params);
+
+ return $this->_verifyGatewayResponse($response);
+ }
+
+ /**
+ * verifies that a valid transaction id is being used
+ * @ignore
+ * @param string transaction id
+ * @throws InvalidArgumentException
+ */
+ private function _validateId($id = null) {
+ if (empty($id)) {
+ throw new InvalidArgumentException(
+ 'expected transaction id to be set'
+ );
+ }
+ if (!preg_match('/^[0-9a-z]+$/', $id)) {
+ throw new InvalidArgumentException(
+ $id . ' is an invalid transaction id.'
+ );
+ }
+ }
+
+
+ /**
+ * generic method for validating incoming gateway responses
+ *
+ * creates a new Braintree_Transaction object and encapsulates
+ * it inside a Braintree_Result_Successful object, or
+ * encapsulates a Braintree_Errors object inside a Result_Error
+ * alternatively, throws an Unexpected exception if the response is invalid.
+ *
+ * @ignore
+ * @param array $response gateway response values
+ * @return object Result_Successful or Result_Error
+ * @throws Braintree_Exception_Unexpected
+ */
+ private function _verifyGatewayResponse($response)
+ {
+ if (isset($response['transaction'])) {
+ // return a populated instance of Braintree_Transaction
+ return new Braintree_Result_Successful(
+ Braintree_Transaction::factory($response['transaction'])
+ );
+ } else if (isset($response['apiErrorResponse'])) {
+ return new Braintree_Result_Error($response['apiErrorResponse']);
+ } else {
+ throw new Braintree_Exception_Unexpected(
+ "Expected transaction or apiErrorResponse"
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionSearch.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionSearch.php
new file mode 100644
index 0000000..82286a1
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransactionSearch.php
@@ -0,0 +1,129 @@
+<?php
+class Braintree_TransactionSearch
+{
+ static function amount() { return new Braintree_RangeNode("amount"); }
+ static function authorizationExpiredAt() { return new Braintree_RangeNode("authorizationExpiredAt"); }
+ static function authorizedAt() { return new Braintree_RangeNode("authorizedAt"); }
+ static function billingCompany() { return new Braintree_TextNode('billing_company'); }
+ static function billingCountryName() { return new Braintree_TextNode('billing_country_name'); }
+ static function billingExtendedAddress() { return new Braintree_TextNode('billing_extended_address'); }
+ static function billingFirstName() { return new Braintree_TextNode('billing_first_name'); }
+ static function billingLastName() { return new Braintree_TextNode('billing_last_name'); }
+ static function billingLocality() { return new Braintree_TextNode('billing_locality'); }
+ static function billingPostalCode() { return new Braintree_TextNode('billing_postal_code'); }
+ static function billingRegion() { return new Braintree_TextNode('billing_region'); }
+ static function billingStreetAddress() { return new Braintree_TextNode('billing_street_address'); }
+ static function createdAt() { return new Braintree_RangeNode("createdAt"); }
+ static function creditCardCardholderName() { return new Braintree_TextNode('credit_card_cardholderName'); }
+ static function creditCardExpirationDate() { return new Braintree_EqualityNode('credit_card_expiration_date'); }
+ static function creditCardNumber() { return new Braintree_PartialMatchNode('credit_card_number'); }
+ static function creditCardUniqueIdentifier() { return new Braintree_TextNode('credit_card_unique_identifier'); }
+ static function customerCompany() { return new Braintree_TextNode('customer_company'); }
+ static function customerEmail() { return new Braintree_TextNode('customer_email'); }
+ static function customerFax() { return new Braintree_TextNode('customer_fax'); }
+ static function customerFirstName() { return new Braintree_TextNode('customer_first_name'); }
+ static function customerId() { return new Braintree_TextNode('customer_id'); }
+ static function customerLastName() { return new Braintree_TextNode('customer_last_name'); }
+ static function customerPhone() { return new Braintree_TextNode('customer_phone'); }
+ static function customerWebsite() { return new Braintree_TextNode('customer_website'); }
+ static function disbursementDate() { return new Braintree_RangeNode("disbursementDate"); }
+ static function disputeDate() { return new Braintree_RangeNode("disputeDate"); }
+ static function failedAt() { return new Braintree_RangeNode("failedAt"); }
+ static function gatewayRejectedAt() { return new Braintree_RangeNode("gatewayRejectedAt"); }
+ static function id() { return new Braintree_TextNode('id'); }
+ static function ids() { return new Braintree_MultipleValueNode('ids'); }
+ static function merchantAccountId() { return new Braintree_MultipleValueNode("merchant_account_id"); }
+ static function orderId() { return new Braintree_TextNode('order_id'); }
+ static function paymentInstrumentType() { return new Braintree_MultipleValueNode('paymentInstrumentType'); }
+ static function paymentMethodToken() { return new Braintree_TextNode('payment_method_token'); }
+ static function paypalAuthorizationId() { return new Braintree_TextNode('paypal_authorization_id'); }
+ static function paypalPayerEmail() { return new Braintree_TextNode('paypal_payer_email'); }
+ static function paypalPaymentId() { return new Braintree_TextNode('paypal_payment_id'); }
+ static function processorAuthorizationCode() { return new Braintree_TextNode('processor_authorization_code'); }
+ static function processorDeclinedAt() { return new Braintree_RangeNode("processorDeclinedAt"); }
+ static function refund() { return new Braintree_KeyValueNode("refund"); }
+ static function settledAt() { return new Braintree_RangeNode("settledAt"); }
+ static function settlementBatchId() { return new Braintree_TextNode('settlement_batch_id'); }
+ static function shippingCompany() { return new Braintree_TextNode('shipping_company'); }
+ static function shippingCountryName() { return new Braintree_TextNode('shipping_country_name'); }
+ static function shippingExtendedAddress() { return new Braintree_TextNode('shipping_extended_address'); }
+ static function shippingFirstName() { return new Braintree_TextNode('shipping_first_name'); }
+ static function shippingLastName() { return new Braintree_TextNode('shipping_last_name'); }
+ static function shippingLocality() { return new Braintree_TextNode('shipping_locality'); }
+ static function shippingPostalCode() { return new Braintree_TextNode('shipping_postal_code'); }
+ static function shippingRegion() { return new Braintree_TextNode('shipping_region'); }
+ static function shippingStreetAddress() { return new Braintree_TextNode('shipping_street_address'); }
+ static function submittedForSettlementAt() { return new Braintree_RangeNode("submittedForSettlementAt"); }
+ static function user() { return new Braintree_MultipleValueNode('user'); }
+ static function voidedAt() { return new Braintree_RangeNode("voidedAt"); }
+
+ static function createdUsing()
+ {
+ return new Braintree_MultipleValueNode("created_using", array(
+ Braintree_Transaction::FULL_INFORMATION,
+ Braintree_Transaction::TOKEN
+ ));
+ }
+
+ static function creditCardCardType()
+ {
+ return new Braintree_MultipleValueNode("credit_card_card_type", array(
+ Braintree_CreditCard::AMEX,
+ Braintree_CreditCard::CARTE_BLANCHE,
+ Braintree_CreditCard::CHINA_UNION_PAY,
+ Braintree_CreditCard::DINERS_CLUB_INTERNATIONAL,
+ Braintree_CreditCard::DISCOVER,
+ Braintree_CreditCard::JCB,
+ Braintree_CreditCard::LASER,
+ Braintree_CreditCard::MAESTRO,
+ Braintree_CreditCard::MASTER_CARD,
+ Braintree_CreditCard::SOLO,
+ Braintree_CreditCard::SWITCH_TYPE,
+ Braintree_CreditCard::VISA,
+ Braintree_CreditCard::UNKNOWN
+ ));
+ }
+
+ static function creditCardCustomerLocation()
+ {
+ return new Braintree_MultipleValueNode("credit_card_customer_location", array(
+ Braintree_CreditCard::INTERNATIONAL,
+ Braintree_CreditCard::US
+ ));
+ }
+
+ static function source()
+ {
+ return new Braintree_MultipleValueNode("source", array(
+ Braintree_Transaction::API,
+ Braintree_Transaction::CONTROL_PANEL,
+ Braintree_Transaction::RECURRING,
+ ));
+ }
+
+ static function status()
+ {
+ return new Braintree_MultipleValueNode("status", array(
+ Braintree_Transaction::AUTHORIZATION_EXPIRED,
+ Braintree_Transaction::AUTHORIZING,
+ Braintree_Transaction::AUTHORIZED,
+ Braintree_Transaction::GATEWAY_REJECTED,
+ Braintree_Transaction::FAILED,
+ Braintree_Transaction::PROCESSOR_DECLINED,
+ Braintree_Transaction::SETTLED,
+ Braintree_Transaction::SETTLING,
+ Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT,
+ Braintree_Transaction::VOIDED,
+ Braintree_Transaction::SETTLEMENT_DECLINED,
+ Braintree_Transaction::SETTLEMENT_PENDING
+ ));
+ }
+
+ static function type()
+ {
+ return new Braintree_MultipleValueNode("type", array(
+ Braintree_Transaction::SALE,
+ Braintree_Transaction::CREDIT
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirect.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirect.php
new file mode 100644
index 0000000..05ec3d4
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirect.php
@@ -0,0 +1,100 @@
+<?php
+
+
+/**
+ * Braintree Transparent Redirect module
+ * Static class providing methods to build Transparent Redirect urls
+ *
+ * The TransparentRedirect module provides methods to build the tr_data param
+ * that must be submitted when using the transparent redirect API.
+ * For more information
+ * about transparent redirect, see (TODO).
+ *
+ * You must provide a redirectUrl to which the gateway will redirect the
+ * user the action is complete.
+ *
+ * <code>
+ * $trData = Braintree_TransparentRedirect::createCustomerData(array(
+ * 'redirectUrl => 'http://example.com/redirect_back_to_merchant_site',
+ * ));
+ * </code>
+ *
+ * In addition to the redirectUrl, any data that needs to be protected
+ * from user tampering should be included in the trData.
+ * For example, to prevent the user from tampering with the transaction
+ * amount, include the amount in the trData.
+ *
+ * <code>
+ * $trData = Braintree_TransparentRedirect::transactionData(array(
+ * 'redirectUrl' => 'http://example.com/complete_transaction',
+ * 'transaction' => array('amount' => '100.00'),
+ * ));
+ *
+ * </code>
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_TransparentRedirect
+{
+ // Request Kinds
+ const CREATE_TRANSACTION = 'create_transaction';
+ const CREATE_PAYMENT_METHOD = 'create_payment_method';
+ const UPDATE_PAYMENT_METHOD = 'update_payment_method';
+ const CREATE_CUSTOMER = 'create_customer';
+ const UPDATE_CUSTOMER = 'update_customer';
+
+ /**
+ * @ignore
+ * don't permit an explicit call of the constructor!
+ * (like $t = new Braintree_TransparentRedirect())
+ */
+ protected function __construct()
+ {
+
+ }
+
+
+ // static methods redirecting to gateway
+
+ public static function confirm($queryString)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->confirm($queryString);
+ }
+
+ public static function createCreditCardData($params)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->createCreditCardData($params);
+ }
+
+ public static function createCustomerData($params)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->createCustomerData($params);
+ }
+
+ public static function url()
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->url();
+ }
+
+ public static function transactionData($params)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->transactionData($params);
+ }
+
+ public static function updateCreditCardData($params)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->updateCreditCardData($params);
+ }
+
+ public static function updateCustomerData($params)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->updateCustomerData($params);
+ }
+
+ public static function parseAndValidateQueryString($queryString)
+ {
+ return Braintree_Configuration::gateway()->transparentRedirect()->parseAndValidateQueryString($queryString);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirectGateway.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirectGateway.php
new file mode 100644
index 0000000..c2212a2
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/TransparentRedirectGateway.php
@@ -0,0 +1,283 @@
+<?php
+/**
+ * Braintree Transparent Redirect Gateway module
+ * Static class providing methods to build Transparent Redirect urls
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_TransparentRedirectGateway
+{
+ private $_gateway;
+ private $_config;
+
+ public function __construct($gateway)
+ {
+ $this->_gateway = $gateway;
+ $this->_config = $gateway->config;
+ $this->_config->assertHasAccessTokenOrKeys();
+ }
+
+ /**
+ *
+ * @ignore
+ */
+ private static $_transparentRedirectKeys = 'redirectUrl';
+ private static $_createCustomerSignature;
+ private static $_updateCustomerSignature;
+ private static $_transactionSignature;
+ private static $_createCreditCardSignature;
+ private static $_updateCreditCardSignature;
+
+ /**
+ * create signatures for different call types
+ * @ignore
+ */
+ public static function init()
+ {
+
+ self::$_createCustomerSignature = array(
+ self::$_transparentRedirectKeys,
+ array('customer' => Braintree_CustomerGateway::createSignature()),
+ );
+ self::$_updateCustomerSignature = array(
+ self::$_transparentRedirectKeys,
+ 'customerId',
+ array('customer' => Braintree_CustomerGateway::updateSignature()),
+ );
+ self::$_transactionSignature = array(
+ self::$_transparentRedirectKeys,
+ array('transaction' => Braintree_TransactionGateway::createSignature()),
+ );
+ self::$_createCreditCardSignature = array(
+ self::$_transparentRedirectKeys,
+ array('creditCard' => Braintree_CreditCardGateway::createSignature()),
+ );
+ self::$_updateCreditCardSignature = array(
+ self::$_transparentRedirectKeys,
+ 'paymentMethodToken',
+ array('creditCard' => Braintree_CreditCardGateway::updateSignature()),
+ );
+ }
+
+ public function confirm($queryString)
+ {
+ $params = Braintree_TransparentRedirect::parseAndValidateQueryString(
+ $queryString
+ );
+ $confirmationKlasses = array(
+ Braintree_TransparentRedirect::CREATE_TRANSACTION => 'Braintree_TransactionGateway',
+ Braintree_TransparentRedirect::CREATE_CUSTOMER => 'Braintree_CustomerGateway',
+ Braintree_TransparentRedirect::UPDATE_CUSTOMER => 'Braintree_CustomerGateway',
+ Braintree_TransparentRedirect::CREATE_PAYMENT_METHOD => 'Braintree_CreditCardGateway',
+ Braintree_TransparentRedirect::UPDATE_PAYMENT_METHOD => 'Braintree_CreditCardGateway'
+ );
+ $confirmationGateway = new $confirmationKlasses[$params["kind"]]($this->_gateway);
+ return $confirmationGateway->_doCreate('/transparent_redirect_requests/' . $params['id'] . '/confirm', array());
+ }
+
+ /**
+ * returns the trData string for creating a credit card,
+ * @param array $params
+ * @return string
+ */
+ public function createCreditCardData($params)
+ {
+ Braintree_Util::verifyKeys(
+ self::$_createCreditCardSignature,
+ $params
+ );
+ $params["kind"] = Braintree_TransparentRedirect::CREATE_PAYMENT_METHOD;
+ return $this->_data($params);
+ }
+
+ /**
+ * returns the trData string for creating a customer.
+ * @param array $params
+ * @return string
+ */
+ public function createCustomerData($params)
+ {
+ Braintree_Util::verifyKeys(
+ self::$_createCustomerSignature,
+ $params
+ );
+ $params["kind"] = Braintree_TransparentRedirect::CREATE_CUSTOMER;
+ return $this->_data($params);
+
+ }
+
+ public function url()
+ {
+ return $this->_config->baseUrl() . $this->_config->merchantPath() . "/transparent_redirect_requests";
+ }
+
+ /**
+ * returns the trData string for creating a transaction
+ * @param array $params
+ * @return string
+ */
+ public function transactionData($params)
+ {
+ Braintree_Util::verifyKeys(
+ self::$_transactionSignature,
+ $params
+ );
+ $params["kind"] = Braintree_TransparentRedirect::CREATE_TRANSACTION;
+ $transactionType = isset($params['transaction']['type']) ?
+ $params['transaction']['type'] :
+ null;
+ if ($transactionType != Braintree_Transaction::SALE && $transactionType != Braintree_Transaction::CREDIT) {
+ throw new InvalidArgumentException(
+ 'expected transaction[type] of sale or credit, was: ' .
+ $transactionType
+ );
+ }
+
+ return $this->_data($params);
+ }
+
+ /**
+ * Returns the trData string for updating a credit card.
+ *
+ * The paymentMethodToken of the credit card to update is required.
+ *
+ * <code>
+ * $trData = Braintree_TransparentRedirect::updateCreditCardData(array(
+ * 'redirectUrl' => 'http://example.com/redirect_here',
+ * 'paymentMethodToken' => 'token123',
+ * ));
+ * </code>
+ *
+ * @param array $params
+ * @return string
+ */
+ public function updateCreditCardData($params)
+ {
+ Braintree_Util::verifyKeys(
+ self::$_updateCreditCardSignature,
+ $params
+ );
+ if (!isset($params['paymentMethodToken'])) {
+ throw new InvalidArgumentException(
+ 'expected params to contain paymentMethodToken.'
+ );
+ }
+ $params["kind"] = Braintree_TransparentRedirect::UPDATE_PAYMENT_METHOD;
+ return $this->_data($params);
+ }
+
+ /**
+ * Returns the trData string for updating a customer.
+ *
+ * The customerId of the customer to update is required.
+ *
+ * <code>
+ * $trData = Braintree_TransparentRedirect::updateCustomerData(array(
+ * 'redirectUrl' => 'http://example.com/redirect_here',
+ * 'customerId' => 'customer123',
+ * ));
+ * </code>
+ *
+ * @param array $params
+ * @return string
+ */
+ public function updateCustomerData($params)
+ {
+ Braintree_Util::verifyKeys(
+ self::$_updateCustomerSignature,
+ $params
+ );
+ if (!isset($params['customerId'])) {
+ throw new InvalidArgumentException(
+ 'expected params to contain customerId of customer to update'
+ );
+ }
+ $params["kind"] = Braintree_TransparentRedirect::UPDATE_CUSTOMER;
+ return $this->_data($params);
+ }
+
+ public function parseAndValidateQueryString($queryString)
+ {
+ // parse the params into an array
+ parse_str($queryString, $params);
+ // remove the hash
+ $queryStringWithoutHash = null;
+ if(preg_match('/^(.*)&hash=[a-f0-9]+$/', $queryString, $match)) {
+ $queryStringWithoutHash = $match[1];
+ }
+
+ if($params['http_status'] != '200') {
+ $message = null;
+ if(array_key_exists('bt_message', $params)) {
+ $message = $params['bt_message'];
+ }
+ Braintree_Util::throwStatusCodeException($params['http_status'], $message);
+ }
+
+ // recreate the hash and compare it
+ if($this->_hash($queryStringWithoutHash) == $params['hash']) {
+ return $params;
+ } else {
+ throw new Braintree_Exception_ForgedQueryString();
+ }
+ }
+
+
+ /**
+ *
+ * @ignore
+ */
+ private function _data($params)
+ {
+ if (!isset($params['redirectUrl'])) {
+ throw new InvalidArgumentException(
+ 'expected params to contain redirectUrl'
+ );
+ }
+ $params = $this->_underscoreKeys($params);
+ $now = new DateTime('now', new DateTimeZone('UTC'));
+ $trDataParams = array_merge($params,
+ array(
+ 'api_version' => Braintree_Configuration::API_VERSION,
+ 'public_key' => $this->_config->publicKey(),
+ 'time' => $now->format('YmdHis'),
+ )
+ );
+ ksort($trDataParams);
+ $urlEncodedData = http_build_query($trDataParams, null, "&");
+ $signatureService = new Braintree_SignatureService(
+ $this->_config->privateKey(),
+ "Braintree_Digest::hexDigestSha1"
+ );
+ return $signatureService->sign($urlEncodedData);
+ }
+
+ private function _underscoreKeys($array)
+ {
+ foreach($array as $key=>$value)
+ {
+ $newKey = Braintree_Util::camelCaseToDelimiter($key, '_');
+ unset($array[$key]);
+ if (is_array($value))
+ {
+ $array[$newKey] = $this->_underscoreKeys($value);
+ }
+ else
+ {
+ $array[$newKey] = $value;
+ }
+ }
+ return $array;
+ }
+
+ /**
+ * @ignore
+ */
+ private function _hash($string)
+ {
+ return Braintree_Digest::hexDigestSha1($this->_config->privateKey(), $string);
+ }
+}
+Braintree_TransparentRedirectGateway::init();
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/UnknownPaymentMethod.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/UnknownPaymentMethod.php
new file mode 100644
index 0000000..bbfeef3
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/UnknownPaymentMethod.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Braintree UnknownPaymentMethod module
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Manages Braintree UnknownPaymentMethod
+ *
+ * <b>== More information ==</b>
+ *
+ *
+ * @package Braintree
+ * @category Resources
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ *
+ * @property-read string $token
+ * @property-read string $imageUrl
+ */
+class Braintree_UnknownPaymentMethod extends Braintree_Base
+{
+
+
+ /**
+ * factory method: returns an instance of Braintree_UnknownPaymentMethod
+ * to the requesting method, with populated properties
+ *
+ * @ignore
+ * @return object instance of Braintree_UnknownPaymentMethod
+ */
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $values = array_values($attributes);
+ $instance->_initialize(array_shift($values));
+ return $instance;
+ }
+
+ /* instance methods */
+
+ /**
+ * returns false if default is null or false
+ *
+ * @return boolean
+ */
+ public function isDefault()
+ {
+ return $this->default;
+ }
+
+ /**
+ * sets instance properties from an array of values
+ *
+ * @access protected
+ * @param array $unknownPaymentMethodAttribs array of unknownPaymentMethod data
+ * @return none
+ */
+ protected function _initialize($unknownPaymentMethodAttribs)
+ {
+ // set the attributes
+ $this->imageUrl = 'https://assets.braintreegateway.com/payment_method_logo/unknown.png';
+ $this->_attributes = $unknownPaymentMethodAttribs;
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Util.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Util.php
new file mode 100644
index 0000000..d59c2f5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Util.php
@@ -0,0 +1,383 @@
+<?php
+/**
+ * Braintree Utility methods
+ * PHP version 5
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+class Braintree_Util
+{
+ /**
+ * extracts an attribute and returns an array of objects
+ *
+ * extracts the requested element from an array, and converts the contents
+ * of its child arrays to objects of type Braintree_$attributeName, or returns
+ * an array with a single element containing the value of that array element
+ *
+ * @param array $attribArray attributes from a search response
+ * @param string $attributeName indicates which element of the passed array to extract
+ * @return array array of Braintree_$attributeName objects, or a single element array
+ */
+ public static function extractAttributeAsArray(& $attribArray, $attributeName)
+ {
+ if(!isset($attribArray[$attributeName])):
+ return array();
+ endif;
+
+ // get what should be an array from the passed array
+ $data = $attribArray[$attributeName];
+ // set up the class that will be used to convert each array element
+ $classFactory = self::buildClassName($attributeName) . '::factory';
+ if(is_array($data)):
+ // create an object from the data in each element
+ $objectArray = array_map($classFactory, $data);
+ else:
+ return array($data);
+ endif;
+
+ unset($attribArray[$attributeName]);
+ return $objectArray;
+ }
+ /**
+ * throws an exception based on the type of error
+ * @param string $statusCode HTTP status code to throw exception from
+ * @throws Braintree_Exception multiple types depending on the error
+ *
+ */
+ public static function throwStatusCodeException($statusCode, $message=null)
+ {
+ switch($statusCode) {
+ case 401:
+ throw new Braintree_Exception_Authentication();
+ break;
+ case 403:
+ throw new Braintree_Exception_Authorization($message);
+ break;
+ case 404:
+ throw new Braintree_Exception_NotFound();
+ break;
+ case 426:
+ throw new Braintree_Exception_UpgradeRequired();
+ break;
+ case 500:
+ throw new Braintree_Exception_ServerError();
+ break;
+ case 503:
+ throw new Braintree_Exception_DownForMaintenance();
+ break;
+ default:
+ throw new Braintree_Exception_Unexpected('Unexpected HTTP_RESPONSE #'.$statusCode);
+ break;
+ }
+ }
+
+ /**
+ *
+ * @param string $className
+ * @param object $resultObj
+ * @return object returns the passed object if successful
+ * @throws Braintree_Exception_ValidationsFailed
+ */
+ public static function returnObjectOrThrowException($className, $resultObj)
+ {
+ $resultObjName = Braintree_Util::cleanClassName($className);
+ if ($resultObj->success) {
+ return $resultObj->$resultObjName;
+ } else {
+ throw new Braintree_Exception_ValidationsFailed();
+ }
+ }
+
+ /**
+ * removes the Braintree_ header from a classname
+ *
+ * @param string $name Braintree_ClassName
+ * @return camelCased classname minus Braintree_ header
+ */
+ public static function cleanClassName($name)
+ {
+ $classNamesToResponseKeys = array(
+ 'CreditCard' => 'creditCard',
+ 'CreditCardGateway' => 'creditCard',
+ 'Customer' => 'customer',
+ 'CustomerGateway' => 'customer',
+ 'Subscription' => 'subscription',
+ 'SubscriptionGateway' => 'subscription',
+ 'Transaction' => 'transaction',
+ 'TransactionGateway' => 'transaction',
+ 'CreditCardVerification' => 'verification',
+ 'CreditCardVerificationGateway' => 'verification',
+ 'AddOn' => 'addOn',
+ 'AddOnGateway' => 'addOn',
+ 'Discount' => 'discount',
+ 'DiscountGateway' => 'discount',
+ 'Plan' => 'plan',
+ 'PlanGateway' => 'plan',
+ 'Address' => 'address',
+ 'AddressGateway' => 'address',
+ 'SettlementBatchSummary' => 'settlementBatchSummary',
+ 'SettlementBatchSummaryGateway' => 'settlementBatchSummary',
+ 'Merchant' => 'merchant',
+ 'MerchantGateway' => 'merchant',
+ 'MerchantAccount' => 'merchantAccount',
+ 'MerchantAccountGateway' => 'merchantAccount',
+ 'OAuthCredentials' => 'credentials',
+ 'PayPalAccount' => 'paypalAccount',
+ 'PayPalAccountGateway' => 'paypalAccount'
+ );
+
+ $name = str_replace('Braintree_', '', $name);
+ return $classNamesToResponseKeys[$name];
+ }
+
+ /**
+ *
+ * @param string $name className
+ * @return string Braintree_ClassName
+ */
+ public static function buildClassName($name)
+ {
+ $responseKeysToClassNames = array(
+ 'creditCard' => 'CreditCard',
+ 'customer' => 'Customer',
+ 'subscription' => 'Subscription',
+ 'transaction' => 'Transaction',
+ 'verification' => 'CreditCardVerification',
+ 'addOn' => 'AddOn',
+ 'discount' => 'Discount',
+ 'plan' => 'Plan',
+ 'address' => 'Address',
+ 'settlementBatchSummary' => 'SettlementBatchSummary',
+ 'merchantAccount' => 'MerchantAccount'
+ );
+
+ return 'Braintree_' . $responseKeysToClassNames[$name];
+ }
+
+ /**
+ * convert alpha-beta-gamma to alphaBetaGamma
+ *
+ * @access public
+ * @param string $string
+ * @return string modified string
+ */
+ public static function delimiterToCamelCase($string, $delimiter = '[\-\_]')
+ {
+ // php doesn't garbage collect functions created by create_function()
+ // so use a static variable to avoid adding a new function to memory
+ // every time this function is called.
+ static $callback = null;
+ if ($callback === null) {
+ $callback = create_function('$matches', 'return strtoupper($matches[1]);');
+ }
+
+ return preg_replace_callback('/' . $delimiter . '(\w)/', $callback, $string);
+ }
+
+ /**
+ * convert alpha-beta-gamma to alpha_beta_gamma
+ *
+ * @access public
+ * @param string $string
+ * @return string modified string
+ */
+ public static function delimiterToUnderscore($string)
+ {
+ return preg_replace('/-/', '_', $string);
+ }
+
+
+ /**
+ * find capitals and convert to delimiter + lowercase
+ *
+ * @access public
+ * @param var $string
+ * @return var modified string
+ */
+ public static function camelCaseToDelimiter($string, $delimiter = '-')
+ {
+ // php doesn't garbage collect functions created by create_function()
+ // so use a static variable to avoid adding a new function to memory
+ // every time this function is called.
+ static $callbacks = array();
+ if (!isset($callbacks[$delimiter])) {
+ $callbacks[$delimiter] = create_function('$matches', "return '$delimiter' . strtolower(\$matches[1]);");
+ }
+
+ return preg_replace_callback('/([A-Z])/', $callbacks[$delimiter], $string);
+ }
+
+ public static function delimiterToCamelCaseArray($array, $delimiter = '[\-\_]')
+ {
+ $converted = array();
+ foreach ($array as $key => $value) {
+ if (is_string($key)) {
+ $key = self::delimiterToCamelCase($key, $delimiter);
+ }
+
+ if (is_array($value)) {
+ // Make an exception for custom fields, which must be underscore (can't be
+ // camelCase).
+ if ($key === 'customFields') {
+ $value = self::delimiterToUnderscoreArray($value);
+ } else {
+ $value = self::delimiterToCamelCaseArray($value, $delimiter);
+ }
+ }
+ $converted[$key] = $value;
+ }
+ return $converted;
+ }
+
+ public static function camelCaseToDelimiterArray($array, $delimiter = '-')
+ {
+ $converted = array();
+ foreach ($array as $key => $value) {
+ if (is_string($key)) {
+ $key = self::camelCaseToDelimiter($key, $delimiter);
+ }
+ if (is_array($value)) {
+ $value = self::camelCaseToDelimiterArray($value, $delimiter);
+ }
+ $converted[$key] = $value;
+ }
+ return $converted;
+ }
+
+ public static function delimiterToUnderscoreArray($array)
+ {
+ $converted = array();
+ foreach ($array as $key => $value) {
+ $key = self::delimiterToUnderscore($key);
+ $converted[$key] = $value;
+ }
+ return $converted;
+ }
+
+ /**
+ *
+ * @param array $array associative array to implode
+ * @param string $separator (optional, defaults to =)
+ * @param string $glue (optional, defaults to ', ')
+ */
+ public static function implodeAssociativeArray($array, $separator = '=', $glue = ', ')
+ {
+ // build a new array with joined keys and values
+ $tmpArray = null;
+ foreach ($array AS $key => $value) {
+ if ($value instanceof DateTime) {
+ $value = $value->format('r');
+ }
+ $tmpArray[] = $key . $separator . $value;
+ }
+ // implode and return the new array
+ return (is_array($tmpArray)) ? implode($glue, $tmpArray) : false;
+ }
+
+ public static function attributesToString($attributes) {
+ $printableAttribs = array();
+ foreach ($attributes AS $key => $value) {
+ if (is_array($value)) {
+ $pAttrib = Braintree_Util::attributesToString($value);
+ } else if ($value instanceof DateTime) {
+ $pAttrib = $value->format(DateTime::RFC850);
+ } else {
+ $pAttrib = $value;
+ }
+ $printableAttribs[$key] = sprintf('%s', $pAttrib);
+ }
+ return Braintree_Util::implodeAssociativeArray($printableAttribs);
+ }
+
+ /**
+ * verify user request structure
+ *
+ * compares the expected signature of a gateway request
+ * against the actual structure sent by the user
+ *
+ * @param array $signature
+ * @param array $attributes
+ */
+ public static function verifyKeys($signature, $attributes)
+ {
+ $validKeys = self::_flattenArray($signature);
+ $userKeys = self::_flattenUserKeys($attributes);
+ $invalidKeys = array_diff($userKeys, $validKeys);
+ $invalidKeys = self::_removeWildcardKeys($validKeys, $invalidKeys);
+
+ if(!empty($invalidKeys)) {
+ asort($invalidKeys);
+ $sortedList = join(', ', $invalidKeys);
+ throw new InvalidArgumentException('invalid keys: '. $sortedList);
+ }
+ }
+ /**
+ * flattens a numerically indexed nested array to a single level
+ * @param array $keys
+ * @param string $namespace
+ * @return array
+ */
+ private static function _flattenArray($keys, $namespace = null)
+ {
+ $flattenedArray = array();
+ foreach($keys AS $key) {
+ if(is_array($key)) {
+ $theKeys = array_keys($key);
+ $theValues = array_values($key);
+ $scope = $theKeys[0];
+ $fullKey = empty($namespace) ? $scope : $namespace . '[' . $scope . ']';
+ $flattenedArray = array_merge($flattenedArray, self::_flattenArray($theValues[0], $fullKey));
+ } else {
+ $fullKey = empty($namespace) ? $key : $namespace . '[' . $key . ']';
+ $flattenedArray[] = $fullKey;
+ }
+ }
+ sort($flattenedArray);
+ return $flattenedArray;
+ }
+
+ private static function _flattenUserKeys($keys, $namespace = null)
+ {
+ $flattenedArray = array();
+
+ foreach($keys AS $key => $value) {
+ $fullKey = empty($namespace) ? $key : $namespace;
+ if (!is_numeric($key) && $namespace != null) {
+ $fullKey .= '[' . $key . ']';
+ }
+ if (is_numeric($key) && is_string($value)) {
+ $fullKey .= '[' . $value . ']';
+ }
+ if(is_array($value)) {
+ $more = self::_flattenUserKeys($value, $fullKey);
+ $flattenedArray = array_merge($flattenedArray, $more);
+ } else {
+ $flattenedArray[] = $fullKey;
+ }
+ }
+ sort($flattenedArray);
+ return $flattenedArray;
+ }
+
+ /**
+ * removes wildcard entries from the invalid keys array
+ * @param array $validKeys
+ * @param <array $invalidKeys
+ * @return array
+ */
+ private static function _removeWildcardKeys($validKeys, $invalidKeys)
+ {
+ foreach($validKeys AS $key) {
+ if (stristr($key, '[_anyKey_]')) {
+ $wildcardKey = str_replace('[_anyKey_]', '', $key);
+ foreach ($invalidKeys AS $index => $invalidKey) {
+ if (stristr($invalidKey, $wildcardKey)) {
+ unset($invalidKeys[$index]);
+ }
+ }
+ }
+ }
+ return $invalidKeys;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Version.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Version.php
new file mode 100644
index 0000000..da95e13
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Version.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Braintree Library Version
+ * stores version information about the Braintree library
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+final class Braintree_Version
+{
+ /**
+ * class constants
+ */
+ const MAJOR = 3;
+ const MINOR = 2;
+ const TINY = 0;
+
+ /**
+ * @ignore
+ * @access protected
+ */
+ protected function __construct()
+ {
+ }
+
+ /**
+ *
+ * @return string the current library version
+ */
+ public static function get()
+ {
+ return self::MAJOR.'.'.self::MINOR.'.'.self::TINY;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookNotification.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookNotification.php
new file mode 100644
index 0000000..9400d8f
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookNotification.php
@@ -0,0 +1,126 @@
+<?php
+class Braintree_WebhookNotification extends Braintree_Base
+{
+ const SUBSCRIPTION_CANCELED = 'subscription_canceled';
+ const SUBSCRIPTION_CHARGED_SUCCESSFULLY = 'subscription_charged_successfully';
+ const SUBSCRIPTION_CHARGED_UNSUCCESSFULLY = 'subscription_charged_unsuccessfully';
+ const SUBSCRIPTION_EXPIRED = 'subscription_expired';
+ const SUBSCRIPTION_TRIAL_ENDED = 'subscription_trial_ended';
+ const SUBSCRIPTION_WENT_ACTIVE = 'subscription_went_active';
+ const SUBSCRIPTION_WENT_PAST_DUE = 'subscription_went_past_due';
+ const SUB_MERCHANT_ACCOUNT_APPROVED = 'sub_merchant_account_approved';
+ const SUB_MERCHANT_ACCOUNT_DECLINED = 'sub_merchant_account_declined';
+ const TRANSACTION_DISBURSED = 'transaction_disbursed';
+ const DISBURSEMENT_EXCEPTION = 'disbursement_exception';
+ const DISBURSEMENT = 'disbursement';
+ const DISPUTE_OPENED = 'dispute_opened';
+ const DISPUTE_LOST = 'dispute_lost';
+ const DISPUTE_WON = 'dispute_won';
+ const PARTNER_MERCHANT_CONNECTED = 'partner_merchant_connected';
+ const PARTNER_MERCHANT_DISCONNECTED = 'partner_merchant_disconnected';
+ const PARTNER_MERCHANT_DECLINED = 'partner_merchant_declined';
+
+ public static function parse($signature, $payload)
+ {
+ if (preg_match("/[^A-Za-z0-9+=\/\n]/", $payload) === 1) {
+ throw new Braintree_Exception_InvalidSignature("payload contains illegal characters");
+ }
+
+ Braintree_Configuration::assertGlobalHasAccessTokenOrKeys();
+ self::_validateSignature($signature, $payload);
+
+ $xml = base64_decode($payload);
+ $attributes = Braintree_Xml::buildArrayFromXml($xml);
+ return self::factory($attributes['notification']);
+ }
+
+ public static function verify($challenge)
+ {
+ if (!preg_match('/^[a-f0-9]{20,32}$/', $challenge)) {
+ throw new Braintree_Exception_InvalidChallenge("challenge contains non-hex characters");
+ }
+ Braintree_Configuration::assertGlobalHasAccessTokenOrKeys();
+ $publicKey = Braintree_Configuration::publicKey();
+ $digest = Braintree_Digest::hexDigestSha1(Braintree_Configuration::privateKey(), $challenge);
+ return "{$publicKey}|{$digest}";
+ }
+
+ public static function factory($attributes)
+ {
+ $instance = new self();
+ $instance->_initialize($attributes);
+ return $instance;
+ }
+
+ private static function _matchingSignature($signaturePairs)
+ {
+ foreach ($signaturePairs as $pair)
+ {
+ $components = preg_split("/\|/", $pair);
+ if ($components[0] == Braintree_Configuration::publicKey()) {
+ return $components[1];
+ }
+ }
+
+ return null;
+ }
+
+ private static function _payloadMatches($signature, $payload)
+ {
+ $payloadSignature = Braintree_Digest::hexDigestSha1(Braintree_Configuration::privateKey(), $payload);
+ return Braintree_Digest::secureCompare($signature, $payloadSignature);
+ }
+
+ private static function _validateSignature($signatureString, $payload)
+ {
+ $signaturePairs = preg_split("/&/", $signatureString);
+ $signature = self::_matchingSignature($signaturePairs);
+ if (!$signature) {
+ throw new Braintree_Exception_InvalidSignature("no matching public key");
+ }
+
+ if (!(self::_payloadMatches($signature, $payload) || self::_payloadMatches($signature, $payload . "\n"))) {
+ throw new Braintree_Exception_InvalidSignature("signature does not match payload - one has been modified");
+ }
+ }
+
+ protected function _initialize($attributes)
+ {
+ $this->_attributes = $attributes;
+
+ if (isset($attributes['subject']['apiErrorResponse'])) {
+ $wrapperNode = $attributes['subject']['apiErrorResponse'];
+ } else {
+ $wrapperNode = $attributes['subject'];
+ }
+
+ if (isset($wrapperNode['subscription'])) {
+ $this->_set('subscription', Braintree_Subscription::factory($attributes['subject']['subscription']));
+ }
+
+ if (isset($wrapperNode['merchantAccount'])) {
+ $this->_set('merchantAccount', Braintree_MerchantAccount::factory($wrapperNode['merchantAccount']));
+ }
+
+ if (isset($wrapperNode['transaction'])) {
+ $this->_set('transaction', Braintree_Transaction::factory($wrapperNode['transaction']));
+ }
+
+ if (isset($wrapperNode['disbursement'])) {
+ $this->_set('disbursement', Braintree_Disbursement::factory($wrapperNode['disbursement']));
+ }
+
+ if (isset($wrapperNode['partnerMerchant'])) {
+ $this->_set('partnerMerchant', Braintree_PartnerMerchant::factory($wrapperNode['partnerMerchant']));
+ }
+
+ if (isset($wrapperNode['dispute'])) {
+ $this->_set('dispute', Braintree_Dispute::factory($wrapperNode['dispute']));
+ }
+
+ if (isset($wrapperNode['errors'])) {
+ $this->_set('errors', new Braintree_Error_ValidationErrorCollection($wrapperNode['errors']));
+ $this->_set('message', $wrapperNode['message']);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookTesting.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookTesting.php
new file mode 100644
index 0000000..41d129c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/WebhookTesting.php
@@ -0,0 +1,283 @@
+<?php
+class Braintree_WebhookTesting
+{
+ public static function sampleNotification($kind, $id)
+ {
+ $payload = base64_encode(self::_sampleXml($kind, $id)) . "\n";
+ $signature = Braintree_Configuration::publicKey() . "|" . Braintree_Digest::hexDigestSha1(Braintree_Configuration::privateKey(), $payload);
+
+ return array(
+ 'bt_signature' => $signature,
+ 'bt_payload' => $payload
+ );
+ }
+
+ private static function _sampleXml($kind, $id)
+ {
+ switch ($kind) {
+ case Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED:
+ $subjectXml = self::_merchantAccountApprovedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED:
+ $subjectXml = self::_merchantAccountDeclinedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::TRANSACTION_DISBURSED:
+ $subjectXml = self::_transactionDisbursedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::DISBURSEMENT_EXCEPTION:
+ $subjectXml = self::_disbursementExceptionSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::DISBURSEMENT:
+ $subjectXml = self::_disbursementSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::PARTNER_MERCHANT_CONNECTED:
+ $subjectXml = self::_partnerMerchantConnectedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::PARTNER_MERCHANT_DISCONNECTED:
+ $subjectXml = self::_partnerMerchantDisconnectedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::PARTNER_MERCHANT_DECLINED:
+ $subjectXml = self::_partnerMerchantDeclinedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::DISPUTE_OPENED:
+ $subjectXml = self::_disputeOpenedSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::DISPUTE_LOST:
+ $subjectXml = self::_disputeLostSampleXml($id);
+ break;
+ case Braintree_WebhookNotification::DISPUTE_WON:
+ $subjectXml = self::_disputeWonSampleXml($id);
+ break;
+ default:
+ $subjectXml = self::_subscriptionSampleXml($id);
+ break;
+ }
+ $timestamp = self::_timestamp();
+ return "
+ <notification>
+ <timestamp type=\"datetime\">{$timestamp}</timestamp>
+ <kind>{$kind}</kind>
+ <subject>{$subjectXml}</subject>
+ </notification>
+ ";
+ }
+
+ private static function _merchantAccountApprovedSampleXml($id)
+ {
+ return "
+ <merchant_account>
+ <id>{$id}</id>
+ <master_merchant_account>
+ <id>master_ma_for_{$id}</id>
+ <status>active</status>
+ </master_merchant_account>
+ <status>active</status>
+ </merchant_account>
+ ";
+ }
+
+ private static function _merchantAccountDeclinedSampleXml($id)
+ {
+ return "
+ <api-error-response>
+ <message>Credit score is too low</message>
+ <errors>
+ <errors type=\"array\"/>
+ <merchant-account>
+ <errors type=\"array\">
+ <error>
+ <code>82621</code>
+ <message>Credit score is too low</message>
+ <attribute type=\"symbol\">base</attribute>
+ </error>
+ </errors>
+ </merchant-account>
+ </errors>
+ <merchant-account>
+ <id>{$id}</id>
+ <status>suspended</status>
+ <master-merchant-account>
+ <id>master_ma_for_{$id}</id>
+ <status>suspended</status>
+ </master-merchant-account>
+ </merchant-account>
+ </api-error-response>
+ ";
+ }
+
+ private static function _transactionDisbursedSampleXml($id)
+ {
+ return "
+ <transaction>
+ <id>${id}</id>
+ <amount>100</amount>
+ <disbursement-details>
+ <disbursement-date type=\"date\">2013-07-09</disbursement-date>
+ </disbursement-details>
+ </transaction>
+ ";
+ }
+
+ private static function _disbursementExceptionSampleXml($id)
+ {
+ return "
+ <disbursement>
+ <id>${id}</id>
+ <transaction-ids type=\"array\">
+ <item>asdfg</item>
+ <item>qwert</item>
+ </transaction-ids>
+ <success type=\"boolean\">false</success>
+ <retry type=\"boolean\">false</retry>
+ <merchant-account>
+ <id>merchant_account_token</id>
+ <currency-iso-code>USD</currency-iso-code>
+ <sub-merchant-account type=\"boolean\">false</sub-merchant-account>
+ <status>active</status>
+ </merchant-account>
+ <amount>100.00</amount>
+ <disbursement-date type=\"date\">2014-02-10</disbursement-date>
+ <exception-message>bank_rejected</exception-message>
+ <follow-up-action>update_funding_information</follow-up-action>
+ </disbursement>
+ ";
+ }
+
+ private static function _disbursementSampleXml($id)
+ {
+ return "
+ <disbursement>
+ <id>${id}</id>
+ <transaction-ids type=\"array\">
+ <item>asdfg</item>
+ <item>qwert</item>
+ </transaction-ids>
+ <success type=\"boolean\">true</success>
+ <retry type=\"boolean\">false</retry>
+ <merchant-account>
+ <id>merchant_account_token</id>
+ <currency-iso-code>USD</currency-iso-code>
+ <sub-merchant-account type=\"boolean\">false</sub-merchant-account>
+ <status>active</status>
+ </merchant-account>
+ <amount>100.00</amount>
+ <disbursement-date type=\"date\">2014-02-10</disbursement-date>
+ <exception-message nil=\"true\"/>
+ <follow-up-action nil=\"true\"/>
+ </disbursement>
+ ";
+ }
+
+ private static function _disputeOpenedSampleXml($id)
+ {
+ return "
+ <dispute>
+ <amount>250.00</amount>
+ <currency-iso-code>USD</currency-iso-code>
+ <received-date type=\"date\">2014-03-01</received-date>
+ <reply-by-date type=\"date\">2014-03-21</reply-by-date>
+ <status>open</status>
+ <reason>fraud</reason>
+ <id>${id}</id>
+ <transaction>
+ <id>${id}</id>
+ <amount>250.00</amount>
+ </transaction>
+ </dispute>
+ ";
+ }
+
+ private static function _disputeLostSampleXml($id)
+ {
+ return "
+ <dispute>
+ <amount>250.00</amount>
+ <currency-iso-code>USD</currency-iso-code>
+ <received-date type=\"date\">2014-03-01</received-date>
+ <reply-by-date type=\"date\">2014-03-21</reply-by-date>
+ <status>lost</status>
+ <reason>fraud</reason>
+ <id>${id}</id>
+ <transaction>
+ <id>${id}</id>
+ <amount>250.00</amount>
+ </transaction>
+ </dispute>
+ ";
+ }
+
+ private static function _disputeWonSampleXml($id)
+ {
+ return "
+ <dispute>
+ <amount>250.00</amount>
+ <currency-iso-code>USD</currency-iso-code>
+ <received-date type=\"date\">2014-03-01</received-date>
+ <reply-by-date type=\"date\">2014-03-21</reply-by-date>
+ <status>won</status>
+ <reason>fraud</reason>
+ <id>${id}</id>
+ <transaction>
+ <id>${id}</id>
+ <amount>250.00</amount>
+ </transaction>
+ </dispute>
+ ";
+ }
+
+ private static function _subscriptionSampleXml($id)
+ {
+ return "
+ <subscription>
+ <id>{$id}</id>
+ <transactions type=\"array\">
+ </transactions>
+ <add_ons type=\"array\">
+ </add_ons>
+ <discounts type=\"array\">
+ </discounts>
+ </subscription>
+ ";
+ }
+
+ private static function _partnerMerchantConnectedSampleXml($id)
+ {
+ return "
+ <partner-merchant>
+ <merchant-public-id>public_id</merchant-public-id>
+ <public-key>public_key</public-key>
+ <private-key>private_key</private-key>
+ <partner-merchant-id>abc123</partner-merchant-id>
+ <client-side-encryption-key>cse_key</client-side-encryption-key>
+ </partner-merchant>
+ ";
+ }
+
+ private static function _partnerMerchantDisconnectedSampleXml($id)
+ {
+ return "
+ <partner-merchant>
+ <partner-merchant-id>abc123</partner-merchant-id>
+ </partner-merchant>
+ ";
+ }
+
+ private static function _partnerMerchantDeclinedSampleXml($id)
+ {
+ return "
+ <partner-merchant>
+ <partner-merchant-id>abc123</partner-merchant-id>
+ </partner-merchant>
+ ";
+ }
+
+ private static function _timestamp()
+ {
+ $originalZone = date_default_timezone_get();
+ date_default_timezone_set('UTC');
+ $timestamp = strftime('%Y-%m-%dT%TZ');
+ date_default_timezone_set($originalZone);
+
+ return $timestamp;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml.php
new file mode 100644
index 0000000..da62741
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Braintree Xml parser and generator
+ * PHP version 5
+ * superclass for Braintree XML parsing and generation
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+final class Braintree_Xml
+{
+ /**
+ * @ignore
+ */
+ protected function __construct()
+ {
+
+ }
+
+ /**
+ *
+ * @param string $xml
+ * @return array
+ */
+ public static function buildArrayFromXml($xml)
+ {
+ return Braintree_Xml_Parser::arrayFromXml($xml);
+ }
+
+ /**
+ *
+ * @param array $array
+ * @return string
+ */
+ public static function buildXmlFromArray($array)
+ {
+ return Braintree_Xml_Generator::arrayToXml($array);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Generator.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Generator.php
new file mode 100644
index 0000000..4e99443
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Generator.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * PHP version 5
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+
+/**
+ * Generates XML output from arrays using PHP's
+ * built-in XMLWriter
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Xml_Generator
+{
+ /**
+ * arrays passed to this method should have a single root element
+ * with an array as its value
+ * @param array $aData the array of data
+ * @return var XML string
+ */
+ public static function arrayToXml($aData)
+ {
+ $aData = Braintree_Util::camelCaseToDelimiterArray($aData, '-');
+ // set up the XMLWriter
+ $writer = new XMLWriter();
+ $writer->openMemory();
+
+ $writer->setIndent(true);
+ $writer->setIndentString(' ');
+ $writer->startDocument('1.0', 'UTF-8');
+
+ // get the root element name
+ $aKeys = array_keys($aData);
+ $rootElementName = $aKeys[0];
+ // open the root element
+ $writer->startElement($rootElementName);
+ // create the body
+ self::_createElementsFromArray($writer, $aData[$rootElementName], $rootElementName);
+
+ // close the root element and document
+ $writer->endElement();
+ $writer->endDocument();
+
+ // send the output as string
+ return $writer->outputMemory();
+ }
+
+ /**
+ * Construct XML elements with attributes from an associative array.
+ *
+ * @access protected
+ * @static
+ * @param object $writer XMLWriter object
+ * @param array $aData contains attributes and values
+ * @return none
+ */
+ private static function _createElementsFromArray(&$writer, $aData)
+ {
+ if (!is_array($aData)) {
+ if (is_bool($aData)) {
+ $writer->text($aData ? 'true' : 'false');
+ } else {
+ $writer->text($aData);
+ }
+ return;
+ }
+ foreach ($aData AS $elementName => $element) {
+ // handle child elements
+ $writer->startElement($elementName);
+ if (is_array($element)) {
+ if (array_key_exists(0, $element) || empty($element)) {
+ $writer->writeAttribute('type', 'array');
+ foreach ($element AS $ignored => $itemInArray) {
+ $writer->startElement('item');
+ self::_createElementsFromArray($writer, $itemInArray);
+ $writer->endElement();
+ }
+ }
+ else {
+ self::_createElementsFromArray($writer, $element);
+ }
+ } else {
+ // generate attributes as needed
+ $attribute = self::_generateXmlAttribute($element);
+ if (is_array($attribute)) {
+ $writer->writeAttribute($attribute[0], $attribute[1]);
+ $element = $attribute[2];
+ }
+ $writer->text($element);
+ }
+ $writer->endElement();
+ }
+ }
+
+ /**
+ * convert passed data into an array of attributeType, attributeName, and value
+ * dates sent as DateTime objects will be converted to strings
+ * @access protected
+ * @param mixed $value
+ * @return array attributes and element value
+ */
+ private static function _generateXmlAttribute($value)
+ {
+ if ($value instanceof DateTime) {
+ return array('type', 'datetime', self::_dateTimeToXmlTimestamp($value));
+ }
+ if (is_int($value)) {
+ return array('type', 'integer', $value);
+ }
+ if (is_bool($value)) {
+ return array('type', 'boolean', ($value ? 'true' : 'false'));
+ }
+ if ($value === NULL) {
+ return array('nil', 'true', $value);
+ }
+ }
+ /**
+ * converts datetime back to xml schema format
+ * @access protected
+ * @param object $dateTime
+ * @return var XML schema formatted timestamp
+ */
+ private static function _dateTimeToXmlTimestamp($dateTime)
+ {
+ $dateTime->setTimeZone(new DateTimeZone('UTC'));
+ return ($dateTime->format('Y-m-d\TH:i:s') . 'Z');
+ }
+
+ private static function _castDateTime($string)
+ {
+ try {
+ if (empty($string)) {
+ return false;
+ }
+ $dateTime = new DateTime($string);
+ return self::_dateTimeToXmlTimestamp($dateTime);
+ } catch (Exception $e) {
+ // not a datetime
+ return false;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Parser.php b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Parser.php
new file mode 100644
index 0000000..85594a7
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/Braintree/Xml/Parser.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * Braintree XML Parser
+ *
+ * @copyright 2014 Braintree, a division of PayPal, Inc.
+ */
+class Braintree_Xml_Parser
+{
+ /**
+ * Converts an XML string into a multidimensional array
+ *
+ * @param string $xml
+ * @return array
+ */
+ public static function arrayFromXml($xml)
+ {
+ $document = new DOMDocument('1.0', 'UTF-8');
+ $document->loadXML($xml);
+
+ $root = $document->documentElement->nodeName;
+
+ return Braintree_Util::delimiterToCamelCaseArray(array(
+ $root => self::_nodeToValue($document->childNodes->item(0)),
+ ));
+ }
+
+ /**
+ * Converts a node to an array of values or nodes
+ *
+ * @param DOMNode @node
+ * @return mixed
+ */
+ private static function _nodeToArray($node)
+ {
+ $type = null;
+ if ($node instanceof DOMElement) {
+ $type = $node->getAttribute('type');
+ }
+
+ switch($type) {
+ case 'array':
+ $array = array();
+ foreach ($node->childNodes as $child) {
+ $value = self::_nodeToValue($child);
+ if ($value !== null) {
+ $array[] = $value;
+ }
+ }
+ return $array;
+ case 'collection':
+ $collection = array();
+ foreach ($node->childNodes as $child) {
+ $value = self::_nodetoValue($child);
+ if ($value !== null) {
+ if (!isset($collection[$child->nodeName])) {
+ $collection[$child->nodeName] = array();
+ }
+ $collection[$child->nodeName][] = self::_nodeToValue($child);
+ }
+ }
+ return $collection;
+ default:
+ $values = array();
+ if ($node->childNodes->length === 1 && $node->childNodes->item(0) instanceof DOMText) {
+ return $node->childNodes->item(0)->nodeValue;
+ } else {
+ foreach ($node->childNodes as $child) {
+ if (!$child instanceof DOMText) {
+ $values[$child->nodeName] = self::_nodeToValue($child);
+ }
+ }
+ return $values;
+ }
+ }
+ }
+
+ /**
+ * Converts a node to a PHP value
+ *
+ * @param DOMNode $node
+ * @return mixed
+ */
+ private static function _nodeToValue($node)
+ {
+ $type = null;
+ if ($node instanceof DOMElement) {
+ $type = $node->getAttribute('type');
+ }
+
+ switch($type) {
+ case 'datetime':
+ return self::_timestampToUTC((string) $node->nodeValue);
+ case 'date':
+ return new DateTime((string) $node->nodeValue);
+ case 'integer':
+ return (int) $node->nodeValue;
+ case 'boolean':
+ $value = (string) $node->nodeValue;
+ if(is_numeric($value)) {
+ return (bool) $value;
+ } else {
+ return ($value !== "true") ? false : true;
+ }
+ case 'array':
+ case 'collection':
+ return self::_nodeToArray($node);
+ default:
+ if ($node->hasChildNodes()) {
+ return self::_nodeToArray($node);
+ } elseif (trim($node->nodeValue) === '') {
+ return null;
+ } else {
+ return $node->nodeValue;
+ }
+ }
+ }
+
+
+ /**
+ * Converts XML timestamps into DateTime instances
+ *
+ * @param string $timestamp
+ * @return DateTime
+ */
+ private static function _timestampToUTC($timestamp)
+ {
+ $tz = new DateTimeZone('UTC');
+ $dateTime = new DateTime($timestamp, $tz);
+ $dateTime->setTimezone($tz);
+ return $dateTime;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/lib/ssl/api_braintreegateway_com.ca.crt b/public/system/storage/vendor/braintree/braintree_php/lib/ssl/api_braintreegateway_com.ca.crt
new file mode 100644
index 0000000..e142318
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/lib/ssl/api_braintreegateway_com.ca.crt
@@ -0,0 +1,351 @@
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
+c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
+MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
+emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
+DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
+FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
+UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
+YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
+MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
+pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
+13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
+AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
+U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
+F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
+oJ2daZH9
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
+N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
+KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
+kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
+CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
+Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
+imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
+2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
+DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
+F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
+TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
+SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
+biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
+GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
+fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
+aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
+aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
+4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
+FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
+2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
+2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
+VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
+c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
+WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
+FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
+XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
+se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
+KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
+IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
+y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
+hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
+QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
+Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
+HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
+KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
+L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
+Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
+ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
+T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
+GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
+1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
+OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
+6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
+QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
+IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
+VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
+cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
+QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
+F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
+c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
+mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
+VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
+teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
+f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
+Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
+nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
+MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
+9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
+IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
+ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
+uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
+Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
+QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
+koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
+ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
+DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
+bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
+IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
+R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
+PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
+Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
+TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
+5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
+S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
+2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
+EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
+EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
+/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
+A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
+abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
+I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
+4iIprn2DQKi6bA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
+MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
+YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
+dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
+BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
+papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
+DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
+KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
+XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
+qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
+BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
+NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
+LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
+A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
+W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
+3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
+6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
+Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
+NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
+r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
+DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
+YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
+/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
+LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
+jVaMaA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
+MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
+YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
+dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
+BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
+papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
+DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
+KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
+XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
+NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
+dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
+WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
+v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
+UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
+IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
+W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
+-----END CERTIFICATE-----
diff --git a/public/system/storage/vendor/braintree/braintree_php/phpunit.xml.dist b/public/system/storage/vendor/braintree/braintree_php/phpunit.xml.dist
new file mode 100644
index 0000000..c1457f9
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/phpunit.xml.dist
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false">
+
+ <php>
+ <ini name="error_reporting" value="32767"/>
+ </php>
+
+ <testsuites>
+ <testsuite name="unit">
+ <directory>./tests/unit</directory>
+ </testsuite>
+ <testsuite name="integration">
+ <directory>./tests/integration</directory>
+ </testsuite>
+ </testsuites>
+</phpunit>
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardDefaults.php b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardDefaults.php
new file mode 100644
index 0000000..d5ed5ab
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardDefaults.php
@@ -0,0 +1,7 @@
+<?php
+
+class CreditCardDefaults
+{
+ const ISSUING_BANK = "NETWORK ONLY";
+ const COUNTRY_OF_ISSUANCE = "USA";
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardNumbers/CardTypeIndicators.php b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardNumbers/CardTypeIndicators.php
new file mode 100644
index 0000000..cf5aef9
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/CreditCardNumbers/CardTypeIndicators.php
@@ -0,0 +1,13 @@
+<?php
+class Braintree_CreditCardNumbers_CardTypeIndicators {
+ const PREPAID = "4111111111111210";
+ const COMMERCIAL = "4111111111131010";
+ const PAYROLL = "4111111114101010";
+ const HEALTHCARE = "4111111510101010";
+ const DURBIN_REGULATED = "4111161010101010";
+ const DEBIT = "4117101010101010";
+ const UNKNOWN = "4111111111112101";
+ const NO = "4111111111310101";
+ const ISSUING_BANK = "4111111141010101";
+ const COUNTRY_OF_ISSUANCE = "4111111111121102";
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/OAuthTestHelper.php b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/OAuthTestHelper.php
new file mode 100644
index 0000000..35dd2d4
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/OAuthTestHelper.php
@@ -0,0 +1,32 @@
+<?php
+
+class Braintree_OAuthTestHelper
+{
+ public static function createGrant($gateway, $params)
+ {
+ $http = new Braintree_Http($gateway->config);
+ $http->useClientCredentials();
+ $response = $http->post('/oauth_testing/grants', array('grant' => $params));
+ return $response['grant']['code'];
+ }
+
+ public static function createCredentials($params)
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => $params['clientId'],
+ 'clientSecret' => $params['clientSecret']
+ ));
+
+ $code = Braintree_OAuthTestHelper::createGrant($gateway, array(
+ 'merchant_public_id' => $params['merchantId'],
+ 'scope' => 'read_write'
+ ));
+
+ $credentials = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => $code,
+ 'scope' => 'read_write',
+ ));
+
+ return $credentials;
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/fixtures/composer_implementation.php b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/fixtures/composer_implementation.php
new file mode 100644
index 0000000..c92ebb5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/Braintree/fixtures/composer_implementation.php
@@ -0,0 +1,5 @@
+<?php
+
+require_once __DIR__ . '/../../../vendor/autoload.php';
+
+class_exists("Braintree_Modification");
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/SanityTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/SanityTest.php
new file mode 100644
index 0000000..0f3a28e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/SanityTest.php
@@ -0,0 +1,20 @@
+<?php
+
+class SanityTest extends PHPUnit_Framework_TestCase
+{
+ public function testLibraryWorksWithComposer()
+ {
+ if (version_compare(PHP_VERSION, "5.4.0", "<")) {
+ $this->markTestSkipped("Requires PHP >=5.4");
+ }
+
+ $returnValue = null;
+
+ $testFile = escapeshellarg(realpath(__DIR__ . '/Braintree/fixtures/composer_implementation.php'));
+ $command = sprintf('%s %s', PHP_BINARY, $testFile);
+
+ system($command, $returnValue);
+
+ $this->assertEquals(0, $returnValue);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/TestHelper.php b/public/system/storage/vendor/braintree/braintree_php/tests/TestHelper.php
new file mode 100644
index 0000000..3b66680
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/TestHelper.php
@@ -0,0 +1,161 @@
+<?php
+
+set_include_path(
+ get_include_path() . PATH_SEPARATOR .
+ realpath(dirname(__FILE__)) . '/../lib'
+);
+
+require_once "Braintree.php";
+require_once "Braintree/CreditCardNumbers/CardTypeIndicators.php";
+require_once "Braintree/CreditCardDefaults.php";
+require_once "Braintree/OAuthTestHelper.php";
+require_once "Braintree/PaymentInstrumentType.php";
+
+function integrationMerchantConfig()
+{
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+}
+
+function testMerchantConfig()
+{
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('test_merchant_id');
+ Braintree_Configuration::publicKey('test_public_key');
+ Braintree_Configuration::privateKey('test_private_key');
+}
+
+integrationMerchantConfig();
+
+date_default_timezone_set("UTC");
+
+class Braintree_TestHelper
+{
+ public static function defaultMerchantAccountId()
+ {
+ return 'sandbox_credit_card';
+ }
+
+ public static function nonDefaultMerchantAccountId()
+ {
+ return 'sandbox_credit_card_non_default';
+ }
+
+ public static function nonDefaultSubMerchantAccountId()
+ {
+ return 'sandbox_sub_merchant_account';
+ }
+
+ public static function threeDSecureMerchantAccountId()
+ {
+ return 'three_d_secure_merchant_account';
+ }
+
+ public static function createViaTr($regularParams, $trParams)
+ {
+ $trData = Braintree_TransparentRedirect::transactionData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+ return Braintree_TestHelper::submitTrRequest(
+ TransparentRedirect::url(),
+ $regularParams,
+ $trData
+ );
+ }
+
+ public static function submitTrRequest($url, $regularParams, $trData)
+ {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ // curl_setopt($curl, CURLOPT_VERBOSE, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query(array_merge($regularParams, array('tr_data' => $trData))));
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array(
+ 'Content-Type: application/x-www-form-urlencoded'
+ ));
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($curl);
+ curl_close($curl);
+ preg_match('/Location: .*\?(.*)/i', $response, $match);
+ return trim($match[1]);
+ }
+
+ public static function suppressDeprecationWarnings()
+ {
+ set_error_handler("Braintree_TestHelper::_errorHandler", E_USER_NOTICE);
+ }
+
+ static function _errorHandler($errno, $errstr, $errfile, $errline)
+ {
+ if (preg_match('/^DEPRECATED/', $errstr) == 0) {
+ trigger_error('Unknown error received: ' . $errstr, E_USER_ERROR);
+ }
+ }
+
+ public static function includes($collection, $targetItem)
+ {
+ foreach ($collection AS $item) {
+ if ($item->id == $targetItem->id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static function assertPrintable($object)
+ {
+ " " . $object;
+ }
+
+ public static function settle($transactionId)
+ {
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $transactionId . '/settle';
+ $http->put($path);
+ }
+
+ public static function settlementDecline($transactionId)
+ {
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $transactionId . '/settlement_decline';
+ $http->put($path);
+ }
+
+ public static function settlementPending($transactionId)
+ {
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $transactionId . '/settlement_pending';
+ $http->put($path);
+ }
+
+ public static function escrow($transactionId)
+ {
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $transactionId . '/escrow';
+ $http->put($path);
+ }
+
+ public static function create3DSVerification($merchantAccountId, $params)
+ {
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/three_d_secure/create_verification/' . $merchantAccountId;
+ $response = $http->post($path, array('threeDSecureVerification' => $params));
+ return $response['threeDSecureVerification']['threeDSecureToken'];
+ }
+
+ public static function nowInEastern()
+ {
+ $eastern = new DateTimeZone('America/New_York');
+ $now = new DateTime('now', $eastern);
+ return $now->format('Y-m-d');
+ }
+
+ public static function decodedClientToken($params=array()) {
+ $encodedClientToken = Braintree_ClientToken::generate($params);
+ return base64_decode($encodedClientToken);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/AddOnsTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/AddOnsTest.php
new file mode 100644
index 0000000..d4a3c6a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/AddOnsTest.php
@@ -0,0 +1,83 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_AddOnTest extends PHPUnit_Framework_TestCase
+{
+ function testAll_returnsAllAddOns()
+ {
+ $newId = strval(rand());
+
+ $addOnParams = array (
+ "amount" => "100.00",
+ "description" => "some description",
+ "id" => $newId,
+ "kind" => "add_on",
+ "name" => "php_add_on",
+ "neverExpires" => "false",
+ "numberOfBillingCycles" => "1"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/modifications/create_modification_for_tests";
+ $http->post($path, array("modification" => $addOnParams));
+
+ $addOns = Braintree_AddOn::all();
+
+ foreach ($addOns as $addOn)
+ {
+ if ($addOn->id == $newId)
+ {
+ $actualAddOn = $addOn;
+ }
+ }
+
+ $this->assertNotNull($actualAddOn);
+ $this->assertEquals($addOnParams["amount"], $actualAddOn->amount);
+ $this->assertEquals($addOnParams["description"], $actualAddOn->description);
+ $this->assertEquals($addOnParams["id"], $actualAddOn->id);
+ $this->assertEquals($addOnParams["kind"], $actualAddOn->kind);
+ $this->assertEquals($addOnParams["name"], $actualAddOn->name);
+ $this->assertFalse($actualAddOn->neverExpires);
+ $this->assertEquals($addOnParams["numberOfBillingCycles"], $actualAddOn->numberOfBillingCycles);
+ }
+
+ function testGatewayAll_returnsAllAddOns()
+ {
+ $newId = strval(rand());
+
+ $addOnParams = array (
+ "amount" => "100.00",
+ "description" => "some description",
+ "id" => $newId,
+ "kind" => "add_on",
+ "name" => "php_add_on",
+ "neverExpires" => "false",
+ "numberOfBillingCycles" => "1"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/modifications/create_modification_for_tests";
+ $http->post($path, array("modification" => $addOnParams));
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $addOns = $gateway->addOn()->all();
+
+ foreach ($addOns as $addOn)
+ {
+ if ($addOn->id == $newId)
+ {
+ $actualAddOn = $addOn;
+ }
+ }
+
+ $this->assertNotNull($actualAddOn);
+ $this->assertEquals($addOnParams["amount"], $actualAddOn->amount);
+ $this->assertEquals($addOnParams["description"], $actualAddOn->description);
+ $this->assertEquals($addOnParams["id"], $actualAddOn->id);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/AddressTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/AddressTest.php
new file mode 100644
index 0000000..e7b1c1a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/AddressTest.php
@@ -0,0 +1,298 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_AddressTest extends PHPUnit_Framework_TestCase
+{
+ function testCreate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'streetAddress' => '1 E Main St',
+ 'extendedAddress' => 'Apt 1F',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'Vatican City',
+ 'countryCodeAlpha2' => 'VA',
+ 'countryCodeAlpha3' => 'VAT',
+ 'countryCodeNumeric' => '336'
+ ));
+ $this->assertTrue($result->success);
+ $address = $result->address;
+ $this->assertEquals('Dan', $address->firstName);
+ $this->assertEquals('Smith', $address->lastName);
+ $this->assertEquals('Braintree', $address->company);
+ $this->assertEquals('1 E Main St', $address->streetAddress);
+ $this->assertEquals('Apt 1F', $address->extendedAddress);
+ $this->assertEquals('Chicago', $address->locality);
+ $this->assertEquals('IL', $address->region);
+ $this->assertEquals('60622', $address->postalCode);
+ $this->assertEquals('Vatican City', $address->countryName);
+ $this->assertEquals('VA', $address->countryCodeAlpha2);
+ $this->assertEquals('VAT', $address->countryCodeAlpha3);
+ $this->assertEquals('336', $address->countryCodeNumeric);
+ }
+
+ function testGatewayCreate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->address()->create(array(
+ 'customerId' => $customer->id,
+ 'streetAddress' => '1 E Main St',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ ));
+
+ $this->assertTrue($result->success);
+ $address = $result->address;
+ $this->assertEquals('1 E Main St', $address->streetAddress);
+ $this->assertEquals('Chicago', $address->locality);
+ $this->assertEquals('IL', $address->region);
+ $this->assertEquals('60622', $address->postalCode);
+ }
+
+ function testCreate_withValidationErrors()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'countryName' => 'Invalid States of America'
+ ));
+ $this->assertFalse($result->success);
+ $countryErrors = $result->errors->forKey('address')->onAttribute('countryName');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, $countryErrors[0]->code);
+ }
+
+ function testCreate_withValidationErrors_onCountryCodes()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'countryCodeAlpha2' => 'ZZ'
+ ));
+ $this->assertFalse($result->success);
+ $countryErrors = $result->errors->forKey('address')->onAttribute('countryCodeAlpha2');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED, $countryErrors[0]->code);
+ }
+
+ function testCreateNoValidate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $address = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'streetAddress' => '1 E Main St',
+ 'extendedAddress' => 'Apt 1F',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'United States of America'
+ ));
+ $this->assertEquals('Dan', $address->firstName);
+ $this->assertEquals('Smith', $address->lastName);
+ $this->assertEquals('Braintree', $address->company);
+ $this->assertEquals('1 E Main St', $address->streetAddress);
+ $this->assertEquals('Apt 1F', $address->extendedAddress);
+ $this->assertEquals('Chicago', $address->locality);
+ $this->assertEquals('IL', $address->region);
+ $this->assertEquals('60622', $address->postalCode);
+ $this->assertEquals('United States of America', $address->countryName);
+ }
+
+ function testCreateNoValidate_withValidationErrors()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'countryName' => 'Invalid States of America'
+ ));
+ }
+
+ function testDelete()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $address = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'streetAddress' => '1 E Main St'
+ ));
+ Braintree_Address::find($customer->id, $address->id);
+ Braintree_Address::delete($customer->id, $address->id);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_Address::find($customer->id, $address->id);
+ }
+
+ function testFind()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'streetAddress' => '1 E Main St',
+ 'extendedAddress' => 'Apt 1F',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'United States of America'
+ ));
+ $this->assertTrue($result->success);
+ $address = Braintree_Address::find($customer->id, $result->address->id);
+ $this->assertEquals('Dan', $address->firstName);
+ $this->assertEquals('Smith', $address->lastName);
+ $this->assertEquals('Braintree', $address->company);
+ $this->assertEquals('1 E Main St', $address->streetAddress);
+ $this->assertEquals('Apt 1F', $address->extendedAddress);
+ $this->assertEquals('Chicago', $address->locality);
+ $this->assertEquals('IL', $address->region);
+ $this->assertEquals('60622', $address->postalCode);
+ $this->assertEquals('United States of America', $address->countryName);
+ }
+
+ function testFind_whenNotFound()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_Address::find($customer->id, 'does-not-exist');
+ }
+
+ function testUpdate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $address = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Old First',
+ 'lastName' => 'Old Last',
+ 'company' => 'Old Company',
+ 'streetAddress' => '1 E Old St',
+ 'extendedAddress' => 'Apt Old',
+ 'locality' => 'Old Chicago',
+ 'region' => 'Old Region',
+ 'postalCode' => 'Old Postal',
+ 'countryName' => 'United States of America',
+ 'countryCodeAlpha2' => 'US',
+ 'countryCodeAlpha3' => 'USA',
+ 'countryCodeNumeric' => '840'
+ ));
+ $result = Braintree_Address::update($customer->id, $address->id, array(
+ 'firstName' => 'New First',
+ 'lastName' => 'New Last',
+ 'company' => 'New Company',
+ 'streetAddress' => '1 E New St',
+ 'extendedAddress' => 'Apt New',
+ 'locality' => 'New Chicago',
+ 'region' => 'New Region',
+ 'postalCode' => 'New Postal',
+ 'countryName' => 'Mexico',
+ 'countryCodeAlpha2' => 'MX',
+ 'countryCodeAlpha3' => 'MEX',
+ 'countryCodeNumeric' => '484'
+ ));
+ $this->assertTrue($result->success);
+ $address = $result->address;
+ $this->assertEquals('New First', $address->firstName);
+ $this->assertEquals('New Last', $address->lastName);
+ $this->assertEquals('New Company', $address->company);
+ $this->assertEquals('1 E New St', $address->streetAddress);
+ $this->assertEquals('Apt New', $address->extendedAddress);
+ $this->assertEquals('New Chicago', $address->locality);
+ $this->assertEquals('New Region', $address->region);
+ $this->assertEquals('New Postal', $address->postalCode);
+ $this->assertEquals('Mexico', $address->countryName);
+ $this->assertEquals('MX', $address->countryCodeAlpha2);
+ $this->assertEquals('MEX', $address->countryCodeAlpha3);
+ $this->assertEquals('484', $address->countryCodeNumeric);
+ }
+
+ function testUpdate_withValidationErrors()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $address = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'streetAddress' => '1 E Main St'
+ ));
+ $result = Braintree_Address::update(
+ $customer->id,
+ $address->id,
+ array(
+ 'countryName' => 'Invalid States of America'
+ )
+ );
+ $this->assertFalse($result->success);
+ $countryErrors = $result->errors->forKey('address')->onAttribute('countryName');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, $countryErrors[0]->code);
+ }
+
+ function testUpdate_withValidationErrors_onCountry()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $address = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'streetAddress' => '1 E Main St'
+ ));
+ $result = Braintree_Address::update(
+ $customer->id,
+ $address->id,
+ array(
+ 'countryCodeAlpha2' => 'MU',
+ 'countryCodeAlpha3' => 'MYT'
+ )
+ );
+ $this->assertFalse($result->success);
+ $countryErrors = $result->errors->forKey('address')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_INCONSISTENT_COUNTRY, $countryErrors[0]->code);
+ }
+
+
+ function testUpdateNoValidate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $createdAddress = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Old First',
+ 'lastName' => 'Old Last',
+ 'company' => 'Old Company',
+ 'streetAddress' => '1 E Old St',
+ 'extendedAddress' => 'Apt Old',
+ 'locality' => 'Old Chicago',
+ 'region' => 'Old Region',
+ 'postalCode' => 'Old Postal',
+ 'countryName' => 'United States of America'
+ ));
+ $address = Braintree_Address::updateNoValidate($customer->id, $createdAddress->id, array(
+ 'firstName' => 'New First',
+ 'lastName' => 'New Last',
+ 'company' => 'New Company',
+ 'streetAddress' => '1 E New St',
+ 'extendedAddress' => 'Apt New',
+ 'locality' => 'New Chicago',
+ 'region' => 'New Region',
+ 'postalCode' => 'New Postal',
+ 'countryName' => 'Mexico'
+ ));
+ $this->assertEquals('New First', $address->firstName);
+ $this->assertEquals('New Last', $address->lastName);
+ $this->assertEquals('New Company', $address->company);
+ $this->assertEquals('1 E New St', $address->streetAddress);
+ $this->assertEquals('Apt New', $address->extendedAddress);
+ $this->assertEquals('New Chicago', $address->locality);
+ $this->assertEquals('New Region', $address->region);
+ $this->assertEquals('New Postal', $address->postalCode);
+ $this->assertEquals('Mexico', $address->countryName);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/ClientTokenTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/ClientTokenTest.php
new file mode 100644
index 0000000..5ef9eea
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/ClientTokenTest.php
@@ -0,0 +1,183 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_ClientTokenTest extends PHPUnit_Framework_TestCase
+{
+ function test_ClientTokenAuthorizesRequest()
+ {
+ $clientToken = Braintree_TestHelper::decodedClientToken();
+ $authorizationFingerprint = json_decode($clientToken)->authorizationFingerprint;
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $response = $http->get_cards(array(
+ "authorization_fingerprint" => $authorizationFingerprint,
+ "shared_customer_identifier" => "fake_identifier",
+ "shared_customer_identifier_type" => "testing"
+ ));
+
+ $this->assertEquals(200, $response["status"]);
+ }
+
+ function test_VersionOptionSupported()
+ {
+ $clientToken = Braintree_ClientToken::generate(array("version" => 1));
+ $version = json_decode($clientToken)->version;
+ $this->assertEquals(1, $version);
+ }
+
+ function test_VersionDefaultsToTwo()
+ {
+ $encodedClientToken = Braintree_ClientToken::generate();
+ $clientToken = base64_decode($encodedClientToken);
+ $version = json_decode($clientToken)->version;
+ $this->assertEquals(2, $version);
+ }
+
+ function testGateway_VersionDefaultsToTwo()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $encodedClientToken = $gateway->clientToken()->generate();
+ $clientToken = base64_decode($encodedClientToken);
+ $version = json_decode($clientToken)->version;
+ $this->assertEquals(2, $version);
+ }
+
+ function test_GatewayRespectsVerifyCard()
+ {
+ $result = Braintree_Customer::create();
+ $this->assertTrue($result->success);
+ $customerId = $result->customer->id;
+
+ $clientToken = Braintree_TestHelper::decodedClientToken(array(
+ "customerId" => $customerId,
+ "options" => array(
+ "verifyCard" => true
+ )
+ ));
+ $authorizationFingerprint = json_decode($clientToken)->authorizationFingerprint;
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $response = $http->post('/client_api/v1/payment_methods/credit_cards.json', json_encode(array(
+ "credit_card" => array(
+ "number" => "4000111111111115",
+ "expirationDate" => "11/2099"
+ ),
+ "authorization_fingerprint" => $authorizationFingerprint,
+ "shared_customer_identifier" => "fake_identifier",
+ "shared_customer_identifier_type" => "testing"
+ )));
+
+ $this->assertEquals(422, $response["status"]);
+ }
+
+ function test_GatewayRespectsFailOnDuplicatePaymentMethod()
+ {
+ $result = Braintree_Customer::create();
+ $this->assertTrue($result->success);
+ $customerId = $result->customer->id;
+
+ $clientToken = Braintree_TestHelper::decodedClientToken(array(
+ "customerId" => $customerId,
+ ));
+ $authorizationFingerprint = json_decode($clientToken)->authorizationFingerprint;
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $response = $http->post('/client_api/v1/payment_methods/credit_cards.json', json_encode(array(
+ "credit_card" => array(
+ "number" => "4242424242424242",
+ "expirationDate" => "11/2099"
+ ),
+ "authorization_fingerprint" => $authorizationFingerprint,
+ "shared_customer_identifier" => "fake_identifier",
+ "shared_customer_identifier_type" => "testing"
+ )));
+ $this->assertEquals(201, $response["status"]);
+
+ $clientToken = Braintree_TestHelper::decodedClientToken(array(
+ "customerId" => $customerId,
+ "options" => array(
+ "failOnDuplicatePaymentMethod" => true
+ )
+ ));
+ $authorizationFingerprint = json_decode($clientToken)->authorizationFingerprint;
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $response = $http->post('/client_api/v1/payment_methods/credit_cards.json', json_encode(array(
+ "credit_card" => array(
+ "number" => "4242424242424242",
+ "expirationDate" => "11/2099"
+ ),
+ "authorization_fingerprint" => $authorizationFingerprint,
+ "shared_customer_identifier" => "fake_identifier",
+ "shared_customer_identifier_type" => "testing"
+ )));
+ $this->assertEquals(422, $response["status"]);
+ }
+
+ function test_GatewayRespectsMakeDefault()
+ {
+ $result = Braintree_Customer::create();
+ $this->assertTrue($result->success);
+ $customerId = $result->customer->id;
+
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customerId,
+ 'number' => '4111111111111111',
+ 'expirationDate' => '11/2099'
+ ));
+ $this->assertTrue($result->success);
+
+ $clientToken = Braintree_TestHelper::decodedClientToken(array(
+ "customerId" => $customerId,
+ "options" => array(
+ "makeDefault" => true
+ )
+ ));
+ $authorizationFingerprint = json_decode($clientToken)->authorizationFingerprint;
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $response = $http->post('/client_api/v1/payment_methods/credit_cards.json', json_encode(array(
+ "credit_card" => array(
+ "number" => "4242424242424242",
+ "expirationDate" => "11/2099"
+ ),
+ "authorization_fingerprint" => $authorizationFingerprint,
+ "shared_customer_identifier" => "fake_identifier",
+ "shared_customer_identifier_type" => "testing"
+ )));
+
+ $this->assertEquals(201, $response["status"]);
+
+ $customer = Braintree_Customer::find($customerId);
+ $this->assertEquals(2, count($customer->creditCards));
+ foreach ($customer->creditCards as $creditCard) {
+ if ($creditCard->last4 == "4242") {
+ $this->assertTrue($creditCard->default);
+ }
+ }
+ }
+
+ function test_ClientTokenAcceptsMerchantAccountId()
+ {
+ $clientToken = Braintree_TestHelper::decodedClientToken(array(
+ 'merchantAccountId' => 'my_merchant_account'
+ ));
+ $merchantAccountId = json_decode($clientToken)->merchantAccountId;
+
+ $this->assertEquals('my_merchant_account', $merchantAccountId);
+ }
+
+ function test_GenerateRaisesExceptionOnGateway422()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'customer_id');
+
+ Braintree_ClientToken::generate(array(
+ "customerId" => "not_a_customer"
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardTest.php
new file mode 100644
index 0000000..2795b26
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardTest.php
@@ -0,0 +1,1289 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_CreditCardTest extends PHPUnit_Framework_TestCase
+{
+ function testCreate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals($customer->id, $result->creditCard->customerId);
+ $this->assertEquals('510510', $result->creditCard->bin);
+ $this->assertEquals('5100', $result->creditCard->last4);
+ $this->assertEquals('Cardholder', $result->creditCard->cardholderName);
+ $this->assertEquals('05/2012', $result->creditCard->expirationDate);
+ $this->assertEquals(1, preg_match('/\A\w{32}\z/', $result->creditCard->uniqueNumberIdentifier));
+ $this->assertFalse($result->creditCard->isVenmoSdk());
+ $this->assertEquals(1, preg_match('/png/', $result->creditCard->imageUrl));
+ }
+
+ function testGatewayCreate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->creditCard()->create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertEquals($customer->id, $result->creditCard->customerId);
+ $this->assertEquals('510510', $result->creditCard->bin);
+ $this->assertEquals('5100', $result->creditCard->last4);
+ $this->assertEquals('Cardholder', $result->creditCard->cardholderName);
+ $this->assertEquals('05/2012', $result->creditCard->expirationDate);
+ }
+
+ function testCreate_withDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $card1 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+ $this->assertTrue($card1->isDefault());
+
+ $card2 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'options' => array(
+ 'makeDefault' => true
+ )
+ ))->creditCard;
+
+ $card1 = Braintree_CreditCard::find($card1->token);
+ $this->assertFalse($card1->isDefault());
+ $this->assertTrue($card2->isDefault());
+ }
+
+ function testAddCardToExistingCustomerUsingNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "credit_card" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "share" => true
+ ));
+
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertSame("411111", $result->creditCard->bin);
+ $this->assertSame("1111", $result->creditCard->last4);
+ }
+
+ function testCreate_withSecurityParams()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'deviceSessionId' => 'abc_123',
+ 'fraudMerchantId' => '456',
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+
+ $this->assertTrue($result->success);
+ }
+
+ function testCreate_withExpirationMonthAndYear()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationMonth' => '05',
+ 'expirationYear' => '2011'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals($customer->id, $result->creditCard->customerId);
+ $this->assertEquals('510510', $result->creditCard->bin);
+ $this->assertEquals('5100', $result->creditCard->last4);
+ $this->assertEquals('Cardholder', $result->creditCard->cardholderName);
+ $this->assertEquals('05/2011', $result->creditCard->expirationDate);
+ }
+
+ function testCreate_withSpecifyingToken()
+ {
+ $token = strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'token' => $token
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals($token, $result->creditCard->token);
+ $this->assertEquals($token, Braintree_CreditCard::find($token)->token);
+ }
+
+ function testCreate_withDuplicateCardCheck()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $attributes = array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'options' => array('failOnDuplicatePaymentMethod' => true)
+ );
+ Braintree_CreditCard::create($attributes);
+
+ $result = Braintree_CreditCard::create($attributes);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('creditCard')->onAttribute('number');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_DUPLICATE_CARD_EXISTS, $errors[0]->code);
+ $this->assertEquals(1, preg_match('/Duplicate card exists in the vault\./', $result->message));
+ }
+
+ function testCreate_withCardVerification()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals('2000', $result->creditCardVerification->processorResponseCode);
+ $this->assertEquals('Do Not Honor', $result->creditCardVerification->processorResponseText);
+ $this->assertEquals('I', $result->creditCardVerification->cvvResponseCode);
+ $this->assertEquals(null, $result->creditCardVerification->avsErrorResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsPostalCodeResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsStreetAddressResponseCode);
+ $this->assertEquals(Braintree_CreditCard::PREPAID_UNKNOWN, $result->creditCardVerification->creditCard["prepaid"]);
+ }
+
+ function testCreate_withCardVerificationReturnsVerificationWithRiskData()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/2011',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertTrue($result->success);
+ $this->assertNotNull($result->creditCard->verification->riskData);
+ $this->assertNotNull($result->creditCard->verification->riskData->decision);
+ }
+
+ function testCreate_withCardVerificationAndOverriddenAmount()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'options' => array('verifyCard' => true, 'verificationAmount' => '1.02')
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals('2000', $result->creditCardVerification->processorResponseCode);
+ $this->assertEquals('Do Not Honor', $result->creditCardVerification->processorResponseText);
+ $this->assertEquals('I', $result->creditCardVerification->cvvResponseCode);
+ $this->assertEquals(null, $result->creditCardVerification->avsErrorResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsPostalCodeResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsStreetAddressResponseCode);
+ $this->assertEquals(Braintree_CreditCard::PREPAID_UNKNOWN, $result->creditCardVerification->creditCard["prepaid"]);
+ }
+
+ function testCreate_withCardVerificationAndSpecificMerchantAccount()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'options' => array('verificationMerchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(), 'verifyCard' => true)
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals('2000', $result->creditCardVerification->processorResponseCode);
+ $this->assertEquals('Do Not Honor', $result->creditCardVerification->processorResponseText);
+ $this->assertEquals('I', $result->creditCardVerification->cvvResponseCode);
+ $this->assertEquals(null, $result->creditCardVerification->avsErrorResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsPostalCodeResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsStreetAddressResponseCode);
+ }
+
+ function testCreate_withBillingAddress()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Peter Tomlin',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'firstName' => 'Drew',
+ 'lastName' => 'Smith',
+ 'company' => 'Smith Co.',
+ 'streetAddress' => '1 E Main St',
+ 'extendedAddress' => 'Suite 101',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'Micronesia',
+ 'countryCodeAlpha2' => 'FM',
+ 'countryCodeAlpha3' => 'FSM',
+ 'countryCodeNumeric' => '583'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals($customer->id, $result->creditCard->customerId);
+ $this->assertEquals('510510', $result->creditCard->bin);
+ $this->assertEquals('5100', $result->creditCard->last4);
+ $this->assertEquals('Peter Tomlin', $result->creditCard->cardholderName);
+ $this->assertEquals('05/2012', $result->creditCard->expirationDate);
+ $address = $result->creditCard->billingAddress;
+ $this->assertEquals('Drew', $address->firstName);
+ $this->assertEquals('Smith', $address->lastName);
+ $this->assertEquals('Smith Co.', $address->company);
+ $this->assertEquals('1 E Main St', $address->streetAddress);
+ $this->assertEquals('Suite 101', $address->extendedAddress);
+ $this->assertEquals('Chicago', $address->locality);
+ $this->assertEquals('IL', $address->region);
+ $this->assertEquals('60622', $address->postalCode);
+ $this->assertEquals('Micronesia', $address->countryName);
+ $this->assertEquals('FM', $address->countryCodeAlpha2);
+ $this->assertEquals('FSM', $address->countryCodeAlpha3);
+ $this->assertEquals('583', $address->countryCodeNumeric);
+ }
+
+ function testCreate_withExistingBillingAddress()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $existingAddress = Braintree_Address::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'John'
+ ));
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddressId' => $existingAddress->id
+ ));
+ $this->assertTrue($result->success);
+ $address = $result->creditCard->billingAddress;
+ $this->assertEquals($existingAddress->id, $address->id);
+ $this->assertEquals('John', $address->firstName);
+ }
+
+ function testCreate_withValidationErrors()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'expirationDate' => 'invalid',
+ 'billingAddress' => array(
+ 'countryName' => 'Tuvalu',
+ 'countryCodeAlpha2' => 'US'
+ )
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('creditCard')->onAttribute('expirationDate');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_EXPIRATION_DATE_IS_INVALID, $errors[0]->code);
+ $this->assertEquals(1, preg_match('/Credit card number is required\./', $result->message));
+ $this->assertEquals(1, preg_match('/Customer ID is required\./', $result->message));
+ $this->assertEquals(1, preg_match('/Expiration date is invalid\./', $result->message));
+
+ $errors = $result->errors->forKey('creditCard')->forKey('billingAddress')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_INCONSISTENT_COUNTRY, $errors[0]->code);
+ }
+
+ function testCreate_withVenmoSdkPaymentMethodCode()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'venmoSdkPaymentMethodCode' => Braintree_Test_VenmoSdk::generateTestPaymentMethodCode("378734493671000")
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals("378734", $result->creditCard->bin);
+ }
+
+ function testCreate_with_invalid_venmoSdkPaymentMethodCode()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'venmoSdkPaymentMethodCode' => Braintree_Test_VenmoSdk::getInvalidPaymentMethodCode()
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('creditCard')->onAttribute('venmoSdkPaymentMethodCode');
+ $this->assertEquals($errors[0]->code, Braintree_Error_Codes::CREDIT_CARD_INVALID_VENMO_SDK_PAYMENT_METHOD_CODE);
+
+ }
+
+ function testCreate_with_venmoSdkSession()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'options' => array(
+ 'venmoSdkSession' => Braintree_Test_VenmoSdk::getTestSession()
+ )
+ ));
+ $this->assertTrue($result->success);
+ $this->assertTrue($result->creditCard->isVenmoSdk());
+ }
+
+ function testCreate_with_invalidVenmoSdkSession()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'options' => array(
+ 'venmoSdkSession' => Braintree_Test_VenmoSdk::getInvalidTestSession()
+ )
+ ));
+ $this->assertTrue($result->success);
+ $this->assertFalse($result->creditCard->isVenmoSdk());
+ }
+
+ function testCreateNoValidate_throwsIfValidationsFail()
+ {
+
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ $customer = Braintree_Customer::createNoValidate();
+ Braintree_CreditCard::createNoValidate(array(
+ 'expirationDate' => 'invalid',
+ ));
+ }
+
+ function testCreateNoValidate_returnsCreditCardIfValid()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertEquals($customer->id, $creditCard->customerId);
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('Cardholder', $creditCard->cardholderName);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ }
+
+ function testCreateFromTransparentRedirect()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $customer = Braintree_Customer::createNoValidate();
+ $queryString = $this->createCreditCardViaTr(
+ array(
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ )
+ ),
+ array(
+ 'creditCard' => array(
+ 'customerId' => $customer->id
+ )
+ )
+ );
+ $result = Braintree_CreditCard::createFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('510510', $result->creditCard->bin);
+ $this->assertEquals('5100', $result->creditCard->last4);
+ $this->assertEquals('05/2012', $result->creditCard->expirationDate);
+ }
+
+ function testCreateFromTransparentRedirect_withDefault()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $customer = Braintree_Customer::createNoValidate();
+ $queryString = $this->createCreditCardViaTr(
+ array(
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12',
+ 'options' => array('make_default' => true)
+ )
+ ),
+ array(
+ 'creditCard' => array(
+ 'customerId' => $customer->id
+ )
+ )
+ );
+ $result = Braintree_CreditCard::createFromTransparentRedirect($queryString);
+ $this->assertTrue($result->creditCard->isDefault());
+ }
+
+ function testUpdateFromTransparentRedirect()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $queryString = $this->updateCreditCardViaTr(
+ array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expiration_date' => '01/11'
+ )
+ ),
+ array('paymentMethodToken' => $creditCard->token)
+ );
+ $result = Braintree_CreditCard::updateFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('411111', $result->creditCard->bin);
+ $this->assertEquals('1111', $result->creditCard->last4);
+ $this->assertEquals('01/2011', $result->creditCard->expirationDate);
+ }
+
+ function testUpdateFromTransparentRedirect_withDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $card1 = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $card2 = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertFalse($card2->isDefault());
+
+ $queryString = $this->updateCreditCardViaTr(
+ array(
+ 'credit_card' => array(
+ 'options' => array(
+ 'make_default' => true
+ )
+ )
+ ),
+ array('paymentMethodToken' => $card2->token)
+ );
+ $result = Braintree_CreditCard::updateFromTransparentRedirect($queryString);
+ $this->assertFalse(Braintree_CreditCard::find($card1->token)->isDefault());
+ $this->assertTrue(Braintree_CreditCard::find($card2->token)->isDefault());
+ }
+
+ function testUpdateFromTransparentRedirect_andUpdateExistingBillingAddress()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $card = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'firstName' => 'Drew',
+ 'lastName' => 'Smith',
+ 'company' => 'Smith Co.',
+ 'streetAddress' => '123 Old St',
+ 'extendedAddress' => 'Suite 101',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'United States of America'
+ )
+ ));
+
+ $queryString = $this->updateCreditCardViaTr(
+ array(),
+ array(
+ 'paymentMethodToken' => $card->token,
+ 'creditCard' => array(
+ 'billingAddress' => array(
+ 'streetAddress' => '123 New St',
+ 'locality' => 'St. Louis',
+ 'region' => 'MO',
+ 'postalCode' => '63119',
+ 'options' => array(
+ 'updateExisting' => True
+ )
+ )
+ )
+ )
+ );
+ $result = Braintree_CreditCard::updateFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $card = $result->creditCard;
+ $this->assertEquals(1, sizeof(Braintree_Customer::find($customer->id)->addresses));
+ $this->assertEquals('123 New St', $card->billingAddress->streetAddress);
+ $this->assertEquals('St. Louis', $card->billingAddress->locality);
+ $this->assertEquals('MO', $card->billingAddress->region);
+ $this->assertEquals('63119', $card->billingAddress->postalCode);
+ }
+
+ function testSale_createsASaleUsingGivenToken()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $result = Braintree_CreditCard::sale($creditCard->token, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals($customer->id, $result->transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $result->transaction->creditCardDetails->token);
+ }
+
+ function testSaleNoValidate_createsASaleUsingGivenToken()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $transaction = Braintree_CreditCard::saleNoValidate($creditCard->token, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals($customer->id, $transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $transaction->creditCardDetails->token);
+ }
+
+ function testSaleNoValidate_createsASaleUsingGivenTokenAndCvv()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $transaction = Braintree_CreditCard::saleNoValidate($creditCard->token, array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cvv' => '301'
+ )
+ ));
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals($customer->id, $transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $transaction->creditCardDetails->token);
+ $this->assertEquals('S', $transaction->cvvResponseCode);
+ }
+
+ function testSaleNoValidate_throwsIfInvalid()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_CreditCard::saleNoValidate($creditCard->token, array(
+ 'amount' => 'invalid'
+ ));
+ }
+
+ function testCredit_createsACreditUsingGivenToken()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $result = Braintree_CreditCard::credit($creditCard->token, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals(Braintree_Transaction::CREDIT, $result->transaction->type);
+ $this->assertEquals($customer->id, $result->transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $result->transaction->creditCardDetails->token);
+ }
+
+ function testCreditNoValidate_createsACreditUsingGivenToken()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $transaction = Braintree_CreditCard::creditNoValidate($creditCard->token, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals(Braintree_Transaction::CREDIT, $transaction->type);
+ $this->assertEquals($customer->id, $transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $transaction->creditCardDetails->token);
+ }
+
+ function testCreditNoValidate_throwsIfInvalid()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_CreditCard::creditNoValidate($creditCard->token, array(
+ 'amount' => 'invalid'
+ ));
+ }
+
+ function testExpired()
+ {
+ $collection = Braintree_CreditCard::expired();
+ $this->assertTrue($collection->maximumCount() > 1);
+
+ $arr = array();
+ foreach($collection as $creditCard) {
+ $this->assertTrue($creditCard->isExpired());
+ array_push($arr, $creditCard->token);
+ }
+ $uniqueCreditCardTokens = array_unique(array_values($arr));
+ $this->assertEquals($collection->maximumCount(), count($uniqueCreditCardTokens));
+ }
+
+
+ function testExpiringBetween()
+ {
+ $collection = Braintree_CreditCard::expiringBetween(
+ mktime(0, 0, 0, 1, 1, 2010),
+ mktime(23, 59, 59, 12, 31, 2010)
+ );
+ $this->assertTrue($collection->maximumCount() > 1);
+
+ $arr = array();
+ foreach($collection as $creditCard) {
+ $this->assertEquals('2010', $creditCard->expirationYear);
+ array_push($arr, $creditCard->token);
+ }
+ $uniqueCreditCardTokens = array_unique(array_values($arr));
+ $this->assertEquals($collection->maximumCount(), count($uniqueCreditCardTokens));
+ }
+
+ function testExpiringBetween_parsesCreditCardDetailsUnderTransactionsCorrectly()
+ {
+ $collection = Braintree_CreditCard::expiringBetween(
+ mktime(0, 0, 0, 1, 1, 2010),
+ mktime(23, 59, 59, 12, 31, 2010)
+ );
+ $this->assertTrue($collection->maximumCount() > 1);
+
+ foreach($collection as $creditCard) {
+ foreach($creditCard->subscriptions as $subscription) {
+ foreach($subscription->transactions as $transaction) {
+ $this->assertNotNull($transaction->creditCardDetails->expirationMonth);
+ }
+ }
+ }
+ }
+
+ function testFind()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertTrue($result->success);
+ $creditCard = Braintree_CreditCard::find($result->creditCard->token);
+ $this->assertEquals($customer->id, $creditCard->customerId);
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('Cardholder', $creditCard->cardholderName);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals(array(), $creditCard->subscriptions);
+ }
+
+ function testFindReturnsAssociatedSubscriptions()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'firstName' => 'Drew',
+ 'lastName' => 'Smith',
+ 'company' => 'Smith Co.',
+ 'streetAddress' => '1 E Main St',
+ 'extendedAddress' => 'Suite 101',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'United States of America'
+ )
+ ));
+ $id = strval(rand());
+ Braintree_Subscription::create(array(
+ 'id' => $id,
+ 'paymentMethodToken' => $result->creditCard->token,
+ 'planId' => 'integration_trialless_plan',
+ 'price' => '1.00'
+ ));
+ $creditCard = Braintree_CreditCard::find($result->creditCard->token);
+ $this->assertEquals($id, $creditCard->subscriptions[0]->id);
+ $this->assertEquals('integration_trialless_plan', $creditCard->subscriptions[0]->planId);
+ $this->assertEquals('1.00', $creditCard->subscriptions[0]->price);
+ }
+
+ function testFind_throwsIfCannotBeFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_CreditCard::find('invalid-token');
+ }
+
+ function testFind_throwsUsefulErrorMessagesWhenEmpty()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'expected credit card id to be set');
+ Braintree_CreditCard::find('');
+ }
+
+ function testFind_throwsUsefulErrorMessagesWhenInvalid()
+ {
+ $this->setExpectedException('InvalidArgumentException', '@ is an invalid credit card token');
+ Braintree_CreditCard::find('@');
+ }
+
+ function testFromNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "credit_card" => array(
+ "number" => "4009348888881881",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "customerId" => $customer->id
+ ));
+
+ $creditCard = Braintree_CreditCard::fromNonce($nonce);
+
+ $customer = Braintree_Customer::find($customer->id);
+ $this->assertEquals($customer->creditCards[0], $creditCard);
+ }
+
+ function testFromNonce_ReturnsErrorWhenNoncePointsToSharedCard()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "credit_card" => array(
+ "number" => "4009348888881881",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "share" => true
+ ));
+
+ $this->setExpectedException('Braintree_Exception_NotFound', "not found");
+ Braintree_CreditCard::fromNonce($nonce);
+ }
+
+ function testFromNonce_ReturnsErrorWhenNonceIsConsumed()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "credit_card" => array(
+ "number" => "4009348888881881",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "customerId" => $customer->id
+ ));
+
+ Braintree_CreditCard::fromNonce($nonce);
+ $this->setExpectedException('Braintree_Exception_NotFound', "consumed");
+ Braintree_CreditCard::fromNonce($nonce);
+ }
+
+ function testUpdate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $createResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Old Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertTrue($createResult->success);
+ $updateResult = Braintree_CreditCard::update($createResult->creditCard->token, array(
+ 'cardholderName' => 'New Cardholder',
+ 'number' => '4111111111111111',
+ 'expirationDate' => '07/14'
+ ));
+ $this->assertEquals($customer->id, $updateResult->creditCard->customerId);
+ $this->assertEquals('411111', $updateResult->creditCard->bin);
+ $this->assertEquals('1111', $updateResult->creditCard->last4);
+ $this->assertEquals('New Cardholder', $updateResult->creditCard->cardholderName);
+ $this->assertEquals('07/2014', $updateResult->creditCard->expirationDate);
+ }
+
+ function testUpdate_withCardVerification()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $initialCreditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $result = Braintree_CreditCard::update($initialCreditCard->token, array(
+ 'billingAddress' => array(
+ 'region' => 'IL'
+ ),
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals('2000', $result->creditCardVerification->processorResponseCode);
+ $this->assertEquals('Do Not Honor', $result->creditCardVerification->processorResponseText);
+ $this->assertEquals('I', $result->creditCardVerification->cvvResponseCode);
+ $this->assertEquals(null, $result->creditCardVerification->avsErrorResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsPostalCodeResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsStreetAddressResponseCode);
+ $this->assertEquals(Braintree_TestHelper::defaultMerchantAccountId(), $result->creditCardVerification->merchantAccountId);
+ }
+
+ function testUpdate_withCardVerificationAndSpecificMerchantAccount()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $initialCreditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $result = Braintree_CreditCard::update($initialCreditCard->token, array(
+ 'billingAddress' => array(
+ 'region' => 'IL'
+ ),
+ 'options' => array(
+ 'verificationMerchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'verifyCard' => true
+ )
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals(Braintree_TestHelper::nonDefaultMerchantAccountId(), $result->creditCardVerification->merchantAccountId);
+ }
+
+ function testUpdate_createsNewBillingAddressByDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $initialCreditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Nigeria Ave'
+ )
+ ))->creditCard;
+
+ $updatedCreditCard = Braintree_CreditCard::update($initialCreditCard->token, array(
+ 'billingAddress' => array(
+ 'region' => 'IL'
+ )
+ ))->creditCard;
+ $this->assertEquals('IL', $updatedCreditCard->billingAddress->region);
+ $this->assertNull($updatedCreditCard->billingAddress->streetAddress);
+ $this->assertNotEquals($initialCreditCard->billingAddress->id, $updatedCreditCard->billingAddress->id);
+ }
+
+ function testUpdate_updatesExistingBillingAddressIfUpdateExistingOptionIsTrue()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $initialCreditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'countryName' => 'Turkey',
+ 'countryCodeAlpha2' => 'TR',
+ 'countryCodeAlpha3' => 'TUR',
+ 'countryCodeNumeric' => '792',
+ )
+ ))->creditCard;
+
+ $updatedCreditCard = Braintree_CreditCard::update($initialCreditCard->token, array(
+ 'billingAddress' => array(
+ 'countryName' => 'Thailand',
+ 'countryCodeAlpha2' => 'TH',
+ 'countryCodeAlpha3' => 'THA',
+ 'countryCodeNumeric' => '764',
+ 'options' => array(
+ 'updateExisting' => True
+ )
+ )
+ ))->creditCard;
+ $this->assertEquals('Thailand', $updatedCreditCard->billingAddress->countryName);
+ $this->assertEquals('TH', $updatedCreditCard->billingAddress->countryCodeAlpha2);
+ $this->assertEquals('THA', $updatedCreditCard->billingAddress->countryCodeAlpha3);
+ $this->assertEquals('764', $updatedCreditCard->billingAddress->countryCodeNumeric);
+ $this->assertEquals($initialCreditCard->billingAddress->id, $updatedCreditCard->billingAddress->id);
+ }
+
+ function testUpdate_canChangeToken()
+ {
+ $oldToken = strval(rand());
+ $newToken = strval(rand());
+
+ $customer = Braintree_Customer::createNoValidate();
+ $createResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'token' => $oldToken,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertTrue($createResult->success);
+ $updateResult = Braintree_CreditCard::update($oldToken, array(
+ 'token' => $newToken
+ ));
+ $this->assertEquals($customer->id, $updateResult->creditCard->customerId);
+ $this->assertEquals($newToken, $updateResult->creditCard->token);
+ $this->assertEquals($newToken, Braintree_CreditCard::find($newToken)->token);
+ }
+
+ function testUpdateNoValidate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Old Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $updatedCard = Braintree_CreditCard::updateNoValidate($creditCard->token, array(
+ 'cardholderName' => 'New Cardholder',
+ 'number' => '4111111111111111',
+ 'expirationDate' => '07/14'
+ ));
+ $this->assertEquals($customer->id, $updatedCard->customerId);
+ $this->assertEquals('411111', $updatedCard->bin);
+ $this->assertEquals('1111', $updatedCard->last4);
+ $this->assertEquals('New Cardholder', $updatedCard->cardholderName);
+ $this->assertEquals('07/2014', $updatedCard->expirationDate);
+ }
+
+ function testUpdateNoValidate_throwsIfInvalid()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Old Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_CreditCard::updateNoValidate($creditCard->token, array(
+ 'number' => 'invalid',
+ ));
+ }
+
+ function testUpdate_withDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $card1 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+ $card2 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $this->assertTrue($card1->isDefault());
+ $this->assertFalse($card2->isDefault());
+
+ Braintree_CreditCard::update($card2->token, array(
+ 'options' => array('makeDefault' => true)
+ ))->creditCard;
+
+ $this->assertFalse(Braintree_CreditCard::find($card1->token)->isDefault());
+ $this->assertTrue(Braintree_CreditCard::find($card2->token)->isDefault());
+ }
+
+ function testDelete_deletesThePaymentMethod()
+ {
+ $customer = Braintree_Customer::createNoValidate(array());
+ $creditCard = Braintree_CreditCard::createNoValidate(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ Braintree_CreditCard::find($creditCard->token);
+ Braintree_CreditCard::delete($creditCard->token);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_CreditCard::find($creditCard->token);
+ }
+
+ function testGatewayRejectionOnCVV()
+ {
+ $old_merchant_id = Braintree_Configuration::merchantId();
+ $old_public_key = Braintree_Configuration::publicKey();
+ $old_private_key = Braintree_Configuration::privateKey();
+
+ Braintree_Configuration::merchantId('processing_rules_merchant_id');
+ Braintree_Configuration::publicKey('processing_rules_public_key');
+ Braintree_Configuration::privateKey('processing_rules_private_key');
+
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/2011',
+ 'cvv' => '200',
+ 'options' => array('verifyCard' => true)
+ ));
+
+ Braintree_Configuration::merchantId($old_merchant_id);
+ Braintree_Configuration::publicKey($old_public_key);
+ Braintree_Configuration::privateKey($old_private_key);
+
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Transaction::CVV, $result->creditCardVerification->gatewayRejectionReason);
+ }
+
+ function testGatewayRejectionIsNullOnProcessorDecline()
+ {
+ $old_merchant_id = Braintree_Configuration::merchantId();
+ $old_public_key = Braintree_Configuration::publicKey();
+ $old_private_key = Braintree_Configuration::privateKey();
+
+ Braintree_Configuration::merchantId('processing_rules_merchant_id');
+ Braintree_Configuration::publicKey('processing_rules_public_key');
+ Braintree_Configuration::privateKey('processing_rules_private_key');
+
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'cvv' => '200',
+ 'options' => array('verifyCard' => true)
+ ));
+
+ Braintree_Configuration::merchantId($old_merchant_id);
+ Braintree_Configuration::publicKey($old_public_key);
+ Braintree_Configuration::privateKey($old_private_key);
+
+ $this->assertFalse($result->success);
+ $this->assertNull($result->creditCardVerification->gatewayRejectionReason);
+ }
+
+ function createCreditCardViaTr($regularParams, $trParams)
+ {
+ $trData = Braintree_TransparentRedirect::createCreditCardData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+ return Braintree_TestHelper::submitTrRequest(
+ Braintree_CreditCard::createCreditCardUrl(),
+ $regularParams,
+ $trData
+ );
+ }
+
+ function updateCreditCardViaTr($regularParams, $trParams)
+ {
+ $trData = Braintree_TransparentRedirect::updateCreditCardData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+ return Braintree_TestHelper::submitTrRequest(
+ Braintree_CreditCard::updateCreditCardUrl(),
+ $regularParams,
+ $trData
+ );
+ }
+
+ function testPrepaidCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::PREPAID,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::PREPAID_YES, $result->creditCard->prepaid);
+ }
+
+ function testCommercialCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::COMMERCIAL,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::COMMERCIAL_YES, $result->creditCard->commercial);
+ }
+
+ function testDebitCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::DEBIT,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::DEBIT_YES, $result->creditCard->debit);
+ }
+
+ function testPayrollCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::PAYROLL,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::PAYROLL_YES, $result->creditCard->payroll);
+ }
+
+ function testHealthCareCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::HEALTHCARE,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::HEALTHCARE_YES, $result->creditCard->healthcare);
+ }
+
+ function testDurbinRegulatedCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::DURBIN_REGULATED,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::DURBIN_REGULATED_YES, $result->creditCard->durbinRegulated);
+ }
+
+ function testCountryOfIssuanceCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::COUNTRY_OF_ISSUANCE,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals("USA", $result->creditCard->countryOfIssuance);
+ }
+
+ function testIssuingBankCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::ISSUING_BANK,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals("NETWORK ONLY", $result->creditCard->issuingBank);
+ }
+
+ function testNegativeCardTypeIndicators()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::NO,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::PREPAID_NO, $result->creditCard->prepaid);
+ $this->assertEquals(Braintree_CreditCard::DURBIN_REGULATED_NO, $result->creditCard->durbinRegulated);
+ $this->assertEquals(Braintree_CreditCard::PAYROLL_NO, $result->creditCard->payroll);
+ $this->assertEquals(Braintree_CreditCard::DEBIT_NO, $result->creditCard->debit);
+ $this->assertEquals(Braintree_CreditCard::HEALTHCARE_NO, $result->creditCard->healthcare);
+ $this->assertEquals(Braintree_CreditCard::COMMERCIAL_NO, $result->creditCard->commercial);
+ }
+
+ function testUnknownCardTypeIndicators()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::UNKNOWN,
+ 'expirationDate' => '05/12',
+ 'options' => array('verifyCard' => true)
+ ));
+ $this->assertEquals(Braintree_CreditCard::PREPAID_UNKNOWN, $result->creditCard->prepaid);
+ $this->assertEquals(Braintree_CreditCard::DURBIN_REGULATED_UNKNOWN, $result->creditCard->durbinRegulated);
+ $this->assertEquals(Braintree_CreditCard::PAYROLL_UNKNOWN, $result->creditCard->payroll);
+ $this->assertEquals(Braintree_CreditCard::DEBIT_UNKNOWN, $result->creditCard->debit);
+ $this->assertEquals(Braintree_CreditCard::HEALTHCARE_UNKNOWN, $result->creditCard->healthcare);
+ $this->assertEquals(Braintree_CreditCard::COMMERCIAL_UNKNOWN, $result->creditCard->commercial);
+ $this->assertEquals(Braintree_CreditCard::COUNTRY_OF_ISSUANCE_UNKNOWN, $result->creditCard->countryOfIssuance);
+ $this->assertEquals(Braintree_CreditCard::ISSUING_BANK_UNKNOWN, $result->creditCard->issuingBank);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardVerificationAdvancedSearchTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardVerificationAdvancedSearchTest.php
new file mode 100644
index 0000000..1505386
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CreditCardVerificationAdvancedSearchTest.php
@@ -0,0 +1,253 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_CreditCardVerificationAdvancedSearchTest extends PHPUnit_Framework_TestCase
+{
+ function test_searchOnTextFields()
+ {
+ $searchCriteria = array(
+ 'creditCardCardholderName' => 'Tim Toole',
+ 'creditCardExpirationDate' => '05/2010',
+ 'creditCardNumber' => Braintree_Test_CreditCardNumbers::$failsSandboxVerification['Visa'],
+ 'billingAddressDetailsPostalCode' => '90210',
+ );
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'cardholderName' => $searchCriteria['creditCardCardholderName'],
+ 'number' => $searchCriteria['creditCardNumber'],
+ 'expirationDate' => $searchCriteria['creditCardExpirationDate'],
+ 'billingAddress' => array(
+ 'postalCode' => $searchCriteria['billingAddressDetailsPostalCode']
+ ),
+ 'options' => array('verifyCard' => true),
+ ),
+ ));
+ $verification = $result->creditCardVerification;
+
+ $query = array(Braintree_CreditCardVerificationSearch::id()->is($verification->id));
+ foreach ($searchCriteria AS $criterion => $value) {
+ $query[] = Braintree_CreditCardVerificationSearch::$criterion()->is($value);
+ }
+
+ $collection = Braintree_CreditCardVerification::search($query);
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($result->creditCardVerification->id, $collection->firstItem()->id);
+
+ foreach ($searchCriteria AS $criterion => $value) {
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::$criterion()->is($value),
+ Braintree_CreditCardVerificationSearch::id()->is($result->creditCardVerification->id)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($result->creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::$criterion()->is('invalid_attribute'),
+ Braintree_CreditCardVerificationSearch::id()->is($result->creditCardVerification->id)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+ }
+
+ function test_searchOnSuccessfulCustomerAndPaymentFields()
+ {
+ $customerId = uniqid();
+ $searchCriteria = array(
+ 'customerId' => $customerId,
+ 'customerEmail' => $customerId . 'sandworm@example.com',
+ 'paymentMethodToken' => $customerId . 'token',
+ );
+ $result = Braintree_Customer::create(array(
+ 'id' => $customerId,
+ 'email' => $searchCriteria['customerEmail'],
+ 'creditCard' => array(
+ 'token' => $searchCriteria['paymentMethodToken'],
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2017',
+ 'options' => array('verifyCard' => true)
+ )
+ ));
+ $customer = $result->customer;
+
+ $query = array();
+ foreach ($searchCriteria AS $criterion => $value) {
+ $query[] = Braintree_CreditCardVerificationSearch::$criterion()->is($value);
+ }
+
+ $collection = Braintree_CreditCardVerification::search($query);
+ $this->assertEquals(1, $collection->maximumCount());
+
+ foreach ($searchCriteria AS $criterion => $value) {
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::$criterion()->is($value),
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::$criterion()->is('invalid_attribute'),
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+ }
+
+ function testGateway_searchEmpty()
+ {
+ $query = array();
+ $query[] = Braintree_CreditCardVerificationSearch::creditCardCardholderName()->is('Not Found');
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $collection = $gateway->creditCardVerification()->search($query);
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_createdAt()
+ {
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'cardholderName' => 'Joe Smith',
+ 'number' => '4000111111111115',
+ 'expirationDate' => '12/2016',
+ 'options' => array('verifyCard' => true),
+ ),
+ ));
+
+ $verification = $result->creditCardVerification;
+
+ $past = clone $verification->createdAt;
+ $past->modify('-1 hour');
+ $future = clone $verification->createdAt;
+ $future->modify('+1 hour');
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($verification->id),
+ Braintree_CreditCardVerificationSearch::createdAt()->between($past, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($verification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($verification->id),
+ Braintree_CreditCardVerificationSearch::createdAt()->lessThanOrEqualTo($future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($verification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($verification->id),
+ Braintree_CreditCardVerificationSearch::createdAt()->greaterThanOrEqualTo($past)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($verification->id, $collection->firstItem()->id);
+ }
+
+ function test_multipleValueNode_ids()
+ {
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'cardholderName' => 'Joe Smith',
+ 'number' => '4000111111111115',
+ 'expirationDate' => '12/2016',
+ 'options' => array('verifyCard' => true),
+ ),
+ ));
+
+ $creditCardVerification = $result->creditCardVerification;
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::ids()->is($creditCardVerification->id)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::ids()->in(
+ array($creditCardVerification->id,'1234')
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::ids()->is('1234')
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_creditCardType()
+ {
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'cardholderName' => 'Joe Smith',
+ 'number' => '4000111111111115',
+ 'expirationDate' => '12/2016',
+ 'options' => array('verifyCard' => true),
+ ),
+ ));
+
+ $creditCardVerification = $result->creditCardVerification;
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($creditCardVerification->id),
+ Braintree_CreditCardVerificationSearch::creditCardCardType()->is($creditCardVerification->creditCard['cardType'])
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($creditCardVerification->id),
+ Braintree_CreditCardVerificationSearch::creditCardCardType()->in(
+ array($creditCardVerification->creditCard['cardType'], Braintree_CreditCard::CHINA_UNION_PAY)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($creditCardVerification->id),
+ Braintree_CreditCardVerificationSearch::creditCardCardType()->is(Braintree_CreditCard::CHINA_UNION_PAY)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_status()
+ {
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'cardholderName' => 'Joe Smith',
+ 'number' => '4000111111111115',
+ 'expirationDate' => '12/2016',
+ 'options' => array('verifyCard' => true),
+ ),
+ ));
+
+ $creditCardVerification = $result->creditCardVerification;
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($creditCardVerification->id),
+ Braintree_CreditCardVerificationSearch::status()->is($creditCardVerification->status)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($creditCardVerification->id),
+ Braintree_CreditCardVerificationSearch::status()->in(
+ array($creditCardVerification->status, Braintree_Result_creditCardVerification::VERIFIED)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($creditCardVerification->id, $collection->firstItem()->id);
+
+ $collection = Braintree_CreditCardVerification::search(array(
+ Braintree_CreditCardVerificationSearch::id()->is($creditCardVerification->id),
+ Braintree_CreditCardVerificationSearch::status()->is(Braintree_Result_creditCardVerification::VERIFIED)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerAdvancedSearchTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerAdvancedSearchTest.php
new file mode 100644
index 0000000..77b090e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerAdvancedSearchTest.php
@@ -0,0 +1,195 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_CustomerAdvancedSearchTest extends PHPUnit_Framework_TestCase
+{
+ function test_noMatches()
+ {
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::company()->is('badname')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_noRequestsWhenIterating()
+ {
+ $resultsReturned = false;
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::firstName()->is('badname')
+ ));
+
+ foreach($collection as $customer) {
+ $resultsReturned = true;
+ break;
+ }
+
+ $this->assertSame(0, $collection->maximumCount());
+ $this->assertEquals(false, $resultsReturned);
+ }
+
+ function test_findDuplicateCardsGivenPaymentMethodToken()
+ {
+ $creditCardRequest = array('number' => '63049580000009', 'expirationDate' => '05/2012');
+
+ $jim = Braintree_Customer::create(array('firstName' => 'Jim', 'creditCard' => $creditCardRequest))->customer;
+ $joe = Braintree_Customer::create(array('firstName' => 'Joe', 'creditCard' => $creditCardRequest))->customer;
+
+ $query = array(Braintree_CustomerSearch::paymentMethodTokenWithDuplicates()->is($jim->creditCards[0]->token));
+ $collection = Braintree_Customer::search($query);
+
+ $customerIds = array();
+ foreach($collection as $customer)
+ {
+ $customerIds[] = $customer->id;
+ }
+
+ $this->assertTrue(in_array($jim->id, $customerIds));
+ $this->assertTrue(in_array($joe->id, $customerIds));
+ }
+
+ function test_searchOnTextFields()
+ {
+ $token = 'cctoken' . rand();
+
+ $search_criteria = array(
+ 'firstName' => 'Timmy',
+ 'lastName' => 'OToole',
+ 'company' => 'OToole and Son(s)' . rand(),
+ 'email' => 'timmy@example.com',
+ 'website' => 'http://example.com',
+ 'phone' => '3145551234',
+ 'fax' => '3145551235',
+ 'cardholderName' => 'Tim Toole',
+ 'creditCardExpirationDate' => '05/2010',
+ 'creditCardNumber' => '4111111111111111',
+ 'paymentMethodToken' => $token,
+ 'addressFirstName' => 'Thomas',
+ 'addressLastName' => 'Otool',
+ 'addressStreetAddress' => '1 E Main St',
+ 'addressExtendedAddress' => 'Suite 3',
+ 'addressLocality' => 'Chicago',
+ 'addressRegion' => 'Illinois',
+ 'addressPostalCode' => '60622',
+ 'addressCountryName' => 'United States of America'
+ );
+
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'firstName' => $search_criteria['firstName'],
+ 'lastName' => $search_criteria['lastName'],
+ 'company' => $search_criteria['company'],
+ 'email' => $search_criteria['email'],
+ 'fax' => $search_criteria['fax'],
+ 'phone' => $search_criteria['phone'],
+ 'website' => $search_criteria['website'],
+ 'creditCard' => array(
+ 'cardholderName' => 'Tim Toole',
+ 'number' => '4111111111111111',
+ 'expirationDate' => $search_criteria['creditCardExpirationDate'],
+ 'token' => $token,
+ 'billingAddress' => array(
+ 'firstName' => $search_criteria['addressFirstName'],
+ 'lastName' => $search_criteria['addressLastName'],
+ 'streetAddress' => $search_criteria['addressStreetAddress'],
+ 'extendedAddress' => $search_criteria['addressExtendedAddress'],
+ 'locality' => $search_criteria['addressLocality'],
+ 'region' => $search_criteria['addressRegion'],
+ 'postalCode' => $search_criteria['addressPostalCode'],
+ 'countryName' => 'United States of America'
+ )
+ )
+ ));
+
+ $query = array(Braintree_CustomerSearch::id()->is($customer->id));
+ foreach ($search_criteria AS $criterion => $value) {
+ $query[] = Braintree_CustomerSearch::$criterion()->is($value);
+ }
+
+ $collection = Braintree_Customer::search($query);
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($customer->id, $collection->firstItem()->id);
+
+ foreach ($search_criteria AS $criterion => $value) {
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::$criterion()->is($value),
+ Braintree_CustomerSearch::id()->is($customer->id)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($customer->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::$criterion()->is('invalid_attribute'),
+ Braintree_CustomerSearch::id()->is($customer->id)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+ }
+
+ function test_createdAt()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $past = clone $customer->createdAt;
+ $past->modify("-1 hour");
+ $future = clone $customer->createdAt;
+ $future->modify("+1 hour");
+
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::id()->is($customer->id),
+ Braintree_CustomerSearch::createdAt()->between($past, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($customer->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::id()->is($customer->id),
+ Braintree_CustomerSearch::createdAt()->lessThanOrEqualTo($future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($customer->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::id()->is($customer->id),
+ Braintree_CustomerSearch::createdAt()->greaterThanOrEqualTo($past)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($customer->id, $collection->firstItem()->id);
+ }
+
+ function test_paypalAccountEmail()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ )
+ ));
+
+ $customerId = 'UNIQUE_CUSTOMER_ID-' . strval(rand());
+ $customerResult = Braintree_Customer::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'id' => $customerId
+ ));
+
+ $this->assertTrue($customerResult->success);
+
+ $customer = $customerResult->customer;
+
+ $collection = Braintree_Customer::search(array(
+ Braintree_CustomerSearch::id()->is($customer->id),
+ Braintree_CustomerSearch::paypalAccountEmail()->is('jane.doe@example.com')
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($customer->id, $collection->firstItem()->id);
+ }
+
+ function test_throwsIfNoOperatorNodeGiven()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Operator must be provided');
+ Braintree_Customer::search(array(
+ Braintree_CustomerSearch::creditCardExpirationDate()
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerTest.php
new file mode 100644
index 0000000..d997c62
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/CustomerTest.php
@@ -0,0 +1,1190 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_CustomerTest extends PHPUnit_Framework_TestCase
+{
+ function testAll_smokeTest()
+ {
+ $all = Braintree_Customer::all();
+ $this->assertTrue($all->maximumCount() > 0);
+ }
+
+ function testAllWithManyResults()
+ {
+ $collection = Braintree_Customer::all();
+ $this->assertTrue($collection->maximumCount() > 1);
+ $customer = $collection->firstItem();
+ $this->assertTrue(intval($customer->id) > 0);
+ $this->assertTrue($customer instanceof Braintree_Customer);
+ }
+
+ function testCreate()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com'
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('Mike', $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertEquals('Jones Co.', $customer->company);
+ $this->assertEquals('mike.jones@example.com', $customer->email);
+ $this->assertEquals('419.555.1234', $customer->phone);
+ $this->assertEquals('419.555.1235', $customer->fax);
+ $this->assertEquals('http://example.com', $customer->website);
+ $this->assertNotNull($customer->merchantId);
+ }
+
+ function testGatewayCreate()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->customer()->create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('Mike', $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertNotNull($customer->merchantId);
+ }
+
+ function testCreateWithAccessToken()
+ {
+ $credentials = Braintree_OAuthTestHelper::createCredentials(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ 'merchantId' => 'integration_merchant_id',
+ ));
+
+ $gateway = new Braintree_Gateway(array(
+ 'accessToken' => $credentials->accessToken,
+ ));
+
+ $result = $gateway->customer()->create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('Mike', $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertNotNull($customer->merchantId);
+ }
+
+ function testCreateCustomerWithCardUsingNonce()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "share" => true
+ ));
+
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'paymentMethodNonce' => $nonce
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertSame("411111", $result->customer->creditCards[0]->bin);
+ $this->assertSame("1111", $result->customer->creditCards[0]->last4);
+ }
+
+ function testCreateCustomerWithApplePayCard()
+ {
+ $nonce = Braintree_Test_Nonces::$applePayVisa;
+ $result = Braintree_Customer::create(array(
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->assertTrue($result->success);
+ $customer = $result->customer;
+ $this->assertNotNull($customer->applePayCards[0]);
+ $this->assertNotNull($customer->paymentMethods[0]);
+ }
+
+ function testCreateCustomerWithAndroidPayCard()
+ {
+ $nonce = Braintree_Test_Nonces::$androidPay;
+ $result = Braintree_Customer::create(array(
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->assertTrue($result->success);
+ $customer = $result->customer;
+ $this->assertNotNull($customer->androidPayCards[0]);
+ $this->assertNotNull($customer->paymentMethods[0]);
+ $androidPayCard = $customer->androidPayCards[0];
+ $this->assertTrue($androidPayCard instanceof Braintree_AndroidPayCard);
+ $this->assertNotNull($androidPayCard->token);
+ $this->assertNotNull($androidPayCard->expirationYear);
+ }
+
+ function testCreateCustomerWithCoinbase()
+ {
+ $nonce = Braintree_Test_Nonces::$coinbase;
+ $result = Braintree_Customer::create(array(
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->assertTrue($result->success);
+ $customer = $result->customer;
+ $this->assertNotNull($customer->coinbaseAccounts[0]);
+ $this->assertNotNull($customer->coinbaseAccounts[0]->userId);
+ $this->assertNotNull($customer->coinbaseAccounts[0]->userName);
+ $this->assertNotNull($customer->coinbaseAccounts[0]->userEmail);
+ $this->assertNotNull($customer->paymentMethods[0]);
+ }
+
+
+ function testCreate_withUnicode()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => "Здравствуйте",
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com'
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals("Здравствуйте", $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertEquals('Jones Co.', $customer->company);
+ $this->assertEquals('mike.jones@example.com', $customer->email);
+ $this->assertEquals('419.555.1234', $customer->phone);
+ $this->assertEquals('419.555.1235', $customer->fax);
+ $this->assertEquals('http://example.com', $customer->website);
+ $this->assertNotNull($customer->merchantId);
+ }
+
+ function testCreate_withCountry()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Bat',
+ 'lastName' => 'Manderson',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'countryName' => 'Gabon',
+ 'countryCodeAlpha2' => 'GA',
+ 'countryCodeAlpha3' => 'GAB',
+ 'countryCodeNumeric' => '266'
+ )
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('Gabon', $customer->creditCards[0]->billingAddress->countryName);
+ $this->assertEquals('GA', $customer->creditCards[0]->billingAddress->countryCodeAlpha2);
+ $this->assertEquals('GAB', $customer->creditCards[0]->billingAddress->countryCodeAlpha3);
+ $this->assertEquals('266', $customer->creditCards[0]->billingAddress->countryCodeNumeric);
+ $this->assertEquals(1, preg_match('/\A\w{32}\z/', $customer->creditCards[0]->uniqueNumberIdentifier));
+ }
+
+ function testCreate_withVenmoSdkSession()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Bat',
+ 'lastName' => 'Manderson',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'options' => array(
+ 'venmoSdkSession' => Braintree_Test_VenmoSdk::getTestSession()
+ )
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals(true, $customer->creditCards[0]->venmoSdk);
+ }
+
+ function testCreate_withVenmoSdkPaymentMethodCode()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Bat',
+ 'lastName' => 'Manderson',
+ 'creditCard' => array(
+ 'venmoSdkPaymentMethodCode' => Braintree_Test_VenmoSdk::$visaPaymentMethodCode
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals("411111", $customer->creditCards[0]->bin);
+ }
+
+ function testCreate_blankCustomer()
+ {
+ $result = Braintree_Customer::create();
+ $this->assertEquals(true, $result->success);
+ $this->assertNotNull($result->customer->id);
+
+ $result = Braintree_Customer::create(array());
+ $this->assertEquals(true, $result->success);
+ $this->assertNotNull($result->customer->id);
+ }
+
+ function testCreate_withSpecialChars()
+ {
+ $result = Braintree_Customer::create(array('firstName' => '<>&"\''));
+ $this->assertEquals(true, $result->success);
+ $this->assertEquals('<>&"\'', $result->customer->firstName);
+ }
+
+ function testCreate_withCustomFields()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'customFields' => array(
+ 'store_me' => 'some custom value'
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $customFields = $result->customer->customFields;
+ $this->assertEquals('some custom value', $customFields['store_me']);
+ }
+
+ function testCreate_withFraudParams()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '123',
+ 'cardholderName' => 'Mike Jones',
+ 'deviceSessionId' => 'abc123',
+ 'fraudMerchantId' => '456'
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ }
+
+ function testCreate_withCreditCard()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '123',
+ 'cardholderName' => 'Mike Jones'
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('Mike', $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertEquals('Jones Co.', $customer->company);
+ $this->assertEquals('mike.jones@example.com', $customer->email);
+ $this->assertEquals('419.555.1234', $customer->phone);
+ $this->assertEquals('419.555.1235', $customer->fax);
+ $this->assertEquals('http://example.com', $customer->website);
+ $creditCard = $customer->creditCards[0];
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('Mike Jones', $creditCard->cardholderName);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('05', $creditCard->expirationMonth);
+ $this->assertEquals('2012', $creditCard->expirationYear);
+ }
+
+ function testCreate_withDuplicateCardCheck()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $attributes = array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '123',
+ 'cardholderName' => 'Mike Jones',
+ 'options' => array(
+ 'failOnDuplicatePaymentMethod' => true
+ )
+ )
+ );
+ Braintree_Customer::create($attributes);
+ $result = Braintree_Customer::create($attributes);
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('customer')->forKey('creditCard')->onAttribute('number');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_DUPLICATE_CARD_EXISTS, $errors[0]->code);
+ $this->assertEquals(1, preg_match('/Duplicate card exists in the vault\./', $result->message));
+ }
+
+ function testCreate_withCreditCardAndSpecificVerificationMerchantAccount()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '123',
+ 'cardholderName' => 'Mike Jones',
+ 'options' => array(
+ 'verificationMerchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'verifyCard' => true
+ )
+ )
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals('2000', $result->creditCardVerification->processorResponseCode);
+ $this->assertEquals('Do Not Honor', $result->creditCardVerification->processorResponseText);
+ $this->assertEquals('M', $result->creditCardVerification->cvvResponseCode);
+ $this->assertEquals(null, $result->creditCardVerification->avsErrorResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsPostalCodeResponseCode);
+ $this->assertEquals('I', $result->creditCardVerification->avsStreetAddressResponseCode);
+ }
+
+ function testCreate_withCreditCardAndBillingAddress()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '123',
+ 'cardholderName' => 'Mike Jones',
+ 'billingAddress' => array(
+ 'firstName' => 'Drew',
+ 'lastName' => 'Smith',
+ 'company' => 'Smith Co.',
+ 'streetAddress' => '1 E Main St',
+ 'extendedAddress' => 'Suite 101',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'United States of America'
+ )
+ )
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('Mike', $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertEquals('Jones Co.', $customer->company);
+ $this->assertEquals('mike.jones@example.com', $customer->email);
+ $this->assertEquals('419.555.1234', $customer->phone);
+ $this->assertEquals('419.555.1235', $customer->fax);
+ $this->assertEquals('http://example.com', $customer->website);
+ $creditCard = $customer->creditCards[0];
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('Mike Jones', $creditCard->cardholderName);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('05', $creditCard->expirationMonth);
+ $this->assertEquals('2012', $creditCard->expirationYear);
+ $address = $customer->addresses[0];
+ $this->assertEquals($address, $creditCard->billingAddress);
+ $this->assertEquals('Drew', $address->firstName);
+ $this->assertEquals('Smith', $address->lastName);
+ $this->assertEquals('Smith Co.', $address->company);
+ $this->assertEquals('1 E Main St', $address->streetAddress);
+ $this->assertEquals('Suite 101', $address->extendedAddress);
+ $this->assertEquals('Chicago', $address->locality);
+ $this->assertEquals('IL', $address->region);
+ $this->assertEquals('60622', $address->postalCode);
+ $this->assertEquals('United States of America', $address->countryName);
+ }
+
+ function testCreate_withValidationErrors()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => 'invalid',
+ 'billingAddress' => array(
+ 'streetAddress' => str_repeat('x', 256)
+ )
+ )
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->forKey('customer')->onAttribute('email');
+ $this->assertEquals(Braintree_Error_Codes::CUSTOMER_EMAIL_IS_INVALID, $errors[0]->code);
+ $errors = $result->errors->forKey('customer')->forKey('creditCard')->onAttribute('number');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_NUMBER_INVALID_LENGTH, $errors[0]->code);
+ $errors = $result->errors->forKey('customer')->forKey('creditCard')->forKey('billingAddress')->onAttribute('streetAddress');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_STREET_ADDRESS_IS_TOO_LONG, $errors[0]->code);
+ }
+
+ function testCreate_countryValidations_inconsistency()
+ {
+ $result = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'billingAddress' => array(
+ 'countryName' => 'Georgia',
+ 'countryCodeAlpha2' => 'TF'
+ )
+ )
+ ));
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->forKey('customer')->forKey('creditCard')->forKey('billingAddress')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_INCONSISTENT_COUNTRY, $errors[0]->code);
+ }
+
+ function testCreateNoValidate_returnsCustomer()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'firstName' => 'Paul',
+ 'lastName' => 'Martin'
+ ));
+ $this->assertEquals('Paul', $customer->firstName);
+ $this->assertEquals('Martin', $customer->lastName);
+ }
+
+ function testCreateNoValidate_throwsIfInvalid()
+ {
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ $customer = Braintree_Customer::createNoValidate(array('email' => 'invalid'));
+ }
+
+ function testCreate_worksWithFuturePayPalNonce()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalFuturePayment;
+
+ $result = Braintree_Customer::create(array(
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+ }
+
+ function testCreate_doesNotWorkWithOnetimePayPalNonce()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $result = Braintree_Customer::create(array(
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('customer')->forKey('paypalAccount')->errors;
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_CANNOT_VAULT_ONE_TIME_USE_PAYPAL_ACCOUNT, $errors[0]->code);
+ }
+
+ function testDelete_deletesTheCustomer()
+ {
+ $result = Braintree_Customer::create(array());
+ $this->assertEquals(true, $result->success);
+ Braintree_Customer::find($result->customer->id);
+ Braintree_Customer::delete($result->customer->id);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_Customer::find($result->customer->id);
+ }
+
+ function testFind()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com'
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = Braintree_Customer::find($result->customer->id);
+ $this->assertEquals('Mike', $customer->firstName);
+ $this->assertEquals('Jones', $customer->lastName);
+ $this->assertEquals('Jones Co.', $customer->company);
+ $this->assertEquals('mike.jones@example.com', $customer->email);
+ $this->assertEquals('419.555.1234', $customer->phone);
+ $this->assertEquals('419.555.1235', $customer->fax);
+ $this->assertEquals('http://example.com', $customer->website);
+ }
+
+ function testFind_throwsExceptionIfNotFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_Customer::find("does-not-exist");
+ }
+
+ function testUpdate()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Old First',
+ 'lastName' => 'Old Last',
+ 'company' => 'Old Company',
+ 'email' => 'old.email@example.com',
+ 'phone' => 'old phone',
+ 'fax' => 'old fax',
+ 'website' => 'http://old.example.com'
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $updateResult = Braintree_Customer::update($customer->id, array(
+ 'firstName' => 'New First',
+ 'lastName' => 'New Last',
+ 'company' => 'New Company',
+ 'email' => 'new.email@example.com',
+ 'phone' => 'new phone',
+ 'fax' => 'new fax',
+ 'website' => 'http://new.example.com'
+ ));
+ $this->assertEquals(true, $updateResult->success);
+ $this->assertEquals('New First', $updateResult->customer->firstName);
+ $this->assertEquals('New Last', $updateResult->customer->lastName);
+ $this->assertEquals('New Company', $updateResult->customer->company);
+ $this->assertEquals('new.email@example.com', $updateResult->customer->email);
+ $this->assertEquals('new phone', $updateResult->customer->phone);
+ $this->assertEquals('new fax', $updateResult->customer->fax);
+ $this->assertEquals('http://new.example.com', $updateResult->customer->website);
+ }
+
+ function testUpdate_withCountry()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Bat',
+ 'lastName' => 'Manderson',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'countryName' => 'United States of America',
+ 'countryCodeAlpha2' => 'US',
+ 'countryCodeAlpha3' => 'USA',
+ 'countryCodeNumeric' => '840'
+ )
+ )
+ ))->customer;
+
+ $result = Braintree_Customer::update($customer->id, array(
+ 'firstName' => 'Bat',
+ 'lastName' => 'Manderson',
+ 'creditCard' => array(
+ 'options' => array(
+ 'updateExistingToken' => $customer->creditCards[0]->token
+ ),
+ 'billingAddress' => array(
+ 'countryName' => 'Gabon',
+ 'countryCodeAlpha2' => 'GA',
+ 'countryCodeAlpha3' => 'GAB',
+ 'countryCodeNumeric' => '266',
+ 'options' => array(
+ 'updateExisting' => true
+ )
+ )
+ )
+ ));
+
+ $this->assertEquals(true, $result->success);
+ $updatedCustomer = $result->customer;
+ $this->assertEquals('Gabon', $updatedCustomer->creditCards[0]->billingAddress->countryName);
+ $this->assertEquals('GA', $updatedCustomer->creditCards[0]->billingAddress->countryCodeAlpha2);
+ $this->assertEquals('GAB', $updatedCustomer->creditCards[0]->billingAddress->countryCodeAlpha3);
+ $this->assertEquals('266', $updatedCustomer->creditCards[0]->billingAddress->countryCodeNumeric);
+ }
+
+ function testUpdate_withUpdatingExistingCreditCard()
+ {
+ $create_result = Braintree_Customer::create(array(
+ 'firstName' => 'Old First',
+ 'lastName' => 'Old Last',
+ 'website' => 'http://old.example.com',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cardholderName' => 'Old Cardholder'
+ )
+ ));
+ $this->assertEquals(true, $create_result->success);
+ $customer = $create_result->customer;
+ $creditCard = $customer->creditCards[0];
+ $result = Braintree_Customer::update($customer->id, array(
+ 'firstName' => 'New First',
+ 'lastName' => 'New Last',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '11/14',
+ 'cardholderName' => 'New Cardholder',
+ 'options' => array(
+ 'updateExistingToken' => $creditCard->token
+ )
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $this->assertEquals('New First', $result->customer->firstName);
+ $this->assertEquals('New Last', $result->customer->lastName);
+ $this->assertEquals(1, sizeof($result->customer->creditCards));
+ $creditCard = $result->customer->creditCards[0];
+ $this->assertEquals('411111', $creditCard->bin);
+ $this->assertEquals('11/2014', $creditCard->expirationDate);
+ $this->assertEquals('New Cardholder', $creditCard->cardholderName);
+ }
+
+ function testUpdate_forBillingAddressAndExistingCreditCardAndCustomerDetailsTogether()
+ {
+ $create_result = Braintree_Customer::create(array(
+ 'firstName' => 'Old First',
+ 'lastName' => 'Old Last',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '123',
+ 'cardholderName' => 'Old Cardholder',
+ 'billingAddress' => array(
+ 'firstName' => 'Drew',
+ 'lastName' => 'Smith'
+ )
+ )
+ ));
+ $this->assertEquals(true, $create_result->success);
+ $customer = $create_result->customer;
+ $creditCard = $customer->creditCards[0];
+ $result = Braintree_Customer::update($customer->id, array(
+ 'firstName' => 'New Customer First',
+ 'lastName' => 'New Customer Last',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '11/14',
+ 'options' => array(
+ 'updateExistingToken' => $creditCard->token
+ ),
+ 'billingAddress' => array(
+ 'firstName' => 'New Billing First',
+ 'lastName' => 'New Billing Last',
+ 'options' => array(
+ 'updateExisting' => true
+ )
+ )
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $this->assertEquals('New Customer First', $result->customer->firstName);
+ $this->assertEquals('New Customer Last', $result->customer->lastName);
+ $this->assertEquals(1, sizeof($result->customer->creditCards));
+ $this->assertEquals(1, sizeof($result->customer->addresses));
+
+ $creditCard = $result->customer->creditCards[0];
+ $this->assertEquals('411111', $creditCard->bin);
+ $this->assertEquals('11/2014', $creditCard->expirationDate);
+
+ $billingAddress = $creditCard->billingAddress;
+ $this->assertEquals('New Billing First', $billingAddress->firstName);
+ $this->assertEquals('New Billing Last', $billingAddress->lastName);
+ }
+
+ function testUpdate_withNewCreditCardAndExistingBillingAddress()
+ {
+ $customer = Braintree_Customer::create()->customer;
+ $address = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Dan'
+ ))->address;
+
+ $result = Braintree_Customer::update($customer->id, array(
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '11/14',
+ 'billingAddressId' => $address->id
+ )
+ ));
+
+ $billingAddress = $result->customer->creditCards[0]->billingAddress;
+ $this->assertEquals($address->id, $billingAddress->id);
+ $this->assertEquals('Dan', $billingAddress->firstName);
+ }
+
+ function testUpdate_worksWithFuturePayPalNonce()
+ {
+ $customerResult = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'options' => array(
+ 'makeDefault' => true
+ )
+ )
+ ));
+ $paypalAccountToken = 'PAYPALToken-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paypalAccountToken,
+ 'options' => array(
+ 'makeDefault' => true
+ )
+ )
+ ));
+
+ $result = Braintree_Customer::update($customerResult->customer->id, array(
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertEquals($result->customer->defaultPaymentMethod()->token, $paypalAccountToken);
+
+ }
+
+ function testUpdate_doesNotWorkWithOnetimePayPalNonce()
+ {
+ $customerResult = Braintree_Customer::create(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'options' => array(
+ 'makeDefault' => true
+ )
+ )
+ ));
+ $paypalAccountToken = 'PAYPALToken-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'access_token' => 'PAYPAL_ACCESS_TOKEN',
+ 'token' => $paypalAccountToken,
+ 'options' => array(
+ 'makeDefault' => true
+ )
+ )
+ ));
+
+ $result = Braintree_Customer::update($customerResult->customer->id, array(
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('customer')->forKey('paypalAccount')->errors;
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_CANNOT_VAULT_ONE_TIME_USE_PAYPAL_ACCOUNT, $errors[0]->code);
+
+ }
+
+ function testUpdateNoValidate()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => 'Old First',
+ 'lastName' => 'Old Last',
+ 'company' => 'Old Company',
+ 'email' => 'old.email@example.com',
+ 'phone' => 'old phone',
+ 'fax' => 'old fax',
+ 'website' => 'http://old.example.com'
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $updated = Braintree_Customer::updateNoValidate($customer->id, array(
+ 'firstName' => 'New First',
+ 'lastName' => 'New Last',
+ 'company' => 'New Company',
+ 'email' => 'new.email@example.com',
+ 'phone' => 'new phone',
+ 'fax' => 'new fax',
+ 'website' => 'http://new.example.com'
+ ));
+ $this->assertEquals('New First', $updated->firstName);
+ $this->assertEquals('New Last', $updated->lastName);
+ $this->assertEquals('New Company', $updated->company);
+ $this->assertEquals('new.email@example.com', $updated->email);
+ $this->assertEquals('new phone', $updated->phone);
+ $this->assertEquals('new fax', $updated->fax);
+ $this->assertEquals('http://new.example.com', $updated->website);
+ }
+
+ function testCreateFromTransparentRedirect()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createCustomerViaTr(
+ array(
+ 'customer' => array(
+ 'first_name' => 'Joe',
+ 'last_name' => 'Martin',
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ )
+ )
+ ),
+ array(
+ )
+ );
+ $result = Braintree_Customer::createFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('Joe', $result->customer->firstName);
+ $this->assertEquals('Martin', $result->customer->lastName);
+ $creditCard = $result->customer->creditCards[0];
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ }
+
+ function testCreateFromTransparentRedirect_withParamsInTrData()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createCustomerViaTr(
+ array(
+ ),
+ array(
+ 'customer' => array(
+ 'firstName' => 'Joe',
+ 'lastName' => 'Martin',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ )
+ )
+ );
+ $result = Braintree_Customer::createFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('Joe', $result->customer->firstName);
+ $this->assertEquals('Martin', $result->customer->lastName);
+ $creditCard = $result->customer->creditCards[0];
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ }
+
+ function testCreateFromTransparentRedirect_withValidationErrors()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createCustomerViaTr(
+ array(
+ 'customer' => array(
+ 'first_name' => str_repeat('x', 256),
+ 'credit_card' => array(
+ 'number' => 'invalid',
+ 'expiration_date' => ''
+ )
+ )
+ ),
+ array(
+ )
+ );
+ $result = Braintree_Customer::createFromTransparentRedirect($queryString);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('customer')->onAttribute('firstName');
+ $this->assertEquals(Braintree_Error_Codes::CUSTOMER_FIRST_NAME_IS_TOO_LONG, $errors[0]->code);
+ $errors = $result->errors->forKey('customer')->forKey('creditCard')->onAttribute('number');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_NUMBER_INVALID_LENGTH, $errors[0]->code);
+ $errors = $result->errors->forKey('customer')->forKey('creditCard')->onAttribute('expirationDate');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_EXPIRATION_DATE_IS_REQUIRED, $errors[0]->code);
+ }
+
+ function testCreateWithInvalidUTF8Bytes()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => "Jos\xe8 Maria",
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals("Jos\xc3\xa8 Maria", $customer->firstName);
+ }
+
+ function testCreateWithValidUTF8Bytes()
+ {
+ $result = Braintree_Customer::create(array(
+ 'firstName' => "Jos\303\251",
+ ));
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals("Jos\303\251", $customer->firstName);
+ }
+
+ function testUpdateFromTransparentRedirect()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $customer = Braintree_Customer::createNoValidate();
+ $queryString = $this->updateCustomerViaTr(
+ array(
+ 'customer' => array(
+ 'first_name' => 'Joe',
+ 'last_name' => 'Martin',
+ 'email' => 'joe.martin@example.com'
+ )
+ ),
+ array(
+ 'customerId' => $customer->id
+ )
+ );
+ $result = Braintree_Customer::updateFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('Joe', $result->customer->firstName);
+ $this->assertEquals('Martin', $result->customer->lastName);
+ $this->assertEquals('joe.martin@example.com', $result->customer->email);
+ }
+
+ function testUpdateFromTransparentRedirect_withParamsInTrData()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $customer = Braintree_Customer::createNoValidate();
+ $queryString = $this->updateCustomerViaTr(
+ array(
+ ),
+ array(
+ 'customerId' => $customer->id,
+ 'customer' => array(
+ 'firstName' => 'Joe',
+ 'lastName' => 'Martin',
+ 'email' => 'joe.martin@example.com'
+ )
+ )
+ );
+ $result = Braintree_Customer::updateFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('Joe', $result->customer->firstName);
+ $this->assertEquals('Martin', $result->customer->lastName);
+ $this->assertEquals('joe.martin@example.com', $result->customer->email);
+ }
+
+ function testUpdateFromTransparentRedirect_withValidationErrors()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $customer = Braintree_Customer::createNoValidate();
+ $queryString = $this->updateCustomerViaTr(
+ array(
+ 'customer' => array(
+ 'first_name' => str_repeat('x', 256),
+ )
+ ),
+ array(
+ 'customerId' => $customer->id
+ )
+ );
+ $result = Braintree_Customer::updateFromTransparentRedirect($queryString);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('customer')->onAttribute('firstName');
+ $this->assertEquals(Braintree_Error_Codes::CUSTOMER_FIRST_NAME_IS_TOO_LONG, $errors[0]->code);
+ }
+
+ function testUpdateFromTransparentRedirect_withUpdateExisting()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cardholderName' => 'Mike Jones',
+ 'billingAddress' => array(
+ 'firstName' => 'Drew',
+ 'lastName' => 'Smith'
+ )
+ )
+ ))->customer;
+
+ $queryString = $this->updateCustomerViaTr(
+ array(),
+ array(
+ 'customerId' => $customer->id,
+ 'customer' => array(
+ 'firstName' => 'New First',
+ 'lastName' => 'New Last',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/13',
+ 'cardholderName' => 'New Cardholder',
+ 'options' => array(
+ 'updateExistingToken' => $customer->creditCards[0]->token
+ ),
+ 'billingAddress' => array(
+ 'firstName' => 'New First Billing',
+ 'lastName' => 'New Last Billing',
+ 'options' => array(
+ 'updateExisting' => true
+ )
+ )
+ )
+ )
+ )
+ );
+ $result = Braintree_Customer::updateFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+
+ $this->assertEquals(true, $result->success);
+ $customer = $result->customer;
+ $this->assertEquals('New First', $customer->firstName);
+ $this->assertEquals('New Last', $customer->lastName);
+
+ $this->assertEquals(1, sizeof($result->customer->creditCards));
+ $creditCard = $customer->creditCards[0];
+ $this->assertEquals('411111', $creditCard->bin);
+ $this->assertEquals('1111', $creditCard->last4);
+ $this->assertEquals('New Cardholder', $creditCard->cardholderName);
+ $this->assertEquals('05/2013', $creditCard->expirationDate);
+
+ $this->assertEquals(1, sizeof($result->customer->addresses));
+ $address = $customer->addresses[0];
+ $this->assertEquals($address, $creditCard->billingAddress);
+ $this->assertEquals('New First Billing', $address->firstName);
+ $this->assertEquals('New Last Billing', $address->lastName);
+ }
+
+ function testSale_createsASaleUsingGivenToken()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $result = Braintree_Customer::sale($customer->id, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals($customer->id, $result->transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $result->transaction->creditCardDetails->token);
+ }
+
+ function testSaleNoValidate_createsASaleUsingGivenToken()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $transaction = Braintree_Customer::saleNoValidate($customer->id, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals($customer->id, $transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $transaction->creditCardDetails->token);
+ }
+
+ function testSaleNoValidate_throwsIfInvalid()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_Customer::saleNoValidate($customer->id, array(
+ 'amount' => 'invalid'
+ ));
+ }
+
+ function testCredit_createsACreditUsingGivenCustomerId()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $result = Braintree_Customer::credit($customer->id, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals(Braintree_Transaction::CREDIT, $result->transaction->type);
+ $this->assertEquals($customer->id, $result->transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $result->transaction->creditCardDetails->token);
+ }
+
+ function testCreditNoValidate_createsACreditUsingGivenId()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $transaction = Braintree_Customer::creditNoValidate($customer->id, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals(Braintree_Transaction::CREDIT, $transaction->type);
+ $this->assertEquals($customer->id, $transaction->customerDetails->id);
+ $this->assertEquals($creditCard->token, $transaction->creditCardDetails->token);
+ }
+
+ function testCreditNoValidate_throwsIfInvalid()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $creditCard = $customer->creditCards[0];
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_Customer::creditNoValidate($customer->id, array(
+ 'amount' => 'invalid'
+ ));
+ }
+
+ function createCustomerViaTr($regularParams, $trParams)
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $trData = Braintree_TransparentRedirect::createCustomerData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+ return Braintree_TestHelper::submitTrRequest(
+ Braintree_Customer::createCustomerUrl(),
+ $regularParams,
+ $trData
+ );
+ }
+
+ function updateCustomerViaTr($regularParams, $trParams)
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $trData = Braintree_TransparentRedirect::updateCustomerData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+ return Braintree_TestHelper::submitTrRequest(
+ Braintree_Customer::updateCustomerUrl(),
+ $regularParams,
+ $trData
+ );
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/DisbursementTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/DisbursementTest.php
new file mode 100644
index 0000000..15b7255
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/DisbursementTest.php
@@ -0,0 +1,33 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_DisbursementTest extends PHPUnit_Framework_TestCase
+{
+ function testTransactions()
+ {
+ $disbursement = Braintree_Disbursement::factory(array(
+ "id" => "123456",
+ "merchantAccount" => array(
+ "id" => "sandbox_sub_merchant_account",
+ "masterMerchantAccount" => array(
+ "id" => "sandbox_master_merchant_account",
+ "status" => "active"
+ ),
+ "status" => "active"
+ ),
+ "transactionIds" => array("sub_merchant_transaction"),
+ "exceptionMessage" => "invalid_account_number",
+ "amount" => "100.00",
+ "disbursementDate" => new DateTime("2013-04-10"),
+ "followUpAction" => "update",
+ "retry" => false,
+ "success" => false
+ ));
+
+ $transactions = $disbursement->transactions();
+
+ $this->assertNotNull($transactions);
+ $this->assertEquals(sizeOf($transactions), 1);
+ $this->assertEquals($transactions->firstItem()->id, 'sub_merchant_transaction');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/DiscountTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/DiscountTest.php
new file mode 100644
index 0000000..848ba73
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/DiscountTest.php
@@ -0,0 +1,83 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_DiscountTest extends PHPUnit_Framework_TestCase
+{
+ function testAll_returnsAllDiscounts()
+ {
+ $newId = strval(rand());
+
+ $discountParams = array (
+ "amount" => "100.00",
+ "description" => "some description",
+ "id" => $newId,
+ "kind" => "discount",
+ "name" => "php_discount",
+ "neverExpires" => "false",
+ "numberOfBillingCycles" => "1"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/modifications/create_modification_for_tests";
+ $http->post($path, array("modification" => $discountParams));
+
+ $discounts = Braintree_Discount::all();
+
+ foreach ($discounts as $discount)
+ {
+ if ($discount->id == $newId)
+ {
+ $actualDiscount = $discount;
+ }
+ }
+
+ $this->assertNotNull($actualDiscount);
+ $this->assertEquals($discountParams["amount"], $actualDiscount->amount);
+ $this->assertEquals($discountParams["description"], $actualDiscount->description);
+ $this->assertEquals($discountParams["id"], $actualDiscount->id);
+ $this->assertEquals($discountParams["kind"], $actualDiscount->kind);
+ $this->assertEquals($discountParams["name"], $actualDiscount->name);
+ $this->assertFalse($actualDiscount->neverExpires);
+ $this->assertEquals($discountParams["numberOfBillingCycles"], $actualDiscount->numberOfBillingCycles);
+ }
+
+ function testGatewayAll_returnsAllDiscounts()
+ {
+ $newId = strval(rand());
+
+ $discountParams = array (
+ "amount" => "100.00",
+ "description" => "some description",
+ "id" => $newId,
+ "kind" => "discount",
+ "name" => "php_discount",
+ "neverExpires" => "false",
+ "numberOfBillingCycles" => "1"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/modifications/create_modification_for_tests";
+ $http->post($path, array("modification" => $discountParams));
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $discounts = $gateway->discount()->all();
+
+ foreach ($discounts as $discount)
+ {
+ if ($discount->id == $newId)
+ {
+ $actualDiscount = $discount;
+ }
+ }
+
+ $this->assertNotNull($actualDiscount);
+ $this->assertEquals($discountParams["amount"], $actualDiscount->amount);
+ $this->assertEquals($discountParams["id"], $actualDiscount->id);
+ $this->assertEquals($discountParams["kind"], $actualDiscount->kind);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ErrorCollectionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ErrorCollectionTest.php
new file mode 100644
index 0000000..3a75a05
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ErrorCollectionTest.php
@@ -0,0 +1,75 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../../TestHelper.php';
+
+class Braintree_Error_ErrorCollectionTest extends PHPUnit_Framework_TestCase
+{
+ function testDeepSize_withNestedErrors()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => 'invalid',
+ 'expirationDate' => 'invalid',
+ 'billingAddress' => array(
+ 'countryName' => 'invaild'
+ )
+ )
+ ));
+ $this->assertEquals(false, $result->success);
+ $this->assertEquals(4, $result->errors->deepSize());
+ }
+
+ function testOnHtmlField()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => 'invalid',
+ 'expirationDate' => 'invalid',
+ 'billingAddress' => array(
+ 'countryName' => 'invaild'
+ )
+ )
+ ));
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->onHtmlField('customer[email]');
+ $this->assertEquals(Braintree_Error_Codes::CUSTOMER_EMAIL_IS_INVALID, $errors[0]->code);
+ $errors = $result->errors->onHtmlField('customer[credit_card][number]');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_NUMBER_INVALID_LENGTH, $errors[0]->code);
+ $errors = $result->errors->onHtmlField('customer[credit_card][billing_address][country_name]');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, $errors[0]->code);
+ }
+
+ function testOnHtmlField_returnsEmptyArrayIfNone()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'billingAddress' => array(
+ 'streetAddress' => '1 E Main St'
+ )
+ )
+ ));
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->onHtmlField('customer[email]');
+ $this->assertEquals(Braintree_Error_Codes::CUSTOMER_EMAIL_IS_INVALID, $errors[0]->code);
+ $this->assertEquals(array(), $result->errors->onHtmlField('customer[credit_card][number]'));
+ $this->assertEquals(array(), $result->errors->onHtmlField('customer[credit_card][billing_address][country_name]'));
+ }
+
+ function testOnHtmlField_returnsEmptyForCustomFieldsIfNoErrors()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'customFields' => array('storeMe' => 'value')
+ ));
+ $this->assertEquals(false, $result->success);
+ $this->assertEquals(array(), $result->errors->onHtmlField('customer[custom_fields][store_me]'));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ValidationErrorCollectionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ValidationErrorCollectionTest.php
new file mode 100644
index 0000000..ad9a8ca
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/Error/ValidationErrorCollectionTest.php
@@ -0,0 +1,71 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../../TestHelper.php';
+
+class Braintree_Error_ValidationErrorCollectionTest extends PHPUnit_Framework_TestCase
+{
+
+ function mapValidationErrorsToCodes($validationErrors)
+ {
+ $codes = array_map(create_function('$validationError', 'return $validationError->code;'), $validationErrors);
+ sort($codes);
+ return $codes;
+ }
+
+ function test_shallowAll_givesAllErrorsShallowly()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => '1234123412341234',
+ 'expirationDate' => 'invalid',
+ 'billingAddress' => array(
+ 'countryName' => 'invalid'
+ )
+ )
+ ));
+
+ $this->assertEquals(array(), $result->errors->shallowAll());
+
+ $expectedCustomerErrors = array(Braintree_Error_Codes::CUSTOMER_EMAIL_IS_INVALID);
+ $actualCustomerErrors = $result->errors->forKey('customer')->shallowAll();
+ $this->assertEquals($expectedCustomerErrors, self::mapValidationErrorsToCodes($actualCustomerErrors));
+
+ $expectedCreditCardErrors = array(
+ Braintree_Error_Codes::CREDIT_CARD_EXPIRATION_DATE_IS_INVALID,
+ Braintree_Error_Codes::CREDIT_CARD_NUMBER_IS_INVALID
+ );
+ $actualCreditCardErrors = $result->errors->forKey('customer')->forKey('creditCard')->shallowAll();
+ $this->assertEquals($expectedCreditCardErrors, self::mapValidationErrorsToCodes($actualCreditCardErrors));
+ }
+
+ function test_deepAll_givesAllErrorsDeeply()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid',
+ 'creditCard' => array(
+ 'number' => '1234123412341234',
+ 'expirationDate' => 'invalid',
+ 'billingAddress' => array(
+ 'countryName' => 'invalid'
+ )
+ )
+ ));
+
+ $expectedErrors = array(
+ Braintree_Error_Codes::CUSTOMER_EMAIL_IS_INVALID,
+ Braintree_Error_Codes::CREDIT_CARD_EXPIRATION_DATE_IS_INVALID,
+ Braintree_Error_Codes::CREDIT_CARD_NUMBER_IS_INVALID,
+ Braintree_Error_Codes::ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED
+ );
+ $actualErrors = $result->errors->deepAll();
+ $this->assertEquals($expectedErrors, self::mapValidationErrorsToCodes($actualErrors));
+
+ $expectedErrors = array(
+ Braintree_Error_Codes::CREDIT_CARD_EXPIRATION_DATE_IS_INVALID,
+ Braintree_Error_Codes::CREDIT_CARD_NUMBER_IS_INVALID,
+ Braintree_Error_Codes::ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED
+ );
+ $actualErrors = $result->errors->forKey('customer')->forKey('creditCard')->deepAll();
+ $this->assertEquals($expectedErrors, self::mapValidationErrorsToCodes($actualErrors));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpClientApi.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpClientApi.php
new file mode 100644
index 0000000..95fd22e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpClientApi.php
@@ -0,0 +1,84 @@
+<?php
+
+class Braintree_HttpClientApi extends Braintree_Http
+{
+
+ protected function _doRequest($httpVerb, $path, $requestBody = null)
+ {
+ return $this->_doUrlRequest($httpVerb, $this->_config->baseUrl() . "/merchants/" . $this->_config->merchantId() . $path, $requestBody);
+ }
+
+ public function get($path)
+ {
+ return $this->_doRequest('GET', $path);
+ }
+
+ public function post($path, $body = null)
+ {
+ return $this->_doRequest('POST', $path, $body);
+ }
+
+ public function _doUrlRequest($httpVerb, $url, $requestBody = null)
+ {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_TIMEOUT, 60);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpVerb);
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array(
+ 'Content-Type: application/json',
+ 'X-ApiVersion: ' . Braintree_Configuration::API_VERSION
+ ));
+ curl_setopt($curl, CURLOPT_USERPWD, $this->_config->publicKey() . ':' . $this->_config->privateKey());
+
+ if(!empty($requestBody)) {
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody);
+ }
+
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($curl);
+ $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ curl_close($curl);
+ return array('status' => $httpStatus, 'body' => $response);
+ }
+
+ public function get_cards($options) {
+ $encoded_fingerprint = urlencode($options["authorization_fingerprint"]);
+ $url = "/client_api/v1/payment_methods.json?";
+ $url .= "authorizationFingerprint=" . $encoded_fingerprint;
+ $url .= "&sharedCustomerIdentifier=" . $options["shared_customer_identifier"];
+ $url .= "&sharedCustomerIdentifierType=" . $options["shared_customer_identifier_type"];
+
+ return $this->get($url);
+ }
+
+ public function nonce_for_new_card($options) {
+ $clientTokenOptions = array();
+ if (array_key_exists("customerId", $options)) {
+ $clientTokenOptions["customerId"] = $options["customerId"];
+ unset($options["customerId"]);
+ }
+ $clientToken = json_decode(Braintree_TestHelper::decodedClientToken($clientTokenOptions));
+ $options["authorization_fingerprint"] = $clientToken->authorizationFingerprint;
+ $options["shared_customer_identifier"] = "fake_identifier_" . rand();
+ $options["shared_customer_identifier_type"] = "testing";
+ $response = $this->post('/client_api/v1/payment_methods/credit_cards.json', json_encode($options));
+ if ($response["status"] == 201 || $response["status"] == 202) {
+ $body = json_decode($response["body"]);
+ return $body->creditCards[0]->nonce;
+ } else {
+ throw new Exception(var_dump($response));
+ }
+ }
+
+ public function nonceForPayPalAccount($options) {
+ $clientToken = json_decode(Braintree_TestHelper::decodedClientToken());
+ $options["authorization_fingerprint"] = $clientToken->authorizationFingerprint;
+ $response = $this->post('/client_api/v1/payment_methods/paypal_accounts.json', json_encode($options));
+ if ($response["status"] == 201 || $response["status"] == 202) {
+ $body = json_decode($response["body"], true);
+ return $body["paypalAccounts"][0]["nonce"];
+ } else {
+ throw new Exception(var_dump($response));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpTest.php
new file mode 100644
index 0000000..cdd762e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/HttpTest.php
@@ -0,0 +1,62 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_HttpTest extends PHPUnit_Framework_TestCase
+{
+ function testProductionSSL()
+ {
+ try {
+ Braintree_Configuration::environment('production');
+ $this->setExpectedException('Braintree_Exception_Authentication');
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $http->get('/');
+ } catch (Exception $e) {
+ Braintree_Configuration::environment('development');
+ throw $e;
+ }
+ Braintree_Configuration::environment('development');
+ }
+
+ function testSandboxSSL()
+ {
+ try {
+ Braintree_Configuration::environment('sandbox');
+ $this->setExpectedException('Braintree_Exception_Authentication');
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $http->get('/');
+ } catch (Exception $e) {
+ Braintree_Configuration::environment('development');
+ throw $e;
+ }
+ Braintree_Configuration::environment('development');
+ }
+
+ function testSslError()
+ {
+ try {
+ Braintree_Configuration::environment('sandbox');
+ $this->setExpectedException('Braintree_Exception_SSLCertificate');
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ //ip address of api.braintreegateway.com
+ $http->_doUrlRequest('get', '204.109.13.121');
+ } catch (Exception $e) {
+ Braintree_Configuration::environment('development');
+ throw $e;
+ }
+ Braintree_Configuration::environment('development');
+ }
+
+ function testAuthorizationWithConfig()
+ {
+ $config = new Braintree_Configuration(array(
+ 'environment' => 'development',
+ 'merchant_id' => 'integration_merchant_id',
+ 'publicKey' => 'badPublicKey',
+ 'privateKey' => 'badPrivateKey'
+ ));
+
+ $http = new Braintree_Http($config);
+ $result = $http->_doUrlRequest('GET', $config->baseUrl() . '/merchants/integration_merchant_id/customers');
+ $this->assertEquals(401, $result['status']);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantAccountTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantAccountTest.php
new file mode 100644
index 0000000..e2803c1
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantAccountTest.php
@@ -0,0 +1,419 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_MerchantAccountTest extends PHPUnit_Framework_TestCase
+{
+
+ private static $deprecatedValidParams = array(
+ 'applicantDetails' => array(
+ 'companyName' => "Robot City",
+ 'firstName' => "Joe",
+ 'lastName' => "Bloggs",
+ 'email' => "joe@bloggs.com",
+ 'phone' => "555-555-5555",
+ 'address' => array(
+ 'streetAddress' => "123 Credibility St.",
+ 'postalCode' => "60606",
+ 'locality' => "Chicago",
+ 'region' => "IL",
+ ),
+ 'dateOfBirth' => "10/9/1980",
+ 'ssn' => "123-00-1234",
+ 'taxId' => "123456789",
+ 'routingNumber' => "122100024",
+ 'accountNumber' => "43759348798"
+ ),
+ 'tosAccepted' => true,
+ 'masterMerchantAccountId' => "sandbox_master_merchant_account"
+ );
+
+ private static $validParams = array(
+ 'individual' => array(
+ 'firstName' => "Joe",
+ 'lastName' => "Bloggs",
+ 'email' => "joe@bloggs.com",
+ 'phone' => "555-555-5555",
+ 'address' => array(
+ 'streetAddress' => "123 Credibility St.",
+ 'postalCode' => "60606",
+ 'locality' => "Chicago",
+ 'region' => "IL",
+ ),
+ 'dateOfBirth' => "10/9/1980",
+ 'ssn' => "123-00-1234",
+ ),
+ 'business' => array(
+ 'dbaName' => "Robot City",
+ 'legalName' => "Robot City INC",
+ 'taxId' => "123456789",
+ ),
+ 'funding' => array(
+ 'routingNumber' => "122100024",
+ 'accountNumber' => "43759348798",
+ 'destination' => Braintree_MerchantAccount::FUNDING_DESTINATION_BANK,
+ 'descriptor' => 'Joes Bloggs MI',
+ ),
+ 'tosAccepted' => true,
+ 'masterMerchantAccountId' => "sandbox_master_merchant_account"
+ );
+
+ function testCreate()
+ {
+ $result = Braintree_MerchantAccount::create(self::$validParams);
+ $this->assertEquals(true, $result->success);
+ $merchantAccount = $result->merchantAccount;
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_PENDING, $merchantAccount->status);
+ $this->assertEquals("sandbox_master_merchant_account", $merchantAccount->masterMerchantAccount->id);
+ }
+
+ function testGatewayCreate()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->merchantAccount()->create(self::$validParams);
+ $this->assertEquals(true, $result->success);
+ $merchantAccount = $result->merchantAccount;
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_PENDING, $merchantAccount->status);
+ $this->assertEquals("sandbox_master_merchant_account", $merchantAccount->masterMerchantAccount->id);
+ }
+
+ function testCreateWithDeprecatedParameters()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $result = Braintree_MerchantAccount::create(self::$deprecatedValidParams);
+ $this->assertEquals(true, $result->success);
+ $merchantAccount = $result->merchantAccount;
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_PENDING, $merchantAccount->status);
+ $this->assertEquals("sandbox_master_merchant_account", $merchantAccount->masterMerchantAccount->id);
+ }
+
+ function testCreateWithId()
+ {
+ $rand = rand(1, 1000);
+ $subMerchantAccountId = "sub_merchant_account_id" + $rand;
+ $validParamsWithId = array_merge(array(), self::$validParams);
+ $validParamsWithId['id'] = $subMerchantAccountId;
+ $result = Braintree_MerchantAccount::create($validParamsWithId);
+ $this->assertEquals(true, $result->success);
+ $merchantAccount = $result->merchantAccount;
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_PENDING, $merchantAccount->status);
+ $this->assertEquals("sandbox_master_merchant_account", $merchantAccount->masterMerchantAccount->id);
+ $this->assertEquals("sub_merchant_account_id" + $rand, $merchantAccount->id);
+ }
+
+ function testFailedCreate()
+ {
+ $result = Braintree_MerchantAccount::create(array());
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->forKey('merchantAccount')->onAttribute('masterMerchantAccountId');
+ $this->assertEquals(Braintree_Error_Codes::MERCHANT_ACCOUNT_MASTER_MERCHANT_ACCOUNT_ID_IS_REQUIRED, $errors[0]->code);
+ }
+
+ function testCreateWithFundingDestination()
+ {
+ $params = array_merge(array(), self::$validParams);
+ $params['funding']['destination'] = Braintree_MerchantAccount::FUNDING_DESTINATION_BANK;
+ $result = Braintree_MerchantAccount::create($params);
+ $this->assertEquals(true, $result->success);
+
+ $params = array_merge(array(), self::$validParams);
+ $params['funding']['destination'] = Braintree_MerchantAccount::FUNDING_DESTINATION_EMAIL;
+ $params['funding']['email'] = "billgates@outlook.com";
+ $result = Braintree_MerchantAccount::create($params);
+ $this->assertEquals(true, $result->success);
+
+ $params = array_merge(array(), self::$validParams);
+ $params['funding']['destination'] = Braintree_MerchantAccount::FUNDING_DESTINATION_MOBILE_PHONE;
+ $params['funding']['mobilePhone'] = "1112224444";
+ $result = Braintree_MerchantAccount::create($params);
+ $this->assertEquals(true, $result->success);
+ }
+
+ function testFind()
+ {
+ $params = array_merge(array(), self::$validParams);
+ $result = Braintree_MerchantAccount::create(self::$validParams);
+ $this->assertEquals(true, $result->success);
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_PENDING, $result->merchantAccount->status);
+
+ $id = $result->merchantAccount->id;
+ $merchantAccount = Braintree_MerchantAccount::find($id);
+
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_ACTIVE, $merchantAccount->status);
+ $this->assertEquals($params['individual']['firstName'], $merchantAccount->individualDetails->firstName);
+ $this->assertEquals($params['individual']['lastName'], $merchantAccount->individualDetails->lastName);
+ }
+
+ function testFind_throwsIfNotFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound', 'merchant account with id does-not-exist not found');
+ Braintree_MerchantAccount::find('does-not-exist');
+ }
+
+ function testUpdate()
+ {
+ $params = array_merge(array(), self::$validParams);
+ unset($params["tosAccepted"]);
+ unset($params["masterMerchantAccountId"]);
+ $params["individual"]["firstName"] = "John";
+ $params["individual"]["lastName"] = "Doe";
+ $params["individual"]["email"] = "john.doe@example.com";
+ $params["individual"]["dateOfBirth"] = "1970-01-01";
+ $params["individual"]["phone"] = "3125551234";
+ $params["individual"]["address"]["streetAddress"] = "123 Fake St";
+ $params["individual"]["address"]["locality"] = "Chicago";
+ $params["individual"]["address"]["region"] = "IL";
+ $params["individual"]["address"]["postalCode"] = "60622";
+ $params["business"]["dbaName"] = "James's Bloggs";
+ $params["business"]["legalName"] = "James's Bloggs Inc";
+ $params["business"]["taxId"] = "123456789";
+ $params["business"]["address"]["streetAddress"] = "999 Fake St";
+ $params["business"]["address"]["locality"] = "Miami";
+ $params["business"]["address"]["region"] = "FL";
+ $params["business"]["address"]["postalCode"] = "99999";
+ $params["funding"]["accountNumber"] = "43759348798";
+ $params["funding"]["routingNumber"] = "071000013";
+ $params["funding"]["email"] = "check@this.com";
+ $params["funding"]["mobilePhone"] = "1234567890";
+ $params["funding"]["destination"] = Braintree_MerchantAccount::FUNDING_DESTINATION_BANK;
+ $params["funding"]["descriptor"] = "Joes Bloggs FL";
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(true, $result->success);
+
+ $updatedMerchantAccount = $result->merchantAccount;
+ $this->assertEquals("active", $updatedMerchantAccount->status);
+ $this->assertEquals("sandbox_sub_merchant_account", $updatedMerchantAccount->id);
+ $this->assertEquals("sandbox_master_merchant_account", $updatedMerchantAccount->masterMerchantAccount->id);
+ $this->assertEquals("John", $updatedMerchantAccount->individualDetails->firstName);
+ $this->assertEquals("Doe", $updatedMerchantAccount->individualDetails->lastName);
+ $this->assertEquals("john.doe@example.com", $updatedMerchantAccount->individualDetails->email);
+ $this->assertEquals("1970-01-01", $updatedMerchantAccount->individualDetails->dateOfBirth);
+ $this->assertEquals("3125551234", $updatedMerchantAccount->individualDetails->phone);
+ $this->assertEquals("123 Fake St", $updatedMerchantAccount->individualDetails->addressDetails->streetAddress);
+ $this->assertEquals("Chicago", $updatedMerchantAccount->individualDetails->addressDetails->locality);
+ $this->assertEquals("IL", $updatedMerchantAccount->individualDetails->addressDetails->region);
+ $this->assertEquals("60622", $updatedMerchantAccount->individualDetails->addressDetails->postalCode);
+ $this->assertEquals("James's Bloggs", $updatedMerchantAccount->businessDetails->dbaName);
+ $this->assertEquals("James's Bloggs Inc", $updatedMerchantAccount->businessDetails->legalName);
+ $this->assertEquals("123456789", $updatedMerchantAccount->businessDetails->taxId);
+ $this->assertEquals("999 Fake St", $updatedMerchantAccount->businessDetails->addressDetails->streetAddress);
+ $this->assertEquals("Miami", $updatedMerchantAccount->businessDetails->addressDetails->locality);
+ $this->assertEquals("FL", $updatedMerchantAccount->businessDetails->addressDetails->region);
+ $this->assertEquals("99999", $updatedMerchantAccount->businessDetails->addressDetails->postalCode);
+ $this->assertEquals("8798", $updatedMerchantAccount->fundingDetails->accountNumberLast4);
+ $this->assertEquals("071000013", $updatedMerchantAccount->fundingDetails->routingNumber);
+ $this->assertEquals("check@this.com", $updatedMerchantAccount->fundingDetails->email);
+ $this->assertEquals("1234567890", $updatedMerchantAccount->fundingDetails->mobilePhone);
+ $this->assertEquals(Braintree_MerchantAccount::FUNDING_DESTINATION_BANK, $updatedMerchantAccount->fundingDetails->destination);
+ $this->assertEquals("Joes Bloggs FL", $updatedMerchantAccount->fundingDetails->descriptor);
+ }
+
+ function testUpdateDoesNotRequireAllFields()
+ {
+ $params = array(
+ 'individual' => array(
+ 'firstName' => "Joe"
+ )
+ );
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(true, $result->success);
+ }
+
+ function testUpdateWithBlankFields()
+ {
+ $params = array(
+ 'individual' => array(
+ 'firstName' => "",
+ 'lastName' => "",
+ 'email' => "",
+ 'phone' => "",
+ 'address' => array(
+ 'streetAddress' => "",
+ 'postalCode' => "",
+ 'locality' => "",
+ 'region' => "",
+ ),
+ 'dateOfBirth' => "",
+ 'ssn' => "",
+ ),
+ 'business' => array(
+ 'dbaName' => "",
+ 'legalName' => "",
+ 'taxId' => "",
+ ),
+ 'funding' => array(
+ 'routingNumber' => "",
+ 'accountNumber' => "",
+ 'destination' => "",
+ ),
+ );
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(false, $result->success);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("firstName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_FIRST_NAME_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("lastName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_LAST_NAME_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("dateOfBirth");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_DATE_OF_BIRTH_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("email");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_EMAIL_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("streetAddress");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_STREET_ADDRESS_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("postalCode");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_POSTAL_CODE_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("locality");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_LOCALITY_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("region");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_REGION_IS_REQUIRED);
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("destination");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_DESTINATION_IS_REQUIRED);
+ }
+
+ function testUpdateWithInvalidFields()
+ {
+ $params = array(
+ "individual" => array(
+ "firstName" => "<>",
+ "lastName" => "<>",
+ "email" => "bad",
+ "phone" => "999",
+ "address" => array(
+ "streetAddress" => "nope",
+ "postalCode" => "1",
+ "region" => "QQ",
+ ),
+ "dateOfBirth" => "hah",
+ "ssn" => "12345",
+ ),
+ "business" => array(
+ "legalName" => "``{}",
+ "dbaName" => "{}``",
+ "taxId" => "bad",
+ "address" => array(
+ "streetAddress" => "nope",
+ "postalCode" => "1",
+ "region" => "QQ",
+ ),
+ ),
+ "funding" => array(
+ "destination" => "MY WALLET",
+ "routingNumber" => "LEATHER",
+ "accountNumber" => "BACK POCKET",
+ "email" => "BILLFOLD",
+ "mobilePhone" => "TRIFOLD"
+ ),
+ );
+
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(false, $result->success);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("firstName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_FIRST_NAME_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("lastName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_LAST_NAME_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("email");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_EMAIL_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("phone");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_PHONE_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("streetAddress");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_STREET_ADDRESS_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("postalCode");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_POSTAL_CODE_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->forKey("address")->onAttribute("region");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_ADDRESS_REGION_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("individual")->onAttribute("ssn");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_INDIVIDUAL_SSN_IS_INVALID);
+ ;
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->onAttribute("legalName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_LEGAL_NAME_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->onAttribute("dbaName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_DBA_NAME_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->onAttribute("taxId");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_TAX_ID_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->forKey("address")->onAttribute("streetAddress");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_ADDRESS_STREET_ADDRESS_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->forKey("address")->onAttribute("postalCode");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_ADDRESS_POSTAL_CODE_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->forKey("address")->onAttribute("region");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_ADDRESS_REGION_IS_INVALID);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("destination");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_DESTINATION_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("routingNumber");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_ROUTING_NUMBER_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("accountNumber");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_ACCOUNT_NUMBER_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("email");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_EMAIL_IS_INVALID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("mobilePhone");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_MOBILE_PHONE_IS_INVALID);
+ }
+
+ function testUpdateWithInvalidBusinessFields()
+ {
+ $params = array(
+ "business" => array(
+ "legalName" => "",
+ "taxId" => "111223333",
+ )
+ );
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(false, $result->success);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->onAttribute("legalName");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_LEGAL_NAME_IS_REQUIRED_WITH_TAX_ID);
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->onAttribute("taxId");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_TAX_ID_MUST_BE_BLANK);
+
+ $params = array(
+ "business" => array(
+ "legalName" => "legal name",
+ "taxId" => "",
+ )
+ );
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(false, $result->success);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("business")->onAttribute("taxId");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_BUSINESS_TAX_ID_IS_REQUIRED_WITH_LEGAL_NAME);
+ }
+
+ function testUpdateWithInvalidFundingFields()
+ {
+ $params = array(
+ "funding" => array(
+ "destination" => Braintree_MerchantAccount::FUNDING_DESTINATION_EMAIL,
+ "email" => "",
+ )
+ );
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(false, $result->success);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("email");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_EMAIL_IS_REQUIRED);
+
+ $params = array(
+ "funding" => array(
+ "destination" => Braintree_MerchantAccount::FUNDING_DESTINATION_MOBILE_PHONE,
+ "mobilePhone" => "",
+ )
+ );
+
+ $result = Braintree_MerchantAccount::update("sandbox_sub_merchant_account", $params);
+ $this->assertEquals(false, $result->success);
+
+ $error = $result->errors->forKey("merchantAccount")->forKey("funding")->onAttribute("mobilePhone");
+ $this->assertEquals($error[0]->code, Braintree_Error_Codes::MERCHANT_ACCOUNT_FUNDING_MOBILE_PHONE_IS_REQUIRED);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantTest.php
new file mode 100644
index 0000000..71082ea
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/MerchantTest.php
@@ -0,0 +1,56 @@
+<?php
+require_once __DIR__ . '/../TestHelper.php';
+
+class Braintree_MerchantTest extends PHPUnit_Framework_TestCase
+{
+ function testCreateMerchant()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ ));
+ $result = $gateway->merchant()->create(array(
+ 'email' => 'name@email.com',
+ 'countryCodeAlpha3' => 'USA',
+ 'paymentMethods' => ['credit_card', 'paypal'],
+ ));
+
+ $this->assertEquals(true, $result->success);
+ $merchant = $result->merchant;
+ $this->assertNotNull($merchant->id);
+ $credentials = $result->credentials;
+ $this->assertNotNull($credentials->accessToken);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage clientId needs to be passed to Braintree_Gateway.
+ */
+ function testAssertsHasCredentials()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ ));
+ $gateway->merchant()->create(array(
+ 'email' => 'name@email.com',
+ 'countryCodeAlpha3' => 'USA',
+ ));
+ }
+
+ function testBadPaymentMethods()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ ));
+ $result = $gateway->merchant()->create(array(
+ 'email' => 'name@email.com',
+ 'countryCodeAlpha3' => 'USA',
+ 'paymentMethods' => ['fake_money'],
+ ));
+
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->forKey('merchant')->onAttribute('paymentMethods');
+ $this->assertEquals(Braintree_Error_Codes::MERCHANT_ACCOUNT_PAYMENT_METHODS_ARE_INVALID, $errors[0]->code);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/MultipleValueNodeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/MultipleValueNodeTest.php
new file mode 100644
index 0000000..2b5385c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/MultipleValueNodeTest.php
@@ -0,0 +1,89 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/SubscriptionTestHelper.php';
+
+class Braintree_MultipleValueNodeTest extends PHPUnit_Framework_TestCase
+{
+ function testIn_singleValue()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $activeSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '3'
+ ))->subscription;
+
+ $canceledSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '3'
+ ))->subscription;
+ Braintree_Subscription::cancel($canceledSubscription->id);
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::status()->in(array(Braintree_Subscription::ACTIVE)),
+ Braintree_SubscriptionSearch::price()->is('3')
+ ));
+ foreach ($collection AS $item) {
+ $this->assertEquals(Braintree_Subscription::ACTIVE, $item->status);
+ }
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $activeSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $canceledSubscription));
+ }
+
+ function testIs()
+ {
+ $found = false;
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::status()->is(Braintree_Subscription::PAST_DUE)
+ ));
+ foreach ($collection AS $item) {
+ $found = true;
+ $this->assertEquals(Braintree_Subscription::PAST_DUE, $item->status);
+ }
+ $this->assertTrue($found);
+ }
+
+ function testSearch_statusIsExpired()
+ {
+ $found = false;
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::status()->in(array(Braintree_Subscription::EXPIRED))
+ ));
+ foreach ($collection AS $item) {
+ $found = true;
+ $this->assertEquals(Braintree_Subscription::EXPIRED, $item->status);
+ }
+ $this->assertTrue($found);
+ }
+
+ function testIn_multipleValues()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $activeSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '4'
+ ))->subscription;
+
+ $canceledSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '4'
+ ))->subscription;
+ Braintree_Subscription::cancel($canceledSubscription->id);
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::status()->in(array(Braintree_Subscription::ACTIVE, Braintree_Subscription::CANCELED)),
+ Braintree_SubscriptionSearch::price()->is('4')
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $activeSubscription));
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $canceledSubscription));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/OAuthTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/OAuthTest.php
new file mode 100644
index 0000000..cd78582
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/OAuthTest.php
@@ -0,0 +1,278 @@
+<?php
+require_once __DIR__ . '/../TestHelper.php';
+
+class Braintree_OAuthTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage clientSecret needs to be passed to Braintree_Gateway.
+ */
+ public function testAssertsHasCredentials()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id'
+ ));
+ $gateway->oauth()->createTokenFromCode(array(
+ 'code' => 'integration_oauth_auth_code_' . rand(0,299)
+ ));
+ }
+
+ public function testCreateTokenFromCode()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $code = Braintree_OAuthTestHelper::createGrant($gateway, array(
+ 'merchant_public_id' => 'integration_merchant_id',
+ 'scope' => 'read_write'
+ ));
+ $result = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => $code,
+ 'scope' => 'read_write',
+ ));
+
+ $this->assertEquals(true, $result->success);
+ $credentials = $result->credentials;
+ $this->assertNotNull($credentials->accessToken);
+ $this->assertNotNull($credentials->refreshToken);
+ $this->assertEquals('bearer', $credentials->tokenType);
+ $this->assertNotNull($credentials->expiresAt);
+ }
+
+ public function testCreateTokenFromCodeWithMixedCredentials()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ 'accessToken' => 'access_token$development$integration_merchant_id$f9ac33b3dd',
+ ));
+ $code = Braintree_OAuthTestHelper::createGrant($gateway, array(
+ 'merchant_public_id' => 'integration_merchant_id',
+ 'scope' => 'read_write'
+ ));
+ $result = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => $code,
+ 'scope' => 'read_write',
+ ));
+
+ $this->assertEquals(true, $result->success);
+ $credentials = $result->credentials;
+ $this->assertNotNull($credentials->accessToken);
+ $this->assertNotNull($credentials->refreshToken);
+ $this->assertEquals('bearer', $credentials->tokenType);
+ $this->assertNotNull($credentials->expiresAt);
+ }
+
+ public function testCreateTokenFromCode_JsonAPI()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $code = Braintree_OAuthTestHelper::createGrant($gateway, array(
+ 'merchant_public_id' => 'integration_merchant_id',
+ 'scope' => 'read_write'
+ ));
+ $result = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => $code,
+ 'scope' => 'read_write',
+ ));
+
+ $this->assertEquals(true, $result->success);
+ $this->assertNotNull($result->accessToken);
+ $this->assertNotNull($result->refreshToken);
+ $this->assertEquals('bearer', $result->tokenType);
+ $this->assertNotNull($result->expiresAt);
+ }
+
+ public function testCreateTokenFromCode_ValidationErrorTest()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $result = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => 'bad_code',
+ 'scope' => 'read_write',
+ ));
+
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->forKey('credentials')->onAttribute('code');
+ $this->assertEquals(Braintree_Error_Codes::OAUTH_INVALID_GRANT, $errors[0]->code);
+ $this->assertEquals(1, preg_match('/Invalid grant: code not found/', $result->message));
+ }
+
+ public function testCreateTokenFromCode_OldError()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $result = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => 'bad_code',
+ 'scope' => 'read_write',
+ ));
+
+ $this->assertEquals(false, $result->success);
+ $this->assertEquals('invalid_grant', $result->error);
+ $this->assertEquals('code not found', $result->errorDescription);
+ }
+
+ public function testCreateTokenFromRefreshToken()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $code = Braintree_OAuthTestHelper::createGrant($gateway, array(
+ 'merchant_public_id' => 'integration_merchant_id',
+ 'scope' => 'read_write'
+ ));
+ $refreshToken = $gateway->oauth()->createTokenFromCode(array(
+ 'code' => $code,
+ 'scope' => 'read_write',
+ ))->credentials->refreshToken;
+
+ $result = $gateway->oauth()->createTokenFromRefreshToken(array(
+ 'refreshToken' => $refreshToken,
+ 'scope' => 'read_write',
+ ));
+
+ $this->assertEquals(true, $result->success);
+ $credentials = $result->credentials;
+ $this->assertNotNull($credentials->accessToken);
+ $this->assertNotNull($credentials->refreshToken);
+ $this->assertEquals('bearer', $credentials->tokenType);
+ $this->assertNotNull($credentials->expiresAt);
+ }
+
+
+ public function testBuildConnectUrl()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $url = $gateway->oauth()->connectUrl(array(
+ 'merchantId' => 'integration_merchant_id',
+ 'redirectUri' => 'http://bar.example.com',
+ 'scope' => 'read_write',
+ 'state' => 'baz_state',
+ 'user' => array(
+ 'country' => 'USA',
+ 'email' => 'foo@example.com',
+ 'firstName' => 'Bob',
+ 'lastName' => 'Jones',
+ 'phone' => '555-555-5555',
+ 'dobYear' => '1970',
+ 'dobMonth' => '01',
+ 'dobDay' => '01',
+ 'streetAddress' => '222 W Merchandise Mart',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60606',
+ ),
+ 'business' => array(
+ 'name' => '14 Ladders',
+ 'registeredAs' => '14.0 Ladders',
+ 'industry' => 'Ladders',
+ 'description' => 'We sell the best ladders',
+ 'streetAddress' => '111 N Canal',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60606',
+ 'country' => 'USA',
+ 'annualVolumeAmount' => '1000000',
+ 'averageTransactionAmount' => '100',
+ 'maximumTransactionAmount' => '10000',
+ 'shipPhysicalGoods' => true,
+ 'fulfillmentCompletedIn' => 7,
+ 'currency' => 'USD',
+ 'website' => 'http://example.com',
+ ),
+ 'paymentMethods' => ['credit_card'],
+ ));
+
+ $components = parse_url($url);
+ $queryString = $components['query'];
+ parse_str($queryString, $query);
+
+ $this->assertEquals('localhost', $components['host']);
+ $this->assertEquals('/oauth/connect', $components['path']);
+ $this->assertEquals('integration_merchant_id', $query['merchant_id']);
+ $this->assertEquals('client_id$development$integration_client_id', $query['client_id']);
+ $this->assertEquals('http://bar.example.com', $query['redirect_uri']);
+ $this->assertEquals('read_write', $query['scope']);
+ $this->assertEquals('baz_state', $query['state']);
+
+ $this->assertEquals('USA', $query['user']['country']);
+ $this->assertEquals('foo@example.com', $query['user']['email']);
+ $this->assertEquals('Bob', $query['user']['first_name']);
+ $this->assertEquals('Jones', $query['user']['last_name']);
+ $this->assertEquals('555-555-5555', $query['user']['phone']);
+ $this->assertEquals('1970', $query['user']['dob_year']);
+ $this->assertEquals('01', $query['user']['dob_month']);
+ $this->assertEquals('01', $query['user']['dob_day']);
+ $this->assertEquals('222 W Merchandise Mart', $query['user']['street_address']);
+ $this->assertEquals('Chicago', $query['user']['locality']);
+ $this->assertEquals('IL', $query['user']['region']);
+ $this->assertEquals('60606', $query['user']['postal_code']);
+
+ $this->assertEquals('14 Ladders', $query['business']['name']);
+ $this->assertEquals('14.0 Ladders', $query['business']['registered_as']);
+ $this->assertEquals('Ladders', $query['business']['industry']);
+ $this->assertEquals('We sell the best ladders', $query['business']['description']);
+ $this->assertEquals('111 N Canal', $query['business']['street_address']);
+ $this->assertEquals('Chicago', $query['business']['locality']);
+ $this->assertEquals('IL', $query['business']['region']);
+ $this->assertEquals('60606', $query['business']['postal_code']);
+ $this->assertEquals('USA', $query['business']['country']);
+ $this->assertEquals('1000000', $query['business']['annual_volume_amount']);
+ $this->assertEquals('100', $query['business']['average_transaction_amount']);
+ $this->assertEquals('10000', $query['business']['maximum_transaction_amount']);
+ $this->assertEquals(true, $query['business']['ship_physical_goods']);
+ $this->assertEquals(7, $query['business']['fulfillment_completed_in']);
+ $this->assertEquals('USD', $query['business']['currency']);
+ $this->assertEquals('http://example.com', $query['business']['website']);
+
+ $this->assertCount(1, $query['payment_methods']);
+ $this->assertEquals('credit_card', $query['payment_methods'][0]);
+
+ $this->assertEquals(64, strlen($query['signature']));
+ $this->assertEquals('SHA256', $query['algorithm']);
+ }
+
+ public function testBuildConnectUrlWithoutOptionalParams()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $url = $gateway->oauth()->connectUrl();
+
+ $queryString = parse_url($url)['query'];
+ parse_str($queryString, $query);
+
+ $this->assertEquals('client_id$development$integration_client_id', $query['client_id']);
+ $this->assertArrayNotHasKey('merchant_id', $query);
+ $this->assertArrayNotHasKey('redirect_uri', $query);
+ $this->assertArrayNotHasKey('scope', $query);
+ }
+
+ public function testBuildConnectUrlWithPaymentMethods()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ $url = $gateway->oauth()->connectUrl(array(
+ 'paymentMethods' => array('credit_card', 'paypal')
+ ));
+
+ $queryString = parse_url($url)['query'];
+ parse_str($queryString, $query);
+
+ $this->assertEquals(array('credit_card', 'paypal'), $query['payment_methods']);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/PayPalAccountTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PayPalAccountTest.php
new file mode 100644
index 0000000..98df7c7
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PayPalAccountTest.php
@@ -0,0 +1,294 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/SubscriptionTestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_PayPalAccountTest extends PHPUnit_Framework_TestCase
+{
+ function testFind()
+ {
+ $paymentMethodToken = 'PAYPALToken-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $foundPayPalAccount = Braintree_PayPalAccount::find($paymentMethodToken);
+
+ $this->assertSame('jane.doe@example.com', $foundPayPalAccount->email);
+ $this->assertSame($paymentMethodToken, $foundPayPalAccount->token);
+ $this->assertNotNull($foundPayPalAccount->imageUrl);
+ }
+
+ function testGatewayFind()
+ {
+ $paymentMethodToken = 'PAYPALToken-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $foundPayPalAccount = $gateway->paypalAccount()->find($paymentMethodToken);
+
+ $this->assertSame('jane.doe@example.com', $foundPayPalAccount->email);
+ $this->assertSame($paymentMethodToken, $foundPayPalAccount->token);
+ $this->assertNotNull($foundPayPalAccount->imageUrl);
+ }
+
+ function testFind_doesNotReturnIncorrectPaymentMethodType()
+ {
+ $creditCardToken = 'creditCardToken-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'token' => $creditCardToken
+ ));
+ $this->assertTrue($result->success);
+
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PayPalAccount::find($creditCardToken);
+ }
+
+ function test_PayPalAccountExposesTimestamps()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$paypalFuturePayment
+ ));
+ $this->assertTrue($result->success);
+
+ $foundPayPalAccount = Braintree_PayPalAccount::find($result->paymentMethod->token);
+
+ $this->assertNotNull($result->paymentMethod->createdAt);
+ $this->assertNotNull($result->paymentMethod->updatedAt);
+ }
+
+ function testFind_throwsIfCannotBeFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PayPalAccount::find('invalid-token');
+ }
+
+ function testFind_throwsUsefulErrorMessagesWhenEmpty()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'expected paypal account id to be set');
+ Braintree_PayPalAccount::find('');
+ }
+
+ function testFind_throwsUsefulErrorMessagesWhenInvalid()
+ {
+ $this->setExpectedException('InvalidArgumentException', '@ is an invalid paypal account token');
+ Braintree_PayPalAccount::find('@');
+ }
+
+ function testFind_returnsSubscriptionsAssociatedWithAPaypalAccount()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $paymentMethodToken = 'paypal-account-' . strval(rand());
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'consent-code',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id
+ ));
+ $this->assertTrue($result->success);
+
+ $token = $result->paymentMethod->token;
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $subscription1 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $token,
+ 'planId' => $triallessPlan['id']
+ ))->subscription;
+
+ $subscription2 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $token,
+ 'planId' => $triallessPlan['id']
+ ))->subscription;
+
+ $paypalAccount = Braintree_PayPalAccount::find($token);
+ $getIds = function($sub) { return $sub->id; };
+ $subIds = array_map($getIds, $paypalAccount->subscriptions);
+ $this->assertTrue(in_array($subscription1->id, $subIds));
+ $this->assertTrue(in_array($subscription2->id, $subIds));
+ }
+
+ function testUpdate()
+ {
+ $originalToken = 'ORIGINAL_PAYPALToken-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $originalToken
+ )
+ ));
+
+ $createResult = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->assertTrue($createResult->success);
+
+ $newToken = 'NEW_PAYPALToken-' . strval(rand());
+ $updateResult = Braintree_PayPalAccount::update($originalToken, array(
+ 'token' => $newToken
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $this->assertEquals($newToken, $updateResult->paypalAccount->token);
+
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PayPalAccount::find($originalToken);
+
+ }
+
+ function testUpdateAndMakeDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ));
+ $this->assertTrue($creditCardResult->success);
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE'
+ )
+ ));
+
+ $createResult = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->assertTrue($createResult->success);
+
+ $updateResult = Braintree_PayPalAccount::update($createResult->paymentMethod->token, array(
+ 'options' => array('makeDefault' => true)
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $this->assertTrue($updateResult->paypalAccount->isDefault());
+ }
+
+ function testUpdate_handleErrors()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $firstToken = 'FIRST_PAYPALToken-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $firstNonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $firstToken
+ )
+ ));
+ $firstPaypalAccount = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $firstNonce
+ ));
+ $this->assertTrue($firstPaypalAccount->success);
+
+ $secondToken = 'SECOND_PAYPALToken-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $secondNonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $secondToken
+ )
+ ));
+ $secondPaypalAccount = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $secondNonce
+ ));
+ $this->assertTrue($secondPaypalAccount->success);
+
+ $updateResult = Braintree_PayPalAccount::update($firstToken, array(
+ 'token' => $secondToken
+ ));
+
+ $this->assertFalse($updateResult->success);
+ $errors = $updateResult->errors->forKey('paypalAccount')->errors;
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_TOKEN_IS_IN_USE, $errors[0]->code);
+ }
+
+ function testDelete()
+ {
+ $paymentMethodToken = 'PAYPALToken-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ Braintree_PayPalAccount::delete($paymentMethodToken);
+
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PayPalAccount::find($paymentMethodToken);
+ }
+
+ function testSale_createsASaleUsingGivenToken()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalFuturePayment;
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'paymentMethodNonce' => $nonce
+ ));
+ $paypalAccount = $customer->paypalAccounts[0];
+
+ $result = Braintree_PayPalAccount::sale($paypalAccount->token, array(
+ 'amount' => '100.00'
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals($customer->id, $result->transaction->customerDetails->id);
+ $this->assertEquals($paypalAccount->token, $result->transaction->paypalDetails->token);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodNonceTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodNonceTest.php
new file mode 100644
index 0000000..ea1292b
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodNonceTest.php
@@ -0,0 +1,66 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_PaymentMethodNonceTest extends PHPUnit_Framework_TestCase
+{
+ function testCreate_fromPaymentMethodToken()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $card = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $result = Braintree_PaymentMethodNonce::create($card->token);
+
+ $this->assertTrue($result->success);
+ $this->assertNotNull($result->paymentMethodNonce);
+ $this->assertNotNull($result->paymentMethodNonce->nonce);
+ }
+
+ function testCreate_fromNonExistentPaymentMethodToken()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethodNonce::create('not_a_token');
+ }
+
+ function testFind_exposesThreeDSecureInfo()
+ {
+ $nonce = Braintree_PaymentMethodNonce::find('threedsecurednonce');
+ $info = $nonce->threeDSecureInfo;
+
+ $this->assertEquals('threedsecurednonce', $nonce->nonce);
+ $this->assertEquals('CreditCard', $nonce->type);
+ $this->assertEquals('Y', $info->enrolled);
+ $this->assertEquals('authenticate_successful', $info->status);
+ $this->assertTrue($info->liabilityShifted);
+ $this->assertTrue($info->liabilityShiftPossible);
+ }
+
+ function testFind_exposesNullThreeDSecureInfoIfNoneExists()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ )
+ ));
+
+ $foundNonce = Braintree_PaymentMethodNonce::find($nonce);
+ $info = $foundNonce->threeDSecureInfo;
+
+ $this->assertEquals($nonce, $foundNonce->nonce);
+ $this->assertNull($info);
+ }
+
+ function testFind_nonExistantNonce()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethodNonce::find('not_a_nonce');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodTest.php
new file mode 100644
index 0000000..5ff9d7f
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PaymentMethodTest.php
@@ -0,0 +1,1154 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_PaymentMethodTest extends PHPUnit_Framework_TestCase
+{
+ function testCreate_fromVaultedCreditCardNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '11',
+ 'expirationYear' => '2099'
+ ),
+ 'share' => true
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertSame('411111', $result->paymentMethod->bin);
+ $this->assertSame('1111', $result->paymentMethod->last4);
+ $this->assertNotNull($result->paymentMethod->token);
+ $this->assertNotNull($result->paymentMethod->imageUrl);
+ }
+
+ function testGatewayCreate_fromVaultedCreditCardNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '11',
+ 'expirationYear' => '2099'
+ ),
+ 'share' => true
+ ));
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->paymentMethod()->create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertSame('411111', $result->paymentMethod->bin);
+ $this->assertSame('1111', $result->paymentMethod->last4);
+ $this->assertNotNull($result->paymentMethod->token);
+ $this->assertNotNull($result->paymentMethod->imageUrl);
+ }
+
+ function testCreate_fromFakeApplePayNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$applePayVisa
+ ));
+
+ $this->assertTrue($result->success);
+ $applePayCard = $result->paymentMethod;
+ $this->assertNotNull($applePayCard->token);
+ $this->assertSame(Braintree_ApplePayCard::VISA, $applePayCard->cardType);
+ $this->assertContains("Visa ", $applePayCard->paymentInstrumentName);
+ $this->assertTrue($applePayCard->default);
+ $this->assertContains('apple_pay', $applePayCard->imageUrl);
+ $this->assertTrue(intval($applePayCard->expirationMonth) > 0);
+ $this->assertTrue(intval($applePayCard->expirationYear) > 0);
+ }
+
+ function testCreate_fromFakeAndroidPayNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$androidPay
+ ));
+
+ $this->assertTrue($result->success);
+ $androidPayCard = $result->paymentMethod;
+ $this->assertNotNull($androidPayCard->token);
+ $this->assertSame(Braintree_CreditCard::DISCOVER, $androidPayCard->virtualCardType);
+ $this->assertSame(Braintree_CreditCard::DISCOVER, $androidPayCard->cardType);
+ $this->assertSame("1117", $androidPayCard->virtualCardLast4);
+ $this->assertSame("1117", $androidPayCard->last4);
+ $this->assertSame(Braintree_CreditCard::VISA, $androidPayCard->sourceCardType);
+ $this->assertSame("1111", $androidPayCard->sourceCardLast4);
+ $this->assertTrue($androidPayCard->default);
+ $this->assertContains('android_pay', $androidPayCard->imageUrl);
+ $this->assertTrue(intval($androidPayCard->expirationMonth) > 0);
+ $this->assertTrue(intval($androidPayCard->expirationYear) > 0);
+ }
+
+ function testCreate_fromUnvalidatedCreditCardNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '11',
+ 'expirationYear' => '2099',
+ 'options' => array(
+ 'validate' => false
+ )
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertSame('411111', $result->paymentMethod->bin);
+ $this->assertSame('1111', $result->paymentMethod->last4);
+ $this->assertNotNull($result->paymentMethod->token);
+ }
+
+ function testCreate_fromUnvalidatedFuturePaypalAccountNonce()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertSame('jane.doe@example.com', $result->paymentMethod->email);
+ $this->assertSame($paymentMethodToken, $result->paymentMethod->token);
+ }
+
+ function testCreate_fromAbstractPaymentMethodNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$abstractTransactable
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertNotNull($result->paymentMethod->token);
+ }
+
+ function testCreate_doesNotWorkForUnvalidatedOnetimePaypalAccountNonce()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'access_token' => 'PAYPAL_ACCESS_TOKEN',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('paypalAccount')->errors;
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_CANNOT_VAULT_ONE_TIME_USE_PAYPAL_ACCOUNT, $errors[0]->code);
+ }
+
+ function testCreate_handlesValidationErrorsForPayPalAccounts()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('paypalAccount')->errors;
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_CANNOT_VAULT_ONE_TIME_USE_PAYPAL_ACCOUNT, $errors[0]->code);
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_CONSENT_CODE_OR_ACCESS_TOKEN_IS_REQUIRED, $errors[1]->code);
+ }
+
+ function testCreate_allowsPassingDefaultOptionWithNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $card1 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $this->assertTrue($card1->isDefault());
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '11',
+ 'expirationYear' => '2099',
+ 'options' => array(
+ 'validate' => false
+ )
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'makeDefault' => true
+ )
+ ));
+
+ $card2 = $result->paymentMethod;
+ $card1 = Braintree_CreditCard::find($card1->token);
+ $this->assertFalse($card1->isDefault());
+ $this->assertTrue($card2->isDefault());
+ }
+
+ function testCreate_overridesNonceToken()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $firstToken = 'FIRST_TOKEN-' . strval(rand());
+ $secondToken = 'SECOND_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'token' => $firstToken,
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '11',
+ 'expirationYear' => '2099',
+ 'options' => array(
+ 'validate' => false
+ )
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce,
+ 'token' => $secondToken
+ ));
+
+ $card = $result->paymentMethod;
+ $this->assertEquals($secondToken, $card->token);
+ }
+
+ function testCreate_respectsVerifyCardAndVerificationMerchantAccountIdWhenIncludedOutsideOfTheNonce()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4000111111111115',
+ 'expirationMonth' => '11',
+ 'expirationYear' => '2099',
+ )
+ ));
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'options' => array(
+ 'verifyCard' => 'true',
+ 'verificationMerchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId()
+ )
+ ));
+
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $result->creditCardVerification->status);
+ $this->assertEquals('2000', $result->creditCardVerification->processorResponseCode);
+ $this->assertEquals('Do Not Honor', $result->creditCardVerification->processorResponseText);
+ $this->assertEquals(Braintree_TestHelper::nonDefaultMerchantAccountId(), $result->creditCardVerification->merchantAccountId);
+ }
+
+ function testCreate_respectsFailOnDuplicatePaymentMethodWhenIncludedOutsideTheNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012"
+ ));
+ $this->assertTrue($result->success);
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012"
+ )
+ ));
+ $updateResult = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'options' => array(
+ 'failOnDuplicatePaymentMethod' => 'true',
+ )
+ ));
+
+ $this->assertFalse($updateResult->success);
+ $resultErrors = $updateResult->errors->deepAll();
+ $this->assertEquals("81724", $resultErrors[0]->code);
+ }
+
+ function testCreate_allowsPassingABillingAddressOutsideOfTheNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '12',
+ 'expirationYear' => '2020',
+ 'options' => array(
+ 'validate' => false
+ )
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Abc Way'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(is_a($result->paymentMethod,'Braintree_CreditCard'));
+ $token = $result->paymentMethod->token;
+
+ $foundCreditCard = Braintree_CreditCard::find($token);
+ $this->assertTrue(NULL != $foundCreditCard);
+ $this->assertEquals('123 Abc Way', $foundCreditCard->billingAddress->streetAddress);
+ }
+
+ function testCreate_overridesTheBillingAddressInTheNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '12',
+ 'expirationYear' => '2020',
+ 'options' => array(
+ 'validate' => false
+ ),
+ 'billingAddress' => array(
+ 'streetAddress' => '456 Xyz Way'
+ )
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Abc Way'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(is_a($result->paymentMethod,'Braintree_CreditCard'));
+ $token = $result->paymentMethod->token;
+
+ $foundCreditCard = Braintree_CreditCard::find($token);
+ $this->assertTrue(NULL != $foundCreditCard);
+ $this->assertEquals('123 Abc Way', $foundCreditCard->billingAddress->streetAddress);
+ }
+
+ function testCreate_doesNotOverrideTheBillingAddressForAVaultedCreditCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'customerId' => $customer->id,
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '12',
+ 'expirationYear' => '2020',
+ 'billingAddress' => array(
+ 'streetAddress' => '456 Xyz Way'
+ )
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Abc Way'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(is_a($result->paymentMethod,'Braintree_CreditCard'));
+ $token = $result->paymentMethod->token;
+
+ $foundCreditCard = Braintree_CreditCard::find($token);
+ $this->assertTrue(NULL != $foundCreditCard);
+ $this->assertEquals('456 Xyz Way', $foundCreditCard->billingAddress->streetAddress);
+ }
+
+ function testCreate_allowsPassingABillingAddressIdOutsideOfTheNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ 'credit_card' => array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '12',
+ 'expirationYear' => '2020',
+ 'options' => array(
+ 'validate' => false
+ )
+ )
+ ));
+
+ $address = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'firstName' => 'Bobby',
+ 'lastName' => 'Tables'
+ ))->address;
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'billingAddressId' => $address->id
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(is_a($result->paymentMethod,'Braintree_CreditCard'));
+ $token = $result->paymentMethod->token;
+
+ $foundCreditCard = Braintree_CreditCard::find($token);
+ $this->assertTrue(NULL != $foundCreditCard);
+ $this->assertEquals('Bobby', $foundCreditCard->billingAddress->firstName);
+ $this->assertEquals('Tables', $foundCreditCard->billingAddress->lastName);
+ }
+
+ function testCreate_doesNotReturnAnErrorIfCreditCardOptionsArePresentForAPaypalNonce()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $originalToken = 'paypal-account-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPaypalAccount(array(
+ 'paypalAccount' => array(
+ 'consentCode' => 'consent-code',
+ 'token' => $originalToken
+ )
+ ));
+
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'options' => array(
+ 'verifyCard' => 'true',
+ 'failOnDuplicatePaymentMethod' => 'true',
+ 'verificationMerchantAccountId' => 'Not a Real Merchant Account Id'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ }
+
+ function testCreate_ignoresPassedBillingAddressParamsForPaypalAccount()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPaypalAccount(array(
+ 'paypalAccount' => array(
+ 'consentCode' => 'PAYPAL_CONSENT_CODE',
+ )
+ ));
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Abc Way'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(is_a($result->paymentMethod,'Braintree_PaypalAccount'));
+ $token = $result->paymentMethod->token;
+
+ $foundPaypalAccount = Braintree_PaypalAccount::find($token);
+ $this->assertTrue(NULL != $foundPaypalAccount);
+ }
+
+ function testCreate_ignoresPassedBillingAddressIdForPaypalAccount()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPaypalAccount(array(
+ 'paypalAccount' => array(
+ 'consentCode' => 'PAYPAL_CONSENT_CODE',
+ )
+ ));
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id,
+ 'billingAddressId' => 'address_id'
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(is_a($result->paymentMethod,'Braintree_PaypalAccount'));
+ $token = $result->paymentMethod->token;
+
+ $foundPaypalAccount = Braintree_PaypalAccount::find($token);
+ $this->assertTrue(NULL != $foundPaypalAccount);
+ }
+
+ function testCreate_acceptsNumberAndOtherCreditCardParameters()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$transactable,
+ 'cardholderName' => 'Jane Doe',
+ 'cvv' => '123',
+ 'expirationMonth' => '10',
+ 'expirationYear' => '24',
+ 'number' => '4242424242424242'
+ ));
+
+ $this->assertTrue($result->success);
+ $this->assertTrue('Jane Doe' == $result->paymentMethod->cardholderName);
+ $this->assertTrue('10' == $result->paymentMethod->expirationMonth);
+ $this->assertTrue('2024' == $result->paymentMethod->expirationYear);
+ $this->assertTrue('424242' == $result->paymentMethod->bin);
+ $this->assertTrue('4242' == $result->paymentMethod->last4);
+ }
+
+ function testFind_returnsCreditCards()
+ {
+ $paymentMethodToken = 'CREDIT_CARD_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'token' => $paymentMethodToken
+ ));
+ $this->assertTrue($creditCardResult->success);
+
+ $foundCreditCard = Braintree_PaymentMethod::find($creditCardResult->creditCard->token);
+
+ $this->assertEquals($paymentMethodToken, $foundCreditCard->token);
+ $this->assertEquals('510510', $foundCreditCard->bin);
+ $this->assertEquals('5100', $foundCreditCard->last4);
+ $this->assertEquals('05/2011', $foundCreditCard->expirationDate);
+ }
+
+ function testFind_returnsCreditCardsWithSubscriptions()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ ));
+ $this->assertTrue($creditCardResult->success);
+
+ $subscriptionId = strval(rand());
+ Braintree_Subscription::create(array(
+ 'id' => $subscriptionId,
+ 'paymentMethodToken' => $creditCardResult->creditCard->token,
+ 'planId' => 'integration_trialless_plan',
+ 'price' => '1.00'
+ ));
+
+ $foundCreditCard = Braintree_PaymentMethod::find($creditCardResult->creditCard->token);
+ $this->assertEquals($subscriptionId, $foundCreditCard->subscriptions[0]->id);
+ $this->assertEquals('integration_trialless_plan', $foundCreditCard->subscriptions[0]->planId);
+ $this->assertEquals('1.00', $foundCreditCard->subscriptions[0]->price);
+ }
+
+ function testFind_returnsPayPalAccounts()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $foundPayPalAccount = Braintree_PaymentMethod::find($paymentMethodToken);
+
+ $this->assertSame('jane.doe@example.com', $foundPayPalAccount->email);
+ $this->assertSame($paymentMethodToken, $foundPayPalAccount->token);
+ }
+
+ function testFind_returnsApplePayCards()
+ {
+ $paymentMethodToken = 'APPLE_PAY-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $nonce = Braintree_Test_Nonces::$applePayVisa;
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce,
+ 'token' => $paymentMethodToken
+ ));
+
+ $foundApplePayCard = Braintree_PaymentMethod::find($paymentMethodToken);
+
+ $this->assertSame($paymentMethodToken, $foundApplePayCard->token);
+ $this->assertInstanceOf('Braintree_ApplePayCard', $foundApplePayCard);
+ $this->assertTrue(intval($foundApplePayCard->expirationMonth) > 0);
+ $this->assertTrue(intval($foundApplePayCard->expirationYear) > 0);
+ }
+
+ function testFind_returnsAndroidPayCards()
+ {
+ $paymentMethodToken = 'ANDROID-PAY-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $nonce = Braintree_Test_Nonces::$androidPay;
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce,
+ 'token' => $paymentMethodToken
+ ));
+
+ $foundAndroidPayCard = Braintree_PaymentMethod::find($paymentMethodToken);
+
+ $this->assertSame($paymentMethodToken, $foundAndroidPayCard->token);
+ $this->assertInstanceOf('Braintree_AndroidPayCard', $foundAndroidPayCard);
+ $this->assertSame(Braintree_CreditCard::DISCOVER, $foundAndroidPayCard->virtualCardType);
+ $this->assertSame("1117", $foundAndroidPayCard->virtualCardLast4);
+ $this->assertSame(Braintree_CreditCard::VISA, $foundAndroidPayCard->sourceCardType);
+ $this->assertSame("1111", $foundAndroidPayCard->sourceCardLast4);
+ $this->assertTrue($foundAndroidPayCard->default);
+ $this->assertContains('android_pay', $foundAndroidPayCard->imageUrl);
+ $this->assertTrue(intval($foundAndroidPayCard->expirationMonth) > 0);
+ $this->assertTrue(intval($foundAndroidPayCard->expirationYear) > 0);
+ }
+
+ function testFind_returnsCoinbaseAccounts()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $result = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$coinbase
+ ));
+
+ $this->assertTrue($result->success);
+ $coinbaseAccount = $result->paymentMethod;
+ $this->assertNotNull($coinbaseAccount->token);
+ $foundCoinbaseAccount = Braintree_PaymentMethod::find($coinbaseAccount->token);
+ $this->assertInstanceOf('Braintree_CoinbaseAccount', $foundCoinbaseAccount);
+ $this->assertNotNull($foundCoinbaseAccount->userId);
+ $this->assertNotNull($foundCoinbaseAccount->userName);
+ $this->assertNotNull($foundCoinbaseAccount->userEmail);
+ }
+
+
+ function testFind_returnsAbstractPaymentMethods()
+ {
+ $paymentMethodToken = 'ABSTRACT-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $nonce = Braintree_test_Nonces::$abstractTransactable;
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce,
+ 'token' => $paymentMethodToken
+ ));
+
+ $foundPaymentMethod = Braintree_PaymentMethod::find($paymentMethodToken);
+
+ $this->assertSame($paymentMethodToken, $foundPaymentMethod-> token);
+ }
+
+ function testFind_throwsIfCannotBeFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find('NON_EXISTENT_TOKEN');
+ }
+
+ function testUpdate_updatesTheCreditCard()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'cardholderName' => 'Original Holder',
+ 'customerId' => $customer->id,
+ 'cvv' => '123',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012"
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'cardholderName' => 'New Holder',
+ 'cvv' => '456',
+ 'number' => Braintree_Test_CreditCardNumbers::$masterCard,
+ 'expirationDate' => "06/2013"
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $this->assertSame($updateResult->paymentMethod->token, $creditCard->token);
+ $updatedCreditCard = $updateResult->paymentMethod;
+ $this->assertSame("New Holder", $updatedCreditCard->cardholderName);
+ $this->assertSame(substr(Braintree_Test_CreditCardNumbers::$masterCard, 0, 6), $updatedCreditCard->bin);
+ $this->assertSame(substr(Braintree_Test_CreditCardNumbers::$masterCard, -4), $updatedCreditCard->last4);
+ $this->assertSame("06/2013", $updatedCreditCard->expirationDate);
+ }
+
+ function testUpdate_createsANewBillingAddressByDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012",
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Nigeria Ave'
+ )
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'billingAddress' => array(
+ 'region' => 'IL'
+ )
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $updatedCreditCard = $updateResult->paymentMethod;
+ $this->assertSame("IL", $updatedCreditCard->billingAddress->region);
+ $this->assertSame(NULL, $updatedCreditCard->billingAddress->streetAddress);
+ $this->assertFalse($creditCard->billingAddress->id == $updatedCreditCard->billingAddress->id);
+ }
+
+ function testUpdate_updatesTheBillingAddressIfOptionIsSpecified()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012",
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Nigeria Ave'
+ )
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'billingAddress' => array(
+ 'region' => 'IL',
+ 'options' => array(
+ 'updateExisting' => 'true'
+ )
+ ),
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $updatedCreditCard = $updateResult->paymentMethod;
+ $this->assertSame("IL", $updatedCreditCard->billingAddress->region);
+ $this->assertSame("123 Nigeria Ave", $updatedCreditCard->billingAddress->streetAddress);
+ $this->assertTrue($creditCard->billingAddress->id == $updatedCreditCard->billingAddress->id);
+ }
+
+ function testUpdate_updatesTheCountryViaCodes()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012",
+ 'billingAddress' => array(
+ 'streetAddress' => '123 Nigeria Ave'
+ )
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'billingAddress' => array(
+ 'countryName' => 'American Samoa',
+ 'countryCodeAlpha2' => 'AS',
+ 'countryCodeAlpha3' => 'ASM',
+ 'countryCodeNumeric' => '016',
+ 'options' => array(
+ 'updateExisting' => 'true'
+ )
+ ),
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $updatedCreditCard = $updateResult->paymentMethod;
+ $this->assertSame("American Samoa", $updatedCreditCard->billingAddress->countryName);
+ $this->assertSame("AS", $updatedCreditCard->billingAddress->countryCodeAlpha2);
+ $this->assertSame("ASM", $updatedCreditCard->billingAddress->countryCodeAlpha3);
+ $this->assertSame("016", $updatedCreditCard->billingAddress->countryCodeNumeric);
+ }
+
+ function testUpdate_canPassExpirationMonthAndExpirationYear()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012"
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'number' => Braintree_Test_CreditCardNumbers::$masterCard,
+ 'expirationMonth' => "07",
+ 'expirationYear' => "2011"
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $this->assertSame($updateResult->paymentMethod->token, $creditCard->token);
+ $updatedCreditCard = $updateResult->paymentMethod;
+ $this->assertSame("07", $updatedCreditCard->expirationMonth);
+ $this->assertSame("07", $updatedCreditCard->expirationMonth);
+ $this->assertSame("07/2011", $updatedCreditCard->expirationDate);
+ }
+
+ function testUpdate_verifiesTheUpdateIfOptionsVerifyCardIsTrue()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'cardholderName' => 'Original Holder',
+ 'customerId' => $customer->id,
+ 'cvv' => '123',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012"
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'cardholderName' => 'New Holder',
+ 'cvv' => '456',
+ 'number' => Braintree_Test_CreditCardNumbers::$failsSandboxVerification['MasterCard'],
+ 'expirationDate' => "06/2013",
+ 'options' => array(
+ 'verifyCard' => 'true'
+ )
+ ));
+
+ $this->assertFalse($updateResult->success);
+ $this->assertEquals(Braintree_Result_CreditCardVerification::PROCESSOR_DECLINED, $updateResult->creditCardVerification->status);
+ $this->assertEquals(NULL, $updateResult->creditCardVerification->gatewayRejectionReason);
+ }
+
+ function testUpdate_canUpdateTheBillingAddress()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'cardholderName' => 'Original Holder',
+ 'customerId' => $customer->id,
+ 'cvv' => '123',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'billingAddress' => array(
+ 'firstName' => 'Old First Name',
+ 'lastName' => 'Old Last Name',
+ 'company' => 'Old Company',
+ 'streetAddress' => '123 Old St',
+ 'extendedAddress' => 'Apt Old',
+ 'locality' => 'Old City',
+ 'region' => 'Old State',
+ 'postalCode' => '12345',
+ 'countryName' => 'Canada'
+ )
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'billingAddress' => array(
+ 'firstName' => 'New First Name',
+ 'lastName' => 'New Last Name',
+ 'company' => 'New Company',
+ 'streetAddress' => '123 New St',
+ 'extendedAddress' => 'Apt New',
+ 'locality' => 'New City',
+ 'region' => 'New State',
+ 'postalCode' => '56789',
+ 'countryName' => 'United States of America'
+ )
+ ));
+
+ $this->assertTrue($updateResult->success);
+ $address = $updateResult->paymentMethod->billingAddress;
+ $this->assertSame('New First Name', $address->firstName);
+ $this->assertSame('New Last Name', $address->lastName);
+ $this->assertSame('New Company', $address->company);
+ $this->assertSame('123 New St', $address->streetAddress);
+ $this->assertSame('Apt New', $address->extendedAddress);
+ $this->assertSame('New City', $address->locality);
+ $this->assertSame('New State', $address->region);
+ $this->assertSame('56789', $address->postalCode);
+ $this->assertSame('United States of America', $address->countryName);
+ }
+
+ function testUpdate_returnsAnErrorIfInvalid()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'cardholderName' => 'Original Holder',
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2012"
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard->token, array(
+ 'cardholderName' => 'New Holder',
+ 'number' => 'invalid',
+ 'expirationDate' => "05/2014",
+ ));
+
+ $this->assertFalse($updateResult->success);
+ $numberErrors = $updateResult->errors->forKey('creditCard')->onAttribute('number');
+ $this->assertEquals("Credit card number must be 12-19 digits.", $numberErrors[0]->message);
+ }
+
+ function testUpdate_canUpdateTheDefault()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+
+ $creditCardResult1 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2009"
+ ));
+ $this->assertTrue($creditCardResult1->success);
+ $creditCard1 = $creditCardResult1->creditCard;
+
+ $creditCardResult2 = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2009"
+ ));
+ $this->assertTrue($creditCardResult2->success);
+ $creditCard2 = $creditCardResult2->creditCard;
+
+ $this->assertTrue($creditCard1->default);
+ $this->assertFalse($creditCard2->default);
+
+
+ $updateResult = Braintree_PaymentMethod::update($creditCard2->token, array(
+ 'options' => array(
+ 'makeDefault' => 'true'
+ )
+ ));
+ $this->assertTrue($updateResult->success);
+
+ $this->assertFalse(Braintree_PaymentMethod::find($creditCard1->token)->default);
+ $this->assertTrue(Braintree_PaymentMethod::find($creditCard2->token)->default);
+ }
+
+ function testUpdate_updatesAPaypalAccountsToken()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $originalToken = 'paypal-account-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'consent-code',
+ 'token' => $originalToken
+ )
+ ));
+
+ $originalResult = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id
+ ));
+ $this->assertTrue($originalResult->success);
+
+ $originalPaypalAccount = $originalResult->paymentMethod;
+
+ $updatedToken = 'UPDATED_TOKEN-' . strval(rand());
+ $updateResult = Braintree_PaymentMethod::update($originalPaypalAccount->token, array(
+ 'token' => $updatedToken
+ ));
+ $this->assertTrue($updateResult->success);
+
+ $updatedPaypalAccount = Braintree_PaymentMethod::find($updatedToken);
+ $this->assertEquals($originalPaypalAccount->email, $updatedPaypalAccount->email);
+
+ $this->setExpectedException('Braintree_Exception_NotFound', 'payment method with token ' . $originalToken . ' not found');
+ Braintree_PaymentMethod::find($originalToken);
+
+ }
+
+ function testUpdate_canMakeAPaypalAccountTheDefaultPaymentMethod()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => "05/2009",
+ 'options' => array(
+ 'makeDefault' => 'true'
+ )
+ ));
+ $this->assertTrue($creditCardResult->success);
+ $creditCard = $creditCardResult->creditCard;
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'consent-code',
+ )
+ ));
+
+ $originalToken = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'customerId' => $customer->id
+ ))->paymentMethod->token;
+
+ $updateResult = Braintree_PaymentMethod::update($originalToken, array(
+ 'options' => array(
+ 'makeDefault' => 'true'
+ )
+ ));
+ $this->assertTrue($updateResult->success);
+
+ $updatedPaypalAccount = Braintree_PaymentMethod::find($originalToken);
+ $this->assertTrue($updatedPaypalAccount->default);
+
+ }
+
+ function testUpdate_returnsAnErrorIfATokenForAccountIsUsedToAttemptAnUpdate()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $firstToken = 'paypal-account-' . strval(rand());
+ $secondToken = 'paypal-account-' . strval(rand());
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $firstNonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'consent-code',
+ 'token' => $firstToken
+ )
+ ));
+ $firstResult = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $firstNonce,
+ 'customerId' => $customer->id
+ ));
+ $this->assertTrue($firstResult->success);
+ $firstPaypalAccount = $firstResult->paymentMethod;
+
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $secondNonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'consent-code',
+ 'token' => $secondToken
+ )
+ ));
+ $secondResult = Braintree_PaymentMethod::create(array(
+ 'paymentMethodNonce' => $secondNonce,
+ 'customerId' => $customer->id
+ ));
+ $this->assertTrue($secondResult->success);
+ $secondPaypalAccount = $firstResult->paymentMethod;
+
+
+ $updateResult = Braintree_PaymentMethod::update($firstToken, array(
+ 'token' => $secondToken
+ ));
+
+ $this->assertFalse($updateResult->success);
+ $resultErrors = $updateResult->errors->deepAll();
+ $this->assertEquals("92906", $resultErrors[0]->code);
+
+ }
+
+ function testDelete_worksWithCreditCards()
+ {
+ $paymentMethodToken = 'CREDIT_CARD_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCardResult = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'token' => $paymentMethodToken
+ ));
+ $this->assertTrue($creditCardResult->success);
+
+ Braintree_PaymentMethod::delete($paymentMethodToken);
+
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ integrationMerchantConfig();
+ }
+
+ function testDelete_worksWithPayPalAccounts()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $paypalAccountResult = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->assertTrue($paypalAccountResult->success);
+
+ Braintree_PaymentMethod::delete($paymentMethodToken);
+
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/PlanTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PlanTest.php
new file mode 100644
index 0000000..94cb8c4
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/PlanTest.php
@@ -0,0 +1,126 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_PlanTest extends PHPUnit_Framework_TestCase
+{
+ function testAll_withNoPlans_returnsEmptyArray()
+ {
+ testMerchantConfig();
+ $plans = Braintree_Plan::all();
+ $this->assertEquals($plans, array());
+ integrationMerchantConfig();
+
+ }
+
+ function testAll_returnsAllPlans()
+ {
+ $newId = strval(rand());
+ $params = array (
+ "id" => $newId,
+ "billingDayOfMonth" => "1",
+ "billingFrequency" => "1",
+ "currencyIsoCode" => "USD",
+ "description" => "some description",
+ "name" => "php test plan",
+ "numberOfBillingCycles" => "1",
+ "price" => "1.00",
+ "trialPeriod" => "false"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/plans/create_plan_for_tests";
+ $http->post($path, array("plan" => $params));
+
+ $addOnParams = array (
+ "kind" => "add_on",
+ "plan_id" => $newId,
+ "amount" => "1.00",
+ "name" => "add_on_name"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/modifications/create_modification_for_tests";
+ $http->post($path, array("modification" => $addOnParams));
+
+ $discountParams = array (
+ "kind" => "discount",
+ "plan_id" => $newId,
+ "amount" => "1.00",
+ "name" => "discount_name"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/modifications/create_modification_for_tests";
+ $http->post($path, array("modification" => $discountParams));
+
+ $plans = Braintree_Plan::all();
+
+ foreach ($plans as $plan)
+ {
+ if ($plan->id == $newId)
+ {
+ $actualPlan = $plan;
+ }
+ }
+
+ $this->assertNotNull($actualPlan);
+ $this->assertEquals($params["billingDayOfMonth"], $actualPlan->billingDayOfMonth);
+ $this->assertEquals($params["billingFrequency"], $actualPlan->billingFrequency);
+ $this->assertEquals($params["currencyIsoCode"], $actualPlan->currencyIsoCode);
+ $this->assertEquals($params["description"], $actualPlan->description);
+ $this->assertEquals($params["name"], $actualPlan->name);
+ $this->assertEquals($params["numberOfBillingCycles"], $actualPlan->numberOfBillingCycles);
+ $this->assertEquals($params["price"], $actualPlan->price);
+
+ $addOn = $actualPlan->addOns[0];
+ $this->assertEquals($addOnParams["name"], $addOn->name);
+
+ $discount = $actualPlan->discounts[0];
+ $this->assertEquals($discountParams["name"], $discount->name);
+ }
+
+ function testGatewayAll_returnsAllPlans()
+ {
+ $newId = strval(rand());
+ $params = array (
+ "id" => $newId,
+ "billingDayOfMonth" => "1",
+ "billingFrequency" => "1",
+ "currencyIsoCode" => "USD",
+ "description" => "some description",
+ "name" => "php test plan",
+ "numberOfBillingCycles" => "1",
+ "price" => "1.00",
+ "trialPeriod" => "false"
+ );
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . "/plans/create_plan_for_tests";
+ $http->post($path, array("plan" => $params));
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $plans = $gateway->plan()->all();
+
+ foreach ($plans as $plan)
+ {
+ if ($plan->id == $newId)
+ {
+ $actualPlan = $plan;
+ }
+ }
+
+ $this->assertNotNull($actualPlan);
+ $this->assertEquals($params["billingDayOfMonth"], $actualPlan->billingDayOfMonth);
+ $this->assertEquals($params["billingFrequency"], $actualPlan->billingFrequency);
+ $this->assertEquals($params["currencyIsoCode"], $actualPlan->currencyIsoCode);
+ $this->assertEquals($params["description"], $actualPlan->description);
+ $this->assertEquals($params["name"], $actualPlan->name);
+ $this->assertEquals($params["numberOfBillingCycles"], $actualPlan->numberOfBillingCycles);
+ $this->assertEquals($params["price"], $actualPlan->price);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/Result/ErrorTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/Result/ErrorTest.php
new file mode 100644
index 0000000..c7d9d70
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/Result/ErrorTest.php
@@ -0,0 +1,28 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../../TestHelper.php';
+
+class Braintree_Result_ErrorTest extends PHPUnit_Framework_TestCase
+{
+ function testValueForHtmlField()
+ {
+ $result = Braintree_Customer::create(array(
+ 'email' => 'invalid-email',
+ 'creditCard' => array(
+ 'number' => 'invalid-number',
+ 'expirationDate' => 'invalid-exp',
+ 'billingAddress' => array(
+ 'countryName' => 'invalid-country'
+ )
+ ),
+ 'customFields' => array(
+ 'store_me' => 'some custom value'
+ )
+ ));
+ $this->assertEquals(false, $result->success);
+ $this->assertEquals('invalid-email', $result->valueForHtmlField('customer[email]'));
+ $this->assertEquals('', $result->valueForHtmlField('customer[credit_card][number]'));
+ $this->assertEquals('invalid-exp', $result->valueForHtmlField('customer[credit_card][expiration_date]'));
+ $this->assertEquals('invalid-country', $result->valueForHtmlField('customer[credit_card][billing_address][country_name]'));
+ $this->assertEquals('some custom value', $result->valueForHtmlField('customer[custom_fields][store_me]'));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/SettlementBatchSummaryTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SettlementBatchSummaryTest.php
new file mode 100644
index 0000000..9a5d056
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SettlementBatchSummaryTest.php
@@ -0,0 +1,88 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_SettlementBatchSummaryTest extends PHPUnit_Framework_TestCase
+{
+ function isMasterCard($record)
+ {
+ return $record['cardType'] == Braintree_CreditCard::MASTER_CARD;
+ }
+
+ function testGenerate_returnsAnEmptyCollectionWhenThereIsNoData()
+ {
+ $result = Braintree_SettlementBatchSummary::generate('2000-01-01');
+
+ $this->assertTrue($result->success);
+ $this->assertEquals(0, count($result->settlementBatchSummary->records));
+ }
+
+ function testGatewayGenerate_returnsAnEmptyCollectionWhenThereIsNoData()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->settlementBatchSummary()->generate('2000-01-01');
+
+ $this->assertTrue($result->success);
+ $this->assertEquals(0, count($result->settlementBatchSummary->records));
+ }
+
+ function testGenerate_returnsAnErrorIfTheDateCanNotBeParsed()
+ {
+ $result = Braintree_SettlementBatchSummary::generate('OMG NOT A DATE');
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('settlementBatchSummary')->onAttribute('settlementDate');
+ $this->assertEquals(Braintree_Error_Codes::SETTLEMENT_BATCH_SUMMARY_SETTLEMENT_DATE_IS_INVALID, $errors[0]->code);
+ }
+
+ function testGenerate_returnsTransactionsSettledOnAGivenDay()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array('submitForSettlement' => true)
+ ));
+ Braintree_TestHelper::settle($transaction->id);
+
+ $today = new Datetime;
+ $result = Braintree_SettlementBatchSummary::generate(Braintree_TestHelper::nowInEastern());
+
+ $this->assertTrue($result->success);
+ $masterCardRecords = array_filter($result->settlementBatchSummary->records, 'self::isMasterCard');
+ $masterCardKeys = array_keys($masterCardRecords);
+ $masterCardIndex = $masterCardKeys[0];
+ $this->assertTrue(count($masterCardRecords) > 0);
+ $this->assertEquals(Braintree_CreditCard::MASTER_CARD, $masterCardRecords[$masterCardIndex]['cardType']);
+ }
+
+ function testGenerate_canBeGroupedByACustomField()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'customFields' => array(
+ 'store_me' => 'custom value'
+ ),
+ 'options' => array('submitForSettlement' => true)
+ ));
+
+ Braintree_TestHelper::settle($transaction->id);
+
+ $today = new Datetime;
+ $result = Braintree_SettlementBatchSummary::generate(Braintree_TestHelper::nowInEastern(), 'store_me');
+
+ $this->assertTrue($result->success);
+ $this->assertTrue(count($result->settlementBatchSummary->records) > 0);
+ $this->assertArrayHasKey('store_me', $result->settlementBatchSummary->records[0]);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionSearchTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionSearchTest.php
new file mode 100644
index 0000000..e6e7a7e
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionSearchTest.php
@@ -0,0 +1,337 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/SubscriptionTestHelper.php';
+
+class Braintree_SubscriptionSearchTest extends PHPUnit_Framework_TestCase
+{
+ function testSearch_planIdIs()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '1'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '1'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->is('integration_trial_plan'),
+ Braintree_SubscriptionSearch::price()->is('1')
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ }
+
+ function test_noRequestsWhenIterating()
+ {
+ $resultsReturned = false;
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->is('imaginary')
+ ));
+
+ foreach($collection as $transaction) {
+ $resultsReturned = true;
+ break;
+ }
+
+ $this->assertSame(0, $collection->maximumCount());
+ $this->assertEquals(false, $resultsReturned);
+ }
+
+ function testSearch_inTrialPeriod()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '1'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '1'
+ ))->subscription;
+
+ $subscriptions_in_trial = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::inTrialPeriod()->is(true)
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($subscriptions_in_trial, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($subscriptions_in_trial, $triallessSubscription));
+
+ $subscriptions_not_in_trial = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::inTrialPeriod()->is(false)
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($subscriptions_not_in_trial, $triallessSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($subscriptions_not_in_trial, $trialSubscription));
+ }
+
+ function testSearch_statusIsPastDue()
+ {
+ $found = false;
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::status()->in(array(Braintree_Subscription::PAST_DUE))
+ ));
+ foreach ($collection AS $item) {
+ $found = true;
+ $this->assertEquals(Braintree_Subscription::PAST_DUE, $item->status);
+ }
+ $this->assertTrue($found);
+ }
+
+ function testSearch_statusIsExpired()
+ {
+ $found = false;
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::status()->in(array(Braintree_Subscription::EXPIRED))
+ ));
+ foreach ($collection AS $item) {
+ $found = true;
+ $this->assertEquals(Braintree_Subscription::EXPIRED, $item->status);
+ }
+ $this->assertTrue($found);
+ }
+
+ function testSearch_billingCyclesRemaing()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $subscription_4 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'numberOfBillingCycles' => 4
+ ))->subscription;
+
+ $subscription_8 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'numberOfBillingCycles' => 8
+ ))->subscription;
+
+ $subscription_10 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'numberOfBillingCycles' => 10
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::billingCyclesRemaining()->between(5, 10)
+ ));
+
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $subscription_4));
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_8));
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_10));
+ }
+
+ function testSearch_subscriptionId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $rand_id = strval(rand());
+
+ $subscription_1 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'id' => 'subscription_123_id_' . $rand_id
+ ))->subscription;
+
+ $subscription_2 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'id' => 'subscription_23_id_' . $rand_id
+ ))->subscription;
+
+ $subscription_3 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'id' => 'subscription_3_id_' . $rand_id
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::id()->contains("23_id_")
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_1));
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_2));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $subscription_3));
+ }
+
+ function testSearch_merchantAccountId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $rand_id = strval(rand());
+
+ $subscription_1 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'id' => strval(rand()) . '_subscription_' . $rand_id,
+ 'price' => '2'
+ ))->subscription;
+
+ $subscription_2 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'id' => strval(rand()) . '_subscription_' . $rand_id,
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'price' => '2'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::id()->endsWith('subscription_' . $rand_id),
+ Braintree_SubscriptionSearch::merchantAccountId()->in(array(Braintree_TestHelper::nonDefaultMerchantAccountId())),
+ Braintree_SubscriptionSearch::price()->is('2')
+ ));
+
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $subscription_1));
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_2));
+ }
+
+ function testSearch_bogusMerchantAccountId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $rand_id = strval(rand());
+
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'id' => strval(rand()) . '_subscription_' . $rand_id,
+ 'price' => '11.38'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::id()->endsWith('subscription_' . $rand_id),
+ Braintree_SubscriptionSearch::merchantAccountId()->in(array("bogus_merchant_account")),
+ Braintree_SubscriptionSearch::price()->is('11.38')
+ ));
+
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $subscription));
+ }
+
+ function testSearch_daysPastDue()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id']
+ ))->subscription;
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/subscriptions/' . $subscription->id . '/make_past_due';
+ $http->put($path, array('daysPastDue' => 5));
+
+ $found = false;
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::daysPastDue()->between(2, 10)
+ ));
+ foreach ($collection AS $item) {
+ $found = true;
+ $this->assertTrue($item->daysPastDue <= 10);
+ $this->assertTrue($item->daysPastDue >= 2);
+ }
+ $this->assertTrue($found);
+ }
+
+ function testSearch_price()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $subscription_850 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '8.50'
+ ))->subscription;
+
+ $subscription_851 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '8.51'
+ ))->subscription;
+
+ $subscription_852 = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '8.52'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::price()->between('8.51', '8.52')
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_851));
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $subscription_852));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $subscription_850));
+ }
+
+ function testSearch_nextBillingDate()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ ))->subscription;
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ ))->subscription;
+
+ $fiveDaysFromNow = new DateTime();
+ $fiveDaysFromNow->modify("+5 days");
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::nextBillingDate()->greaterThanOrEqualTo($fiveDaysFromNow)
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $trialSubscription));
+ }
+
+ function testSearch_transactionId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $matchingSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ ))->subscription;
+
+ $nonMatchingSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::transactionId()->is($matchingSubscription->transactions[0]->id)
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $matchingSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $nonMatchingSubscription));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTest.php
new file mode 100644
index 0000000..a983005
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTest.php
@@ -0,0 +1,1197 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/SubscriptionTestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_SubscriptionTest extends PHPUnit_Framework_TestCase
+{
+ function testCreate_doesNotAcceptBadAttributes()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'invalid keys: bad');
+ $result = Braintree_Subscription::create(array(
+ 'bad' => 'value'
+ ));
+ }
+
+ function testCreate_whenSuccessful()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertTrue($result->success);
+ $subscription = $result->subscription;
+ $this->assertEquals($creditCard->token, $subscription->paymentMethodToken);
+ $this->assertEquals(0, $subscription->failureCount);
+ $this->assertEquals($plan['id'], $subscription->planId);
+ $this->assertEquals(Braintree_TestHelper::defaultMerchantAccountId(), $subscription->merchantAccountId);
+ $this->assertEquals(Braintree_Subscription::ACTIVE, $subscription->status);
+ $this->assertEquals('12.34', $subscription->nextBillAmount);
+ $this->assertEquals('12.34', $subscription->nextBillingPeriodAmount);
+ $this->assertEquals('0.00', $subscription->balance);
+ $this->assertEquals(1, $subscription->currentBillingCycle);
+ $this->assertInstanceOf('DateTime', $subscription->firstBillingDate);
+ $this->assertInstanceOf('DateTime', $subscription->nextBillingDate);
+ $this->assertInstanceOf('DateTime', $subscription->billingPeriodStartDate);
+ $this->assertInstanceOf('DateTime', $subscription->billingPeriodEndDate);
+ $this->assertInstanceOf('DateTime', $subscription->paidThroughDate);
+ $this->assertInstanceOf('DateTime', $subscription->updatedAt);
+ $this->assertInstanceOf('DateTime', $subscription->createdAt);
+
+ $this->assertEquals('12.34', $subscription->statusHistory[0]->price);
+ $this->assertEquals('0.00', $subscription->statusHistory[0]->balance);
+ $this->assertEquals(Braintree_Subscription::ACTIVE, $subscription->statusHistory[0]->status);
+ $this->assertEquals(Braintree_Subscription::API, $subscription->statusHistory[0]->subscriptionSource);
+ }
+
+ function testGatewayCreate_whenSuccessful()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->subscription()->create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertTrue($result->success);
+ $subscription = $result->subscription;
+ $this->assertEquals($creditCard->token, $subscription->paymentMethodToken);
+ $this->assertEquals(0, $subscription->failureCount);
+ $this->assertEquals($plan['id'], $subscription->planId);
+ $this->assertEquals(Braintree_TestHelper::defaultMerchantAccountId(), $subscription->merchantAccountId);
+ $this->assertEquals(Braintree_Subscription::ACTIVE, $subscription->status);
+ }
+
+ function testCreate_withPaymentMethodNonce()
+ {
+ $customerId = Braintree_Customer::create()->customer->id;
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "customerId" => $customerId,
+ "share" => true
+ ));
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'planId' => $plan['id']
+ ));
+
+ $this->assertTrue($result->success);
+
+ $transaction = $result->subscription->transactions[0];
+ $this->assertEquals("411111", $transaction->creditCardDetails->bin);
+ $this->assertEquals("1111", $transaction->creditCardDetails->last4);
+ }
+
+ function testCreate_returnsTransactionWhenTransactionFails()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'price' => Braintree_Test_TransactionAmounts::$decline
+
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Transaction::PROCESSOR_DECLINED, $result->transaction->status);
+ }
+
+ function testCreate_canSetTheId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $newId = strval(rand());
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'id' => $newId
+ ));
+
+ $this->assertTrue($result->success);
+ $subscription = $result->subscription;
+ $this->assertEquals($newId, $subscription->id);
+ }
+
+ function testCreate_canSetTheMerchantAccountId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId()
+ ));
+
+ $this->assertTrue($result->success);
+ $subscription = $result->subscription;
+ $this->assertEquals(Braintree_TestHelper::nonDefaultMerchantAccountId(), $subscription->merchantAccountId);
+ }
+
+ function testCreate_trialPeriodDefaultsToPlanWithoutTrial()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ ));
+ $subscription = $result->subscription;
+ $this->assertFalse($subscription->trialPeriod);
+ $this->assertNull($subscription->trialDuration);
+ $this->assertNull($subscription->trialDurationUnit);
+ }
+
+ function testCreate_trialPeriondDefaultsToPlanWithTrial()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ ));
+ $subscription = $result->subscription;
+ $this->assertTrue($subscription->trialPeriod);
+ $this->assertEquals(2, $subscription->trialDuration);
+ $this->assertEquals('day', $subscription->trialDurationUnit);
+ }
+
+ function testCreate_alterPlanTrialPeriod()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'trialDuration' => 5,
+ 'trialDurationUnit' => 'month'
+ ));
+ $subscription = $result->subscription;
+ $this->assertTrue($subscription->trialPeriod);
+ $this->assertEquals(5, $subscription->trialDuration);
+ $this->assertEquals('month', $subscription->trialDurationUnit);
+ }
+
+ function testCreate_removePlanTrialPeriod()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'trialPeriod' => false,
+ ));
+ $subscription = $result->subscription;
+ $this->assertFalse($subscription->trialPeriod);
+ }
+
+ function testCreate_createsATransactionIfNoTrialPeriod()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(1, sizeof($subscription->transactions));
+ $transaction = $subscription->transactions[0];
+ $this->assertInstanceOf('Braintree_Transaction', $transaction);
+ $this->assertEquals($plan['price'], $transaction->amount);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals($subscription->id, $transaction->subscriptionId);
+ }
+
+ function testCreate_doesNotCreateTransactionIfTrialPeriod()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(0, sizeof($subscription->transactions));
+ }
+
+ function testCreate_returnsATransactionWithSubscriptionBillingPeriod()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ ));
+ $subscription = $result->subscription;
+ $transaction = $subscription->transactions[0];
+ $this->assertEquals($subscription->billingPeriodStartDate, $transaction->subscriptionDetails->billingPeriodStartDate);
+ $this->assertEquals($subscription->billingPeriodEndDate, $transaction->subscriptionDetails->billingPeriodEndDate);
+ }
+
+ function testCreate_priceCanBeOverriden()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'price' => '2.00'
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals('2.00', $subscription->price);
+ }
+
+ function testCreate_billingDayOfMonthIsInheritedFromPlan()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::billingDayOfMonthPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(5, $subscription->billingDayOfMonth);
+ }
+
+ function testCreate_billingDayOfMonthCanBeOverriden()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::billingDayOfMonthPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'billingDayOfMonth' => 14
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(14, $subscription->billingDayOfMonth);
+ }
+
+ function testCreate_billingDayOfMonthCanBeOverridenWithStartImmediately()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::billingDayOfMonthPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'options' => array('startImmediately' => true)
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(1, sizeof($subscription->transactions));
+ }
+
+ function testCreate_firstBillingDateCanBeSet()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::billingDayOfMonthPlan();
+
+ $tomorrow = new DateTime("now + 1 day");
+ $tomorrow->setTime(0,0,0);
+
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'firstBillingDate' => $tomorrow
+ ));
+
+ $subscription = $result->subscription;
+ $this->assertEquals($tomorrow, $subscription->firstBillingDate);
+ $this->assertEquals(Braintree_Subscription::PENDING, $result->subscription->status);
+ }
+
+ function testCreate_firstBillingDateInThePast()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::billingDayOfMonthPlan();
+
+ $past = new DateTime("now - 3 days");
+ $past->setTime(0,0,0);
+
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'firstBillingDate' => $past
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('subscription')->onAttribute('firstBillingDate');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_FIRST_BILLING_DATE_CANNOT_BE_IN_THE_PAST, $errors[0]->code);
+ }
+
+ function testCreate_numberOfBillingCyclesCanBeOverridden()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals($plan['numberOfBillingCycles'], $subscription->numberOfBillingCycles);
+
+ $result = Braintree_Subscription::create(array(
+ 'numberOfBillingCycles' => '10',
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(10, $subscription->numberOfBillingCycles);
+ $this->assertFalse($subscription->neverExpires);
+ }
+
+ function testCreate_numberOfBillingCyclesCanBeOverriddenToNeverExpire()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals($plan['numberOfBillingCycles'], $subscription->numberOfBillingCycles);
+
+ $result = Braintree_Subscription::create(array(
+ 'neverExpires' => true,
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+ ));
+ $subscription = $result->subscription;
+ $this->assertNull($subscription->numberOfBillingCycles);
+ $this->assertTrue($subscription->neverExpires);
+ }
+
+ function testCreate_doesNotInheritAddOnsAndDiscountsWhenDoNotInheritAddOnsOrDiscountsIsSet()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'options' => array('doNotInheritAddOnsOrDiscounts' => true)
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(0, sizeof($subscription->addOns));
+ $this->assertEquals(0, sizeof($subscription->discounts));
+ }
+
+ function testCreate_inheritsAddOnsAndDiscountsFromPlanByDefault()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(2, sizeof($subscription->addOns));
+ $addOns = $subscription->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->amount, "10.00");
+ $this->assertEquals($addOns[0]->quantity, 1);
+ $this->assertEquals($addOns[0]->numberOfBillingCycles, null);
+ $this->assertEquals($addOns[0]->neverExpires, true);
+ $this->assertEquals($addOns[0]->currentBillingCycle, 0);
+
+ $this->assertEquals($addOns[1]->amount, "20.00");
+ $this->assertEquals($addOns[1]->quantity, 1);
+ $this->assertEquals($addOns[1]->numberOfBillingCycles, null);
+ $this->assertEquals($addOns[1]->neverExpires, true);
+ $this->assertEquals($addOns[1]->currentBillingCycle, 0);
+
+ $this->assertEquals(2, sizeof($subscription->discounts));
+ $discounts = $subscription->discounts;
+ Braintree_SubscriptionTestHelper::sortModificationsById($discounts);
+
+ $this->assertEquals($discounts[0]->amount, "11.00");
+ $this->assertEquals($discounts[0]->quantity, 1);
+ $this->assertEquals($discounts[0]->numberOfBillingCycles, null);
+ $this->assertEquals($discounts[0]->neverExpires, true);
+ $this->assertEquals($discounts[0]->currentBillingCycle, 0);
+
+ $this->assertEquals($discounts[1]->amount, "7.00");
+ $this->assertEquals($discounts[1]->quantity, 1);
+ $this->assertEquals($discounts[1]->numberOfBillingCycles, null);
+ $this->assertEquals($discounts[1]->neverExpires, true);
+ $this->assertEquals($discounts[1]->currentBillingCycle, 0);
+ }
+
+ function testCreate_allowsOverridingInheritedAddOnsAndDiscounts()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'addOns' => array(
+ 'update' => array(
+ array(
+ 'amount' => '50.00',
+ 'existingId' => 'increase_10',
+ 'quantity' => 2,
+ 'numberOfBillingCycles' => 5
+ ),
+ array(
+ 'amount' => '60.00',
+ 'existingId' => 'increase_20',
+ 'quantity' => 4,
+ 'numberOfBillingCycles' => 9
+ )
+ ),
+ ),
+ 'discounts' => array(
+ 'update' => array(
+ array(
+ 'amount' => '15.00',
+ 'existingId' => 'discount_7',
+ 'quantity' => 2,
+ 'neverExpires' => true
+ )
+ )
+ )
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(2, sizeof($subscription->addOns));
+ $addOns = $subscription->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->amount, "50.00");
+ $this->assertEquals($addOns[0]->quantity, 2);
+ $this->assertEquals($addOns[0]->numberOfBillingCycles, 5);
+ $this->assertEquals($addOns[0]->neverExpires, false);
+ $this->assertEquals($addOns[0]->currentBillingCycle, 0);
+
+ $this->assertEquals($addOns[1]->amount, "60.00");
+ $this->assertEquals($addOns[1]->quantity, 4);
+ $this->assertEquals($addOns[1]->numberOfBillingCycles, 9);
+ $this->assertEquals($addOns[1]->neverExpires, false);
+ $this->assertEquals($addOns[1]->currentBillingCycle, 0);
+
+ $this->assertEquals(2, sizeof($subscription->discounts));
+ $discounts = $subscription->discounts;
+ Braintree_SubscriptionTestHelper::sortModificationsById($discounts);
+
+ $this->assertEquals($discounts[0]->amount, "11.00");
+ $this->assertEquals($discounts[0]->quantity, 1);
+ $this->assertEquals($discounts[0]->numberOfBillingCycles, null);
+ $this->assertEquals($discounts[0]->neverExpires, true);
+ $this->assertEquals($discounts[0]->currentBillingCycle, 0);
+
+ $this->assertEquals($discounts[1]->amount, "15.00");
+ $this->assertEquals($discounts[1]->quantity, 2);
+ $this->assertEquals($discounts[1]->numberOfBillingCycles, null);
+ $this->assertEquals($discounts[1]->neverExpires, true);
+ $this->assertEquals($discounts[1]->currentBillingCycle, 0);
+ }
+
+ function testCreate_allowsRemovalOfInheritedAddOnsAndDiscounts()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'addOns' => array(
+ 'remove' => array('increase_10', 'increase_20')
+ ),
+ 'discounts' => array(
+ 'remove' => array('discount_7')
+ )
+ ));
+ $subscription = $result->subscription;
+ $this->assertEquals(0, sizeof($subscription->addOns));
+
+ $this->assertEquals(1, sizeof($subscription->discounts));
+
+ $this->assertEquals($subscription->discounts[0]->amount, "11.00");
+ $this->assertEquals($subscription->discounts[0]->quantity, 1);
+ $this->assertEquals($subscription->discounts[0]->numberOfBillingCycles, null);
+ $this->assertEquals($subscription->discounts[0]->neverExpires, true);
+ $this->assertEquals($subscription->discounts[0]->currentBillingCycle, 0);
+ }
+
+ function testCreate_allowsAddingNewAddOnsAndDiscounts()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'addOns' => array(
+ 'add' => array(
+ array(
+ 'inheritedFromId' => 'increase_30',
+ 'amount' => '35.00',
+ 'neverExpires' => true,
+ 'quantity' => 2
+ ),
+ ),
+ ),
+ 'discounts' => array(
+ 'add' => array(
+ array(
+ 'inheritedFromId' => 'discount_15',
+ 'amount' => '15.50',
+ 'numberOfBillingCycles' => 10,
+ 'quantity' => 3
+ )
+ )
+ )
+ ));
+
+ $subscription = $result->subscription;
+ $this->assertEquals(3, sizeof($subscription->addOns));
+ $addOns = $subscription->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->amount, "10.00");
+ $this->assertEquals($addOns[1]->amount, "20.00");
+ $this->assertEquals($addOns[2]->id, "increase_30");
+ $this->assertEquals($addOns[2]->amount, "35.00");
+ $this->assertEquals($addOns[2]->neverExpires, true);
+ $this->assertEquals($addOns[2]->numberOfBillingCycles, null);
+ $this->assertEquals($addOns[2]->quantity, 2);
+ $this->assertEquals($addOns[2]->currentBillingCycle, 0);
+
+
+ $this->assertEquals(3, sizeof($subscription->discounts));
+ $discounts = $subscription->discounts;
+ Braintree_SubscriptionTestHelper::sortModificationsById($discounts);
+
+ $this->assertEquals($discounts[0]->amount, "11.00");
+
+ $this->assertEquals($discounts[1]->amount, "15.50");
+ $this->assertEquals($discounts[1]->id, "discount_15");
+ $this->assertEquals($discounts[1]->neverExpires, false);
+ $this->assertEquals($discounts[1]->numberOfBillingCycles, 10);
+ $this->assertEquals($discounts[1]->quantity, 3);
+ $this->assertEquals($discounts[1]->currentBillingCycle, 0);
+
+ $this->assertEquals($discounts[2]->amount, "7.00");
+ }
+
+ function testCreate_properlyParsesValidationErrorsForArrays()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'addOns' => array(
+ 'update' => array(
+ array(
+ 'existingId' => 'increase_10',
+ 'amount' => 'invalid',
+ ),
+ array(
+ 'existingId' => 'increase_20',
+ 'quantity' => -10,
+ )
+ )
+ )
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('subscription')->forKey('addOns')->forKey('update')->forIndex(0)->onAttribute('amount');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_MODIFICATION_AMOUNT_IS_INVALID, $errors[0]->code);
+ $errors = $result->errors->forKey('subscription')->forKey('addOns')->forKey('update')->forIndex(1)->onAttribute('quantity');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_MODIFICATION_QUANTITY_IS_INVALID, $errors[0]->code);
+ }
+
+ function testCreate_withDescriptor()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'descriptor' => array(
+ 'name' => '123*123456789012345678',
+ 'phone' => '3334445555',
+ 'url' => 'ebay.com'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $subscription = $result->subscription;
+ $this->assertEquals('123*123456789012345678', $subscription->descriptor->name);
+ $this->assertEquals('3334445555', $subscription->descriptor->phone);
+ $this->assertEquals('ebay.com', $subscription->descriptor->url);
+ $transaction = $subscription->transactions[0];
+ $this->assertEquals('123*123456789012345678', $transaction->descriptor->name);
+ $this->assertEquals('3334445555', $transaction->descriptor->phone);
+ $this->assertEquals('ebay.com', $transaction->descriptor->url);
+ }
+
+ function testCreate_withDescriptorValidation()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'descriptor' => array(
+ 'name' => 'xxxxxx',
+ 'phone' => 'xxxx',
+ 'url' => '12345678901234'
+ )
+ ));
+ $this->assertFalse($result->success);
+ $subscription = $result->subscription;
+
+ $errors = $result->errors->forKey('subscription')->forKey('descriptor')->onAttribute('name');
+ $this->assertEquals(Braintree_Error_Codes::DESCRIPTOR_NAME_FORMAT_IS_INVALID, $errors[0]->code);
+
+ $errors = $result->errors->forKey('subscription')->forKey('descriptor')->onAttribute('phone');
+ $this->assertEquals(Braintree_Error_Codes::DESCRIPTOR_PHONE_FORMAT_IS_INVALID, $errors[0]->code);
+
+ $errors = $result->errors->forKey('subscription')->forKey('descriptor')->onAttribute('url');
+ $this->assertEquals(Braintree_Error_Codes::DESCRIPTOR_URL_FORMAT_IS_INVALID, $errors[0]->code);
+ }
+
+ function testCreate_fromPayPalACcount()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $paypalResult = Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $subscriptionResult = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $paymentMethodToken,
+ 'planId' => $plan['id']
+
+ ));
+ $this->assertTrue($subscriptionResult->success);
+ $transaction = $subscriptionResult->subscription->transactions[0];
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ }
+
+ function testCreate_fromPayPalACcountDoesNotWorkWithFutureNonce()
+ {
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $nonce = Braintree_Test_Nonces::$paypalFuturePayment;
+
+ $subscriptionResult = Braintree_Subscription::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'planId' => $plan['id']
+
+ ));
+ $this->assertFalse($subscriptionResult->success);
+ $errors = $subscriptionResult->errors->forKey('subscription')->errors;
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_PAYMENT_METHOD_NONCE_IS_INVALID, $errors[0]->code);
+ }
+
+ function testCreate_fromPayPalACcountDoesNotWorkWithOnetimeNonce()
+ {
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $subscriptionResult = Braintree_Subscription::create(array(
+ 'paymentMethodNonce' => $nonce,
+ 'planId' => $plan['id']
+
+ ));
+ $this->assertFalse($subscriptionResult->success);
+ $errors = $subscriptionResult->errors->forKey('subscription')->errors;
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_PAYMENT_METHOD_NONCE_IS_INVALID, $errors[0]->code);
+ }
+
+ function testValidationErrors_hasValidationErrorsOnId()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'id' => 'invalid token'
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('subscription')->onAttribute('id');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_TOKEN_FORMAT_IS_INVALID, $errors[0]->code);
+ }
+
+ function testFind()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id']
+ ));
+ $this->assertTrue($result->success);
+ $subscription = Braintree_Subscription::find($result->subscription->id);
+ $this->assertEquals($result->subscription->id, $subscription->id);
+ $this->assertEquals($plan['id'], $subscription->planId);
+ }
+
+ function testFind_throwsIfNotFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound', 'subscription with id does-not-exist not found');
+ Braintree_Subscription::find('does-not-exist');
+
+ }
+
+ function testUpdate_whenSuccessful()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $newId = strval(rand());
+ $newPlan = Braintree_SubscriptionTestHelper::trialPlan();
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'id' => $newId,
+ 'price' => '999.99',
+ 'planId' => $newPlan['id']
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals($newId, $result->subscription->id);
+ $this->assertEquals($newPlan['id'], $result->subscription->planId);
+ $this->assertEquals('999.99', $result->subscription->price);
+ }
+
+ function testUpdate_doesNotAcceptBadAttributes()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'invalid keys: bad');
+ $result = Braintree_Subscription::update('id', array(
+ 'bad' => 'value'
+ ));
+ }
+
+ function testUpdate_canUpdateNumberOfBillingCycles()
+ {
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $this->assertEquals($plan['numberOfBillingCycles'], $subscription->numberOfBillingCycles);
+
+ $updatedSubscription = Braintree_Subscription::update($subscription->id, array(
+ 'numberOfBillingCycles' => 15
+ ))->subscription;
+ $this->assertEquals(15, $updatedSubscription->numberOfBillingCycles);
+ }
+
+ function testUpdate_canUpdateNumberOfBillingCyclesToNeverExpire()
+ {
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $this->assertEquals($plan['numberOfBillingCycles'], $subscription->numberOfBillingCycles);
+
+ $updatedSubscription = Braintree_Subscription::update($subscription->id, array(
+ 'neverExpires' => true
+ ))->subscription;
+ $this->assertNull($updatedSubscription->numberOfBillingCycles);
+ }
+
+ function testUpdate_createsTransactionOnProration()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'price' => $subscription->price + 1,
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals(sizeof($subscription->transactions) + 1, sizeof($result->subscription->transactions));
+ }
+
+ function testUpdate_createsProratedTransactionWhenFlagIsPassedTrue()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'price' => $subscription->price + 1,
+ 'options' => array('prorateCharges' => true)
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals(sizeof($subscription->transactions) + 1, sizeof($result->subscription->transactions));
+ }
+
+ function testUpdate_createsProratedTransactionWhenFlagIsPassedFalse()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'price' => $subscription->price + 1,
+ 'options' => array('prorateCharges' => false)
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals(sizeof($subscription->transactions), sizeof($result->subscription->transactions));
+ }
+
+ function testUpdate_DoesNotUpdateSubscriptionWhenProrationTransactionFailsAndRevertIsTrue()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'price' => $subscription->price + 2100,
+ 'options' => array('prorateCharges' => true, 'revertSubscriptionOnProrationFailure' => true)
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(sizeof($subscription->transactions) + 1, sizeof($result->subscription->transactions));
+ $this->assertEquals(Braintree_Transaction::PROCESSOR_DECLINED, $result->subscription->transactions[0]->status);
+ $this->assertEquals("0.00", $result->subscription->balance);
+ $this->assertEquals($subscription->price, $result->subscription->price);
+ }
+
+ function testUpdate_UpdatesSubscriptionWhenProrationTransactionFailsAndRevertIsFalse()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'price' => $subscription->price + 2100,
+ 'options' => array('prorateCharges' => true, 'revertSubscriptionOnProrationFailure' => false)
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals(sizeof($subscription->transactions) + 1, sizeof($result->subscription->transactions));
+ $this->assertEquals(Braintree_Transaction::PROCESSOR_DECLINED, $result->subscription->transactions[0]->status);
+ $this->assertEquals($result->subscription->transactions[0]->amount, $result->subscription->balance);
+ $this->assertEquals($subscription->price + 2100, $result->subscription->price);
+ }
+
+ function testUpdate_invalidSubscriptionId()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_Subscription::update('does-not-exist', array());
+ }
+
+ function testUpdate_validationErrors()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::update($subscription->id, array('price' => ''));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('subscription')->onAttribute('price');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_PRICE_CANNOT_BE_BLANK, $errors[0]->code);
+ }
+
+ function testUpdate_cannotUpdateCanceledSubscription()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ Braintree_Subscription::cancel($subscription->id);
+ $result = Braintree_Subscription::update($subscription->id, array('price' => '1.00'));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('subscription')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_CANNOT_EDIT_CANCELED_SUBSCRIPTION, $errors[0]->code);
+ }
+
+ function testUpdate_canUpdatePaymentMethodToken()
+ {
+ $oldCreditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $oldCreditCard->token,
+ 'price' => '54.99',
+ 'planId' => $plan['id']
+ ))->subscription;
+
+ $newCreditCard = Braintree_CreditCard::createNoValidate(array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2010',
+ 'customerId' => $oldCreditCard->customerId
+ ));
+
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'paymentMethodToken' => $newCreditCard->token
+ ));
+ $this->assertTrue($result->success);
+ $this->assertEquals($newCreditCard->token, $result->subscription->paymentMethodToken);
+ }
+
+ function testUpdate_canUpdatePaymentMethodWithPaymentMethodNonce()
+ {
+ $oldCreditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $oldCreditCard->token,
+ 'price' => '54.99',
+ 'planId' => $plan['id']
+ ))->subscription;
+
+ $customerId = Braintree_Customer::create()->customer->id;
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "customerId" => $oldCreditCard->customerId,
+ "share" => true
+ ));
+
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+
+ $newCreditCard = Braintree_CreditCard::find($result->subscription->paymentMethodToken);
+
+ $this->assertEquals("1111", $newCreditCard->last4);
+ $this->assertNotEquals($oldCreditCard->last4, $newCreditCard->last4);
+ }
+
+ function testUpdate_canUpdateAddOnsAndDiscounts()
+ {
+ $oldCreditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $oldCreditCard->token,
+ 'price' => '54.99',
+ 'planId' => $plan['id']
+ ))->subscription;
+
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'addOns' => array(
+ 'update' => array(
+ array(
+ 'amount' => '99.99',
+ 'existingId' => 'increase_10',
+ 'quantity' => 99,
+ 'numberOfBillingCycles' => 99
+ ),
+ array(
+ 'amount' => '22.22',
+ 'existingId' => 'increase_20',
+ 'quantity' => 22,
+ 'neverExpires' => true
+ )
+ ),
+ ),
+ 'discounts' => array(
+ 'update' => array(
+ array(
+ 'amount' => '33.33',
+ 'existingId' => 'discount_11',
+ 'quantity' => 33,
+ 'numberOfBillingCycles' => 33
+ )
+ ),
+ ),
+ ));
+ $this->assertTrue($result->success);
+
+ $subscription = $result->subscription;
+ $this->assertEquals(2, sizeof($subscription->addOns));
+ $addOns = $subscription->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->id, "increase_10");
+ $this->assertEquals($addOns[0]->amount, "99.99");
+ $this->assertEquals($addOns[0]->neverExpires, false);
+ $this->assertEquals($addOns[0]->numberOfBillingCycles, 99);
+ $this->assertEquals($addOns[0]->quantity, 99);
+
+ $this->assertEquals($addOns[1]->id, "increase_20");
+ $this->assertEquals($addOns[1]->amount, "22.22");
+ $this->assertEquals($addOns[1]->neverExpires, true);
+ $this->assertEquals($addOns[1]->numberOfBillingCycles, null);
+ $this->assertEquals($addOns[1]->quantity, 22);
+
+ $this->assertEquals(2, sizeof($subscription->discounts));
+ $discounts = $subscription->discounts;
+ Braintree_SubscriptionTestHelper::sortModificationsById($discounts);
+
+ $this->assertEquals($discounts[0]->id, "discount_11");
+ $this->assertEquals($discounts[0]->amount, "33.33");
+ $this->assertEquals($discounts[0]->neverExpires, false);
+ $this->assertEquals($discounts[0]->numberOfBillingCycles, 33);
+ $this->assertEquals($discounts[0]->quantity, 33);
+ }
+
+ function testUpdate_canAddAndRemoveAddOnsAndDiscounts()
+ {
+ $oldCreditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $oldCreditCard->token,
+ 'price' => '54.99',
+ 'planId' => $plan['id']
+ ))->subscription;
+
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'addOns' => array(
+ 'add' => array(
+ array(
+ 'amount' => '33.33',
+ 'inheritedFromId' => 'increase_30',
+ 'quantity' => 33,
+ 'numberOfBillingCycles' => 33
+ )
+ ),
+ 'remove' => array('increase_10', 'increase_20')
+ ),
+ 'discounts' => array(
+ 'add' => array(
+ array(
+ 'inheritedFromId' => 'discount_15',
+ )
+ ),
+ 'remove' => array('discount_7')
+ ),
+ ));
+ $this->assertTrue($result->success);
+
+ $subscription = $result->subscription;
+ $this->assertEquals(1, sizeof($subscription->addOns));
+ $addOns = $subscription->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->id, "increase_30");
+ $this->assertEquals($addOns[0]->amount, "33.33");
+ $this->assertEquals($addOns[0]->neverExpires, false);
+ $this->assertEquals($addOns[0]->numberOfBillingCycles, 33);
+ $this->assertEquals($addOns[0]->quantity, 33);
+
+ $this->assertEquals(2, sizeof($subscription->discounts));
+ $discounts = $subscription->discounts;
+ Braintree_SubscriptionTestHelper::sortModificationsById($discounts);
+
+ $this->assertEquals($discounts[0]->id, "discount_11");
+ $this->assertEquals($discounts[1]->id, "discount_15");
+ $this->assertEquals($discounts[1]->amount, "15.00");
+ $this->assertEquals($discounts[1]->neverExpires, true);
+ $this->assertNull($discounts[1]->numberOfBillingCycles);
+ $this->assertEquals($discounts[1]->quantity, 1);
+ }
+
+ function testUpdate_canReplaceEntireSetOfAddonsAndDiscounts()
+ {
+ $oldCreditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::addOnDiscountPlan();
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $oldCreditCard->token,
+ 'price' => '54.99',
+ 'planId' => $plan['id']
+ ))->subscription;
+
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'addOns' => array(
+ 'add' => array(
+ array('inheritedFromId' => 'increase_30'),
+ array('inheritedFromId' => 'increase_20')
+ )
+ ),
+ 'discounts' => array(
+ 'add' => array(
+ array('inheritedFromId' => 'discount_15')
+ )
+ ),
+ 'options' => array('replaceAllAddOnsAndDiscounts' => true)
+ ));
+ $this->assertTrue($result->success);
+ $subscription = $result->subscription;
+
+ $this->assertEquals(2, sizeof($subscription->addOns));
+ $addOns = $subscription->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->id, "increase_20");
+ $this->assertEquals($addOns[1]->id, "increase_30");
+
+ $this->assertEquals(1, sizeof($subscription->discounts));
+ $discounts = $subscription->discounts;
+
+ $this->assertEquals($discounts[0]->id, "discount_15");
+ }
+
+ function testUpdate_withDescriptor()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $subscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'descriptor' => array(
+ 'name' => '123*123456789012345678',
+ 'phone' => '3334445555'
+ )
+ ))->subscription;
+ $result = Braintree_Subscription::update($subscription->id, array(
+ 'descriptor' => array(
+ 'name' => '999*9999999',
+ 'phone' => '8887776666'
+ )
+ ));
+ $updatedSubscription = $result->subscription;
+ $this->assertEquals('999*9999999', $updatedSubscription->descriptor->name);
+ $this->assertEquals('8887776666', $updatedSubscription->descriptor->phone);
+ }
+
+ function testCancel_returnsSuccessIfCanceled()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $result = Braintree_Subscription::cancel($subscription->id);
+ $this->assertTrue($result->success);
+ $this->assertEquals(Braintree_Subscription::CANCELED, $result->subscription->status);
+ }
+
+ function testCancel_throwsErrorIfRecordNotFound()
+ {
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_Subscription::cancel('non-existing-id');
+ }
+
+ function testCancel_returnsErrorIfCancelingCanceledSubscription()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ Braintree_Subscription::cancel($subscription->id);
+ $result = Braintree_Subscription::cancel($subscription->id);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('subscription')->onAttribute('status');
+ $this->assertEquals(Braintree_Error_Codes::SUBSCRIPTION_STATUS_IS_CANCELED, $errors[0]->code);
+ }
+
+ function testRetryCharge_WithoutAmount()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/subscriptions/' . $subscription->id . '/make_past_due';
+ $http->put($path);
+
+ $result = Braintree_Subscription::retryCharge($subscription->id);
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $this->assertEquals($subscription->price, $transaction->amount);
+ $this->assertNotNull($transaction->processorAuthorizationCode);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ }
+
+ function testRetryCharge_WithAmount()
+ {
+ $subscription = Braintree_SubscriptionTestHelper::createSubscription();
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/subscriptions/' . $subscription->id . '/make_past_due';
+ $http->put($path);
+
+ $result = Braintree_Subscription::retryCharge($subscription->id, 1000);
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $this->assertEquals(1000, $transaction->amount);
+ $this->assertNotNull($transaction->processorAuthorizationCode);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTestHelper.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTestHelper.php
new file mode 100644
index 0000000..ff3a6b6
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/SubscriptionTestHelper.php
@@ -0,0 +1,84 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_SubscriptionTestHelper
+{
+ static function addOnDiscountPlan()
+ {
+ return array(
+ 'description' => "Plan for integration tests -- with add-ons and discounts",
+ 'id' => "integration_plan_with_add_ons_and_discounts",
+ 'price' => '9.99',
+ 'trial_period' => true,
+ 'trial_duration' => 2,
+ 'trial_duration_unit' => 'day'
+ );
+ }
+
+ static function billingDayOfMonthPlan()
+ {
+ return array(
+ 'description' => 'Plan for integration tests -- with billing day of month',
+ 'id' => 'integration_plan_with_billing_day_of_month',
+ 'numberOfBillingCycles' => 5,
+ 'price' => '8.88',
+ 'trial_period' => false
+ );
+ }
+
+ static function trialPlan()
+ {
+ return array(
+ 'description' => 'Plan for integration tests -- with trial',
+ 'id' => 'integration_trial_plan',
+ 'numberOfBillingCycles' => 12,
+ 'price' => '43.21',
+ 'trial_period' => true,
+ 'trial_duration' => 2,
+ 'trial_duration_unit' => 'day'
+ );
+ }
+
+ static function triallessPlan()
+ {
+ return array(
+ 'description' => 'Plan for integration tests -- without a trial',
+ 'id' => 'integration_trialless_plan',
+ 'numberOfBillingCycles' => 12,
+ 'price' => '12.34',
+ 'trial_period' => false
+ );
+ }
+
+ static function createCreditCard()
+ {
+ $customer = Braintree_Customer::createNoValidate(array(
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2010'
+ )
+ ));
+ return $customer->creditCards[0];
+ }
+
+ static function createSubscription()
+ {
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => Braintree_SubscriptionTestHelper::createCreditCard()->token,
+ 'price' => '54.99',
+ 'planId' => $plan['id']
+ ));
+ return $result->subscription;
+ }
+
+ static function compareModificationsById($left, $right)
+ {
+ return strcmp($left->id, $right->id);
+ }
+
+ static function sortModificationsById(&$modifications)
+ {
+ usort($modifications, array("Braintree_SubscriptionTestHelper", "compareModificationsById"));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/TextNodeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TextNodeTest.php
new file mode 100644
index 0000000..f82a0da
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TextNodeTest.php
@@ -0,0 +1,142 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/SubscriptionTestHelper.php';
+
+class Braintree_TextNodeTest extends PHPUnit_Framework_TestCase
+{
+ function testIs()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '5'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '5'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->is("integration_trial_plan"),
+ Braintree_SubscriptionSearch::price()->is('5')
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ }
+
+ function testIsNot()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '6'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '6'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->isNot("integration_trialless_plan"),
+ Braintree_SubscriptionSearch::price()->is("6")
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ }
+
+ function testStartsWith()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '7'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '7'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->startsWith("integration_trial_pl"),
+ Braintree_SubscriptionSearch::price()->is("7")
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ }
+
+ function testEndsWith()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '8'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '8'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->endsWith("rial_plan"),
+ Braintree_SubscriptionSearch::price()->is("8")
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ }
+
+
+ function testContains()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $triallessPlan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $trialPlan = Braintree_SubscriptionTestHelper::trialPlan();
+
+ $trialSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $trialPlan['id'],
+ 'price' => '9'
+ ))->subscription;
+
+ $triallessSubscription = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $triallessPlan['id'],
+ 'price' => '9'
+ ))->subscription;
+
+ $collection = Braintree_Subscription::search(array(
+ Braintree_SubscriptionSearch::planId()->contains("ration_trial_pl"),
+ Braintree_SubscriptionSearch::price()->is("9")
+ ));
+
+ $this->assertTrue(Braintree_TestHelper::includes($collection, $trialSubscription));
+ $this->assertFalse(Braintree_TestHelper::includes($collection, $triallessSubscription));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionAdvancedSearchTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionAdvancedSearchTest.php
new file mode 100644
index 0000000..204e5c8
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionAdvancedSearchTest.php
@@ -0,0 +1,1526 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_TransactionAdvancedSearchTest extends PHPUnit_Framework_TestCase
+{
+ function testNoMatches()
+ {
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::billingFirstName()->is('thisnameisnotreal')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_noRequestsWhenIterating()
+ {
+ $resultsReturned = false;
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::billingFirstName()->is('thisnameisnotreal')
+ ));
+
+ foreach($collection as $transaction) {
+ $resultsReturned = true;
+ break;
+ }
+
+ $this->assertSame(0, $collection->maximumCount());
+ $this->assertEquals(false, $resultsReturned);
+ }
+
+ function testSearchOnTextFields()
+ {
+ $firstName = 'Tim' . rand();
+ $token = 'creditcard' . rand();
+ $customerId = 'customer' . rand();
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'cardholderName' => 'Tom Smith',
+ 'token' => $token,
+ ),
+ 'billing' => array(
+ 'company' => 'Braintree',
+ 'countryName' => 'United States of America',
+ 'extendedAddress' => 'Suite 123',
+ 'firstName' => $firstName,
+ 'lastName' => 'Smith',
+ 'locality' => 'Chicago',
+ 'postalCode' => '12345',
+ 'region' => 'IL',
+ 'streetAddress' => '123 Main St'
+ ),
+ 'customer' => array(
+ 'company' => 'Braintree',
+ 'email' => 'smith@example.com',
+ 'fax' => '5551231234',
+ 'firstName' => 'Tom',
+ 'id' => $customerId,
+ 'lastName' => 'Smith',
+ 'phone' => '5551231234',
+ 'website' => 'http://example.com',
+ ),
+ 'options' => array(
+ 'storeInVault' => true
+ ),
+ 'orderId' => 'myorder',
+ 'shipping' => array(
+ 'company' => 'Braintree P.S.',
+ 'countryName' => 'Mexico',
+ 'extendedAddress' => 'Apt 456',
+ 'firstName' => 'Thomas',
+ 'lastName' => 'Smithy',
+ 'locality' => 'Braintree',
+ 'postalCode' => '54321',
+ 'region' => 'MA',
+ 'streetAddress' => '456 Road'
+ ),
+ ));
+
+ $search_criteria = array(
+ 'billingCompany' => "Braintree",
+ 'billingCountryName' => "United States of America",
+ 'billingExtendedAddress' => "Suite 123",
+ 'billingFirstName' => $firstName,
+ 'billingLastName' => "Smith",
+ 'billingLocality' => "Chicago",
+ 'billingPostalCode' => "12345",
+ 'billingRegion' => "IL",
+ 'billingStreetAddress' => "123 Main St",
+ 'creditCardCardholderName' => "Tom Smith",
+ 'creditCardExpirationDate' => "05/2012",
+ 'creditCardNumber' => Braintree_Test_CreditCardNumbers::$visa,
+ 'creditCardUniqueIdentifier' => $transaction->creditCardDetails->uniqueNumberIdentifier,
+ 'customerCompany' => "Braintree",
+ 'customerEmail' => "smith@example.com",
+ 'customerFax' => "5551231234",
+ 'customerFirstName' => "Tom",
+ 'customerId' => $customerId,
+ 'customerLastName' => "Smith",
+ 'customerPhone' => "5551231234",
+ 'customerWebsite' => "http://example.com",
+ 'orderId' => "myorder",
+ 'paymentMethodToken' => $token,
+ 'paymentInstrumentType' => 'CreditCardDetail',
+ 'processorAuthorizationCode' => $transaction->processorAuthorizationCode,
+ 'shippingCompany' => "Braintree P.S.",
+ 'shippingCountryName' => "Mexico",
+ 'shippingExtendedAddress' => "Apt 456",
+ 'shippingFirstName' => "Thomas",
+ 'shippingLastName' => "Smithy",
+ 'shippingLocality' => "Braintree",
+ 'shippingPostalCode' => "54321",
+ 'shippingRegion' => "MA",
+ 'shippingStreetAddress' => "456 Road",
+ 'user' => "integration_user_public_id"
+ );
+
+ $query = array(Braintree_TransactionSearch::id()->is($transaction->id));
+ foreach ($search_criteria AS $criterion => $value) {
+ $query[] = Braintree_TransactionSearch::$criterion()->is($value);
+ }
+
+ $collection = Braintree_Transaction::search($query);
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ foreach ($search_criteria AS $criterion => $value) {
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::$criterion()->is($value),
+ Braintree_TransactionSearch::id()->is($transaction->id)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::$criterion()->is('invalid_attribute'),
+ Braintree_TransactionSearch::id()->is($transaction->id)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+ }
+
+ function testIs()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'cardholderName' => 'tom smith'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->is('tom smith')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->is('somebody else')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function testIsNot()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'cardholderName' => 'tom smith'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->isNot('somebody else')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->isNot('tom smith')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function testEndsWith()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'cardholderName' => 'tom smith'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->endsWith('m smith')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->endsWith('tom s')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function testStartsWith()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'cardholderName' => 'tom smith'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->startsWith('tom s')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->startsWith('m smith')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function testContains()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012',
+ 'cardholderName' => 'tom smith'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->contains('m sm')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardholderName()->contains('something else')
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_createdUsing()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::createdUsing()->is(Braintree_Transaction::FULL_INFORMATION)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::createdUsing()->in(
+ array(Braintree_Transaction::FULL_INFORMATION, Braintree_Transaction::TOKEN)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::createdUsing()->in(array(Braintree_Transaction::TOKEN))
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_paymentInstrumentType_is_creditCard()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::paymentInstrumentType()->is("CreditCardDetail")
+ ));
+
+
+ $this->assertEquals($transaction->paymentInstrumentType, Braintree_PaymentInstrumentType::CREDIT_CARD);
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_multipleValueNode_paymentInstrumentType_is_paypal()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$paypalOneTimePayment
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::paymentInstrumentType()->is("PayPalDetail")
+ ));
+
+
+ $this->assertEquals($transaction->paymentInstrumentType, Braintree_PaymentInstrumentType::PAYPAL_ACCOUNT);
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_multipleValueNode_paymentInstrumentType_is_applepay()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$applePayVisa
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::paymentInstrumentType()->is("ApplePayDetail")
+ ));
+
+
+ $this->assertEquals($transaction->paymentInstrumentType, Braintree_PaymentInstrumentType::APPLE_PAY_CARD);
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_multipleValueNode_createdUsing_allowedValues()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Invalid argument(s) for created_using: noSuchCreatedUsing');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::createdUsing()->is('noSuchCreatedUsing')
+ ));
+ }
+
+ function test_multipleValueNode_creditCardCustomerLocation()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCustomerLocation()->is(Braintree_CreditCard::US)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCustomerLocation()->in(
+ array(Braintree_CreditCard::US, Braintree_CreditCard::INTERNATIONAL)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCustomerLocation()->in(array(Braintree_CreditCard::INTERNATIONAL))
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_creditCardCustomerLocation_allowedValues()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Invalid argument(s) for credit_card_customer_location: noSuchLocation');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCustomerLocation()->is('noSuchLocation')
+ ));
+ }
+
+ function test_multipleValueNode_merchantAccountId()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::merchantAccountId()->is($transaction->merchantAccountId)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::merchantAccountId()->in(
+ array($transaction->merchantAccountId, "bogus_merchant_account_id")
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::merchantAccountId()->is("bogus_merchant_account_id")
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_creditCardType()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardType()->is($transaction->creditCardDetails->cardType)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardType()->in(
+ array($transaction->creditCardDetails->cardType, Braintree_CreditCard::CHINA_UNION_PAY)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::creditCardCardType()->is(Braintree_CreditCard::CHINA_UNION_PAY)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_creditCardType_allowedValues()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Invalid argument(s) for credit_card_card_type: noSuchCardType');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardType()->is('noSuchCardType')
+ ));
+ }
+
+ function test_multipleValueNode_status()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::status()->is($transaction->status)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::status()->in(
+ array($transaction->status, Braintree_Transaction::SETTLED)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::status()->is(Braintree_Transaction::SETTLED)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_status_authorizationExpired()
+ {
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::status()->is(Braintree_Transaction::AUTHORIZATION_EXPIRED)
+ ));
+ $this->assertGreaterThan(0, $collection->maximumCount());
+ $this->assertEquals(Braintree_Transaction::AUTHORIZATION_EXPIRED, $collection->firstItem()->status);
+ }
+
+ function test_multipleValueNode_status_allowedValues()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Invalid argument(s) for status: noSuchStatus');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::status()->is('noSuchStatus')
+ ));
+ }
+
+ function test_multipleValueNode_source()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'creditCard' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/2012'
+ )
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::source()->is(Braintree_Transaction::API)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::source()->in(
+ array(Braintree_Transaction::API, Braintree_Transaction::RECURRING)
+ )
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::source()->is(Braintree_Transaction::RECURRING)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_source_allowedValues()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Invalid argument(s) for source: noSuchSource');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::source()->is('noSuchSource')
+ ));
+ }
+
+ function test_multipleValueNode_type()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Joe Everyman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $sale = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodToken' => $creditCard->token,
+ 'options' => array('submitForSettlement' => true)
+ ));
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $sale->id . '/settle';
+ $http->put($path);
+ $refund = Braintree_Transaction::refund($sale->id)->transaction;
+
+ $credit = Braintree_Transaction::creditNoValidate(array(
+ 'amount' => '100.00',
+ 'paymentMethodToken' => $creditCard->token
+ ));
+
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::type()->is($sale->type)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::type()->in(
+ array($sale->type, $credit->type)
+ )
+ ));
+ $this->assertEquals(3, $collection->maximumCount());
+
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::type()->is($credit->type)
+ ));
+ $this->assertEquals(2, $collection->maximumCount());
+ }
+
+ function test_multipleValueNode_type_allowedValues()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Invalid argument(s) for type: noSuchType');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::type()->is('noSuchType')
+ ));
+ }
+
+ function test_multipleValueNode_type_withRefund()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Joe Everyman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $sale = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodToken' => $creditCard->token,
+ 'options' => array('submitForSettlement' => true)
+ ));
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $sale->id . '/settle';
+ $http->put($path);
+ $refund = Braintree_Transaction::refund($sale->id)->transaction;
+
+ $credit = Braintree_Transaction::creditNoValidate(array(
+ 'amount' => '100.00',
+ 'paymentMethodToken' => $creditCard->token
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::type()->is($credit->type),
+ Braintree_TransactionSearch::refund()->is(True)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($refund->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::type()->is($credit->type),
+ Braintree_TransactionSearch::refund()->is(False)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($credit->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_amount()
+ {
+ $customer = Braintree_Customer::createNoValidate();
+ $creditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'cardholderName' => 'Jane Everywoman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ))->creditCard;
+
+ $t_1000 = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'paymentMethodToken' => $creditCard->token
+ ));
+
+ $t_1500 = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1500.00',
+ 'paymentMethodToken' => $creditCard->token
+ ));
+
+ $t_1800 = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1800.00',
+ 'paymentMethodToken' => $creditCard->token
+ ));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::amount()->greaterThanOrEqualTo('1700')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($t_1800->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::amount()->lessThanOrEqualTo('1250')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($t_1000->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($creditCard->cardholderName),
+ Braintree_TransactionSearch::amount()->between('1100', '1600')
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($t_1500->id, $collection->firstItem()->id);
+ }
+
+ private function runDisbursementDateSearchTests($disbursementDateString, $comparison)
+ {
+ $knownDepositId = "deposittransaction";
+ $now = new DateTime($disbursementDateString);
+ $past = clone $now;
+ $past->modify("-1 hour");
+ $future = clone $now;
+ $future->modify("+1 hour");
+
+ $collections = array(
+ 'future' => Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownDepositId),
+ $comparison($future)
+ )),
+ 'now' => Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownDepositId),
+ $comparison($now)
+ )),
+ 'past' => Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownDepositId),
+ $comparison($past)
+ ))
+ );
+ return $collections;
+ }
+
+ function test_rangeNode_disbursementDate_lessThanOrEqualTo()
+ {
+ $compareLessThan = function($time) {
+ return Braintree_TransactionSearch::disbursementDate()->lessThanOrEqualTo($time);
+ };
+ $collection = $this->runDisbursementDateSearchTests("2013-04-10", $compareLessThan);
+
+ $this->assertEquals(0, $collection['past']->maximumCount());
+ $this->assertEquals(1, $collection['now']->maximumCount());
+ $this->assertEquals(1, $collection['future']->maximumCount());
+ }
+
+ function test_rangeNode_disbursementDate_GreaterThanOrEqualTo()
+ {
+ $comparison = function($time) {
+ return Braintree_TransactionSearch::disbursementDate()->GreaterThanOrEqualTo($time);
+ };
+ $collection = $this->runDisbursementDateSearchTests("2013-04-11", $comparison);
+
+ $this->assertEquals(1, $collection['past']->maximumCount());
+ $this->assertEquals(0, $collection['now']->maximumCount());
+ $this->assertEquals(0, $collection['future']->maximumCount());
+ }
+
+ function test_rangeNode_disbursementDate_between()
+ {
+ $knownId = "deposittransaction";
+
+ $now = new DateTime("2013-04-10");
+ $past = clone $now;
+ $past->modify("-1 day");
+ $future = clone $now;
+ $future->modify("+1 day");
+ $future2 = clone $now;
+ $future2->modify("+2 days");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->between($past, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->between($now, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->between($past, $now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->between($future, $future2)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_rangeNode_disbursementDate_is()
+ {
+ $knownId = "deposittransaction";
+
+ $now = new DateTime("2013-04-10");
+ $past = clone $now;
+ $past->modify("-1 day");
+ $future = clone $now;
+ $future->modify("+1 day");
+ $future2 = clone $now;
+ $future2->modify("+2 days");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->is($past)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->is($now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disbursementDate()->is($future)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ private function rundisputeDateSearchTests($disputeDateString, $comparison)
+ {
+ $knowndisputedId = "disputedtransaction";
+ $now = new DateTime($disputeDateString);
+ $past = clone $now;
+ $past->modify("-1 hour");
+ $future = clone $now;
+ $future->modify("+1 hour");
+
+ $collections = array(
+ 'future' => Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knowndisputedId),
+ $comparison($future)
+ )),
+ 'now' => Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knowndisputedId),
+ $comparison($now)
+ )),
+ 'past' => Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knowndisputedId),
+ $comparison($past)
+ ))
+ );
+ return $collections;
+ }
+
+ function test_rangeNode_disputeDate_lessThanOrEqualTo()
+ {
+ $compareLessThan = function($time) {
+ return Braintree_TransactionSearch::disputeDate()->lessThanOrEqualTo($time);
+ };
+ $collection = $this->rundisputeDateSearchTests("2014-03-01", $compareLessThan);
+
+ $this->assertEquals(0, $collection['past']->maximumCount());
+ $this->assertEquals(1, $collection['now']->maximumCount());
+ $this->assertEquals(1, $collection['future']->maximumCount());
+ }
+
+ function test_rangeNode_disputeDate_GreaterThanOrEqualTo()
+ {
+ $comparison = function($time) {
+ return Braintree_TransactionSearch::disputeDate()->GreaterThanOrEqualTo($time);
+ };
+ $collection = $this->rundisputeDateSearchTests("2014-03-01", $comparison);
+
+ $this->assertEquals(1, $collection['past']->maximumCount());
+ $this->assertEquals(1, $collection['now']->maximumCount());
+ $this->assertEquals(1, $collection['future']->maximumCount());
+ }
+
+ function test_rangeNode_disputeDate_between()
+ {
+ $knownId = "disputedtransaction";
+
+ $now = new DateTime("2014-03-01");
+ $past = clone $now;
+ $past->modify("-1 day");
+ $future = clone $now;
+ $future->modify("+1 day");
+ $future2 = clone $now;
+ $future2->modify("+2 days");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->between($past, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->between($now, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->between($past, $now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->between($future, $future2)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_rangeNode_disputeDate_is()
+ {
+ $knownId = "disputedtransaction";
+
+ $now = new DateTime("2014-03-01");
+ $past = clone $now;
+ $past->modify("-1 day");
+ $future = clone $now;
+ $future->modify("+1 day");
+ $future2 = clone $now;
+ $future2->modify("+2 days");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->is($past)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->is($now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($knownId, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($knownId),
+ Braintree_TransactionSearch::disputeDate()->is($future)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_rangeNode_createdAt_lessThanOrEqualTo()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Ted Everywoman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $past = clone $transaction->createdAt;
+ $past->modify("-1 hour");
+ $now = $transaction->createdAt;
+ $future = clone $transaction->createdAt;
+ $future->modify("+1 hour");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->lessThanOrEqualTo($future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->lessThanOrEqualTo($now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->lessThanOrEqualTo($past)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_rangeNode_createdAt_GreaterThanOrEqualTo()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Ted Everyman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $past = clone $transaction->createdAt;
+ $past->modify("-1 hour");
+ $now = $transaction->createdAt;
+ $future = clone $transaction->createdAt;
+ $future->modify("+1 hour");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->GreaterThanOrEqualTo($future)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->GreaterThanOrEqualTo($now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->GreaterThanOrEqualTo($past)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+
+
+ function test_rangeNode_createdAt_between()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Ted Everyman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $past = clone $transaction->createdAt;
+ $past->modify("-1 hour");
+ $now = $transaction->createdAt;
+ $future = clone $transaction->createdAt;
+ $future->modify("+1 hour");
+ $future2 = clone $transaction->createdAt;
+ $future2->modify("+1 day");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->between($past, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->between($now, $future)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->between($past, $now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->between($future, $future2)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_rangeNode_createdAt_is()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Ted Everyman' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $past = clone $transaction->createdAt;
+ $past->modify("-1 hour");
+ $now = $transaction->createdAt;
+ $future = clone $transaction->createdAt;
+ $future->modify("+1 hour");
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->is($future)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->is($now)
+ ));
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardCardholderName()->is($transaction->creditCardDetails->cardholderName),
+ Braintree_TransactionSearch::createdAt()->is($past)
+ ));
+ $this->assertEquals(0, $collection->maximumCount());
+ }
+
+ function test_rangeNode_createdAt_convertLocalToUTC()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Pingu Penguin' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("US/Pacific"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("US/Pacific"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::createdAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_createdAt_handlesUTCDateTimes()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Pingu Penguin' . rand(),
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::createdAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_authorizationExpiredAt()
+ {
+ $two_days_ago = date_create("now -2 days", new DateTimeZone("UTC"));
+ $yesterday = date_create("now -1 day", new DateTimeZone("UTC"));
+ $tomorrow = date_create("now +1 day", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::authorizationExpiredAt()->between($two_days_ago, $yesterday)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::authorizationExpiredAt()->between($yesterday, $tomorrow)
+ ));
+
+ $this->assertGreaterThan(0, $collection->maximumCount());
+ $this->assertEquals(Braintree_Transaction::AUTHORIZATION_EXPIRED, $collection->firstItem()->status);
+ }
+
+ function test_rangeNode_authorizedAt()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ )
+ ));
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::authorizedAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::authorizedAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_failedAt()
+ {
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '3000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ )
+ ))->transaction;
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::failedAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::failedAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_gatewayRejectedAt()
+ {
+ $old_merchant_id = Braintree_Configuration::merchantId();
+ $old_public_key = Braintree_Configuration::publicKey();
+ $old_private_key = Braintree_Configuration::privateKey();
+
+ Braintree_Configuration::merchantId('processing_rules_merchant_id');
+ Braintree_Configuration::publicKey('processing_rules_public_key');
+ Braintree_Configuration::privateKey('processing_rules_private_key');
+
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12',
+ 'cvv' => '200'
+ )
+ ))->transaction;
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::gatewayRejectedAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $firstCount = $collection->maximumCount();
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::gatewayRejectedAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $secondCount = $collection->maximumCount();
+ $firstId = $collection->firstItem()->id;
+
+ Braintree_Configuration::merchantId($old_merchant_id);
+ Braintree_Configuration::publicKey($old_public_key);
+ Braintree_Configuration::privateKey($old_private_key);
+
+ $this->assertEquals(0, $firstCount);
+ $this->assertEquals(1, $secondCount);
+ $this->assertEquals($transaction->id, $firstId);
+ }
+
+ function test_rangeNode_processorDeclinedAt()
+ {
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '2000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ )
+ ))->transaction;
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::processorDeclinedAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::processorDeclinedAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_settledAt()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $http = new Braintree_Http(Braintree_Configuration::$global);
+ $path = Braintree_Configuration::$global->merchantPath() . '/transactions/' . $transaction->id . '/settle';
+ $http->put($path);
+ $transaction = Braintree_Transaction::find($transaction->id);
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::settledAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::settledAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_submittedForSettlementAt()
+ {
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ))->transaction;
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::submittedForSettlementAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::submittedForSettlementAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_voidedAt()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ )
+ ));
+
+ $transaction = Braintree_Transaction::void($transaction->id)->transaction;
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::voidedAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::voidedAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_rangeNode_canSearchOnMultipleStatuses()
+ {
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '1000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ))->transaction;
+
+ $twenty_min_ago = date_create("now -20 minutes", new DateTimeZone("UTC"));
+ $ten_min_ago = date_create("now -10 minutes", new DateTimeZone("UTC"));
+ $ten_min_from_now = date_create("now +10 minutes", new DateTimeZone("UTC"));
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::authorizedAt()->between($twenty_min_ago, $ten_min_ago),
+ Braintree_TransactionSearch::submittedForSettlementAt()->between($twenty_min_ago, $ten_min_ago)
+ ));
+
+ $this->assertEquals(0, $collection->maximumCount());
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::id()->is($transaction->id),
+ Braintree_TransactionSearch::authorizedAt()->between($ten_min_ago, $ten_min_from_now),
+ Braintree_TransactionSearch::submittedForSettlementAt()->between($ten_min_ago, $ten_min_from_now)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($transaction->id, $collection->firstItem()->id);
+ }
+
+ function test_advancedSearchGivesIterableResult()
+ {
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::creditCardNumber()->startsWith("411111")
+ ));
+ $this->assertTrue($collection->maximumCount() > 100);
+
+ $arr = array();
+ foreach($collection as $transaction) {
+ array_push($arr, $transaction->id);
+ }
+ $unique_transaction_ids = array_unique(array_values($arr));
+ $this->assertEquals($collection->maximumCount(), count($unique_transaction_ids));
+ }
+
+ function test_handles_search_timeout()
+ {
+ $this->setExpectedException('Braintree_Exception_DownForMaintenance');
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::amount()->is('-5')
+ ));
+ }
+
+ function testHandlesPayPalAccounts()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'access_token' => 'PAYPAL_ACCESS_TOKEN'
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ ));
+
+ $this->assertTrue($result->success);
+ $paypalDetails = $result->transaction->paypalDetails;
+
+ $collection = Braintree_Transaction::search(array(
+ Braintree_TransactionSearch::paypalPaymentId()->is($paypalDetails->paymentId),
+ Braintree_TransactionSearch::paypalAuthorizationId()->is($paypalDetails->authorizationId),
+ Braintree_TransactionSearch::paypalPayerEmail()->is($paypalDetails->payerEmail)
+ ));
+
+ $this->assertEquals(1, $collection->maximumCount());
+ $this->assertEquals($result->transaction->id, $collection->firstItem()->id);
+
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionTest.php
new file mode 100644
index 0000000..cb77409
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransactionTest.php
@@ -0,0 +1,2833 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/SubscriptionTestHelper.php';
+require_once realpath(dirname(__FILE__)) . '/HttpClientApi.php';
+
+class Braintree_TransactionTest extends PHPUnit_Framework_TestCase
+{
+ function testCloneTransaction()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'orderId' => '123',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ ),
+ 'customer' => array(
+ 'firstName' => 'Dan',
+ ),
+ 'billing' => array(
+ 'firstName' => 'Carl',
+ ),
+ 'shipping' => array(
+ 'firstName' => 'Andrew',
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $cloneResult = Braintree_Transaction::cloneTransaction(
+ $transaction->id,
+ array(
+ 'amount' => '123.45',
+ 'channel' => 'MyShoppingCartProvider',
+ 'options' => array('submitForSettlement' => false)
+ )
+ );
+ Braintree_TestHelper::assertPrintable($cloneResult);
+ $this->assertTrue($cloneResult->success);
+ $cloneTransaction = $cloneResult->transaction;
+ $this->assertEquals('Dan', $cloneTransaction->customerDetails->firstName);
+ $this->assertEquals('Carl', $cloneTransaction->billingDetails->firstName);
+ $this->assertEquals('Andrew', $cloneTransaction->shippingDetails->firstName);
+ $this->assertEquals('510510******5100', $cloneTransaction->creditCardDetails->maskedNumber);
+ $this->assertEquals('authorized', $cloneTransaction->status);
+ $this->assertEquals('123.45', $cloneTransaction->amount);
+ $this->assertEquals('MyShoppingCartProvider', $cloneTransaction->channel);
+ }
+
+ function testCreateTransactionUsingNonce()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "share" => true
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '47.00',
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('47.00', $transaction->amount);
+ }
+
+ function testGatewayCreateTransactionUsingNonce()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "share" => true
+ ));
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $result = $gateway->transaction()->sale(array(
+ 'amount' => '47.00',
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('47.00', $transaction->amount);
+ }
+
+ function testCreateTransactionUsingFakeApplePayNonce()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '47.00',
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$applePayAmEx
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('47.00', $transaction->amount);
+ $applePayDetails = $transaction->applePayCardDetails;
+ $this->assertSame(Braintree_ApplePayCard::AMEX, $applePayDetails->cardType);
+ $this->assertContains("AmEx ", $applePayDetails->paymentInstrumentName);
+ $this->assertTrue(intval($applePayDetails->expirationMonth) > 0);
+ $this->assertTrue(intval($applePayDetails->expirationYear) > 0);
+ $this->assertNotNull($applePayDetails->cardholderName);
+ }
+
+ function testCreateTransactionUsingFakeAndroidPayNonce()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '47.00',
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$androidPay
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('47.00', $transaction->amount);
+ $androidPayCardDetails = $transaction->androidPayCardDetails;
+ $this->assertSame(Braintree_CreditCard::DISCOVER, $androidPayCardDetails->cardType);
+ $this->assertSame("1117", $androidPayCardDetails->last4);
+ $this->assertNull($androidPayCardDetails->token);
+ $this->assertSame(Braintree_CreditCard::DISCOVER, $androidPayCardDetails->virtualCardType);
+ $this->assertSame("1117", $androidPayCardDetails->virtualCardLast4);
+ $this->assertSame(Braintree_CreditCard::VISA, $androidPayCardDetails->sourceCardType);
+ $this->assertSame("1111", $androidPayCardDetails->sourceCardLast4);
+ $this->assertContains('android_pay', $androidPayCardDetails->imageUrl);
+ $this->assertTrue(intval($androidPayCardDetails->expirationMonth) > 0);
+ $this->assertTrue(intval($androidPayCardDetails->expirationYear) > 0);
+ }
+
+ function testCreateTransactionUsingFakeCoinbaseNonce()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '17.00',
+ 'paymentMethodNonce' => Braintree_Test_Nonces::$coinbase
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertNotNull($transaction->coinbaseDetails);
+ $this->assertNotNull($transaction->coinbaseDetails->userId);
+ $this->assertNotNull($transaction->coinbaseDetails->userName);
+ $this->assertNotNull($transaction->coinbaseDetails->userEmail);
+ }
+
+ function testCreateTransactionReturnsPaymentInstrumentType()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ ),
+ "share" => true
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '47.00',
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_PaymentInstrumentType::CREDIT_CARD, $transaction->paymentInstrumentType);
+ }
+
+ function testCloneTransactionAndSubmitForSettlement()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $cloneResult = Braintree_Transaction::cloneTransaction($transaction->id, array('amount' => '123.45', 'options' => array('submitForSettlement' => true)));
+ $cloneTransaction = $cloneResult->transaction;
+ $this->assertEquals('submitted_for_settlement', $cloneTransaction->status);
+ }
+
+ function testCloneWithValidations()
+ {
+ $result = Braintree_Transaction::credit(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $cloneResult = Braintree_Transaction::cloneTransaction($transaction->id, array('amount' => '123.45'));
+ $this->assertFalse($cloneResult->success);
+
+ $baseErrors = $cloneResult->errors->forKey('transaction')->onAttribute('base');
+
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_CANNOT_CLONE_CREDIT, $baseErrors[0]->code);
+ }
+
+ function testSale()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertNotNull($transaction->processorAuthorizationCode);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ $this->assertEquals('The Cardholder', $transaction->creditCardDetails->cardholderName);
+ }
+
+ function testSaleWithAccessToken()
+ {
+ $credentials = Braintree_OAuthTestHelper::createCredentials(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ 'merchantId' => 'integration_merchant_id',
+ ));
+
+ $gateway = new Braintree_Gateway(array(
+ 'accessToken' => $credentials->accessToken,
+ ));
+
+ $result = $gateway->transaction()->sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertNotNull($transaction->processorAuthorizationCode);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ $this->assertEquals('The Cardholder', $transaction->creditCardDetails->cardholderName);
+ }
+
+ function testSaleWithRiskData()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertNotNull($transaction->riskData);
+ $this->assertNotNull($transaction->riskData->decision);
+ }
+
+ function testRecurring()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'recurring' => true,
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(true, $transaction->recurring);
+ }
+
+ function testSale_withServiceFee()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '10.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'serviceFeeAmount' => '1.00'
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('1.00', $transaction->serviceFeeAmount);
+ }
+
+ function testSale_isInvalidIfTransactionMerchantAccountIsNotSub()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '10.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'serviceFeeAmount' => '1.00'
+ ));
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+ $serviceFeeErrors = $result->errors->forKey('transaction')->onAttribute('serviceFeeAmount');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_SERVICE_FEE_AMOUNT_NOT_ALLOWED_ON_MASTER_MERCHANT_ACCOUNT, $serviceFeeErrors[0]->code);
+ }
+
+ function testSale_isInvalidIfSubMerchantAccountHasNoServiceFee()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '10.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+ $serviceFeeErrors = $result->errors->forKey('transaction')->onAttribute('merchantAccountId');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_SUB_MERCHANT_ACCOUNT_REQUIRES_SERVICE_FEE_AMOUNT, $serviceFeeErrors[0]->code);
+ }
+
+ function testSale_withVenmoSdkSession()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '10.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'venmoSdkSession' => Braintree_Test_VenmoSdk::getTestSession()
+ )
+ ));
+ $this->assertEquals(true, $result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(true, $transaction->creditCardDetails->venmoSdk);
+ }
+
+ function testSale_withVenmoSdkPaymentMethodCode()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '10.00',
+ 'venmoSdkPaymentMethodCode' => Braintree_Test_VenmoSdk::$visaPaymentMethodCode
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals("411111", $transaction->creditCardDetails->bin);
+ }
+
+ function testSale_withLevel2Attributes()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'expirationDate' => '05/2011',
+ 'number' => '5105105105105100'
+ ),
+ 'taxExempt' => true,
+ 'taxAmount' => '10.00',
+ 'purchaseOrderNumber' => '12345'
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $this->assertTrue($transaction->taxExempt);
+ $this->assertEquals('10.00', $transaction->taxAmount);
+ $this->assertEquals('12345', $transaction->purchaseOrderNumber);
+ }
+
+ function testSale_withInvalidTaxAmountAttribute()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'expirationDate' => '05/2011',
+ 'number' => '5105105105105100'
+ ),
+ 'taxAmount' => 'abc'
+ ));
+
+ $this->assertFalse($result->success);
+
+ $taxAmountErrors = $result->errors->forKey('transaction')->onAttribute('taxAmount');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_TAX_AMOUNT_FORMAT_IS_INVALID, $taxAmountErrors[0]->code);
+ }
+
+ function testSale_withServiceFeeTooLarge()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '10.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'serviceFeeAmount' => '20.00'
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('serviceFeeAmount');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_SERVICE_FEE_AMOUNT_IS_TOO_LARGE, $errors[0]->code);
+ }
+
+ function testSale_withTooLongPurchaseOrderAttribute()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'expirationDate' => '05/2011',
+ 'number' => '5105105105105100'
+ ),
+ 'purchaseOrderNumber' => 'aaaaaaaaaaaaaaaaaa'
+ ));
+
+ $this->assertFalse($result->success);
+
+ $purchaseOrderNumberErrors = $result->errors->forKey('transaction')->onAttribute('purchaseOrderNumber');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_PURCHASE_ORDER_NUMBER_IS_TOO_LONG, $purchaseOrderNumberErrors[0]->code);
+ }
+
+ function testSale_withInvalidPurchaseOrderNumber()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'expirationDate' => '05/2011',
+ 'number' => '5105105105105100'
+ ),
+ 'purchaseOrderNumber' => "\x80\x90\xA0"
+ ));
+
+ $this->assertFalse($result->success);
+
+ $purchaseOrderNumberErrors = $result->errors->forKey('transaction')->onAttribute('purchaseOrderNumber');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_PURCHASE_ORDER_NUMBER_IS_INVALID, $purchaseOrderNumberErrors[0]->code);
+ }
+
+ function testSale_withAllAttributes()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'orderId' => '123',
+ 'channel' => 'MyShoppingCardProvider',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/2011',
+ 'cvv' => '123'
+ ),
+ 'customer' => array(
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'email' => 'dan@example.com',
+ 'phone' => '419-555-1234',
+ 'fax' => '419-555-1235',
+ 'website' => 'http://braintreepayments.com'
+ ),
+ 'billing' => array(
+ 'firstName' => 'Carl',
+ 'lastName' => 'Jones',
+ 'company' => 'Braintree',
+ 'streetAddress' => '123 E Main St',
+ 'extendedAddress' => 'Suite 403',
+ 'locality' => 'Chicago',
+ 'region' => 'IL',
+ 'postalCode' => '60622',
+ 'countryName' => 'United States of America',
+ 'countryCodeAlpha2' => 'US',
+ 'countryCodeAlpha3' => 'USA',
+ 'countryCodeNumeric' => '840'
+ ),
+ 'shipping' => array(
+ 'firstName' => 'Andrew',
+ 'lastName' => 'Mason',
+ 'company' => 'Braintree',
+ 'streetAddress' => '456 W Main St',
+ 'extendedAddress' => 'Apt 2F',
+ 'locality' => 'Bartlett',
+ 'region' => 'IL',
+ 'postalCode' => '60103',
+ 'countryName' => 'United States of America',
+ 'countryCodeAlpha2' => 'US',
+ 'countryCodeAlpha3' => 'USA',
+ 'countryCodeNumeric' => '840'
+ )
+ ));
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+
+ $this->assertNotNull($transaction->id);
+ $this->assertNotNull($transaction->createdAt);
+ $this->assertNotNull($transaction->updatedAt);
+ $this->assertNull($transaction->refundId);
+
+ $this->assertEquals(Braintree_TestHelper::defaultMerchantAccountId(), $transaction->merchantAccountId);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals('USD', $transaction->currencyIsoCode);
+ $this->assertEquals('123', $transaction->orderId);
+ $this->assertEquals('MyShoppingCardProvider', $transaction->channel);
+ $this->assertEquals('MasterCard', $transaction->creditCardDetails->cardType);
+ $this->assertEquals('1000', $transaction->processorResponseCode);
+ $this->assertEquals('Approved', $transaction->processorResponseText);
+ $this->assertNull($transaction->voiceReferralNumber);
+ $this->assertFalse($transaction->taxExempt);
+
+ $this->assertEquals('M', $transaction->avsPostalCodeResponseCode);
+ $this->assertEquals('M', $transaction->avsStreetAddressResponseCode);
+ $this->assertEquals('M', $transaction->cvvResponseCode);
+
+ $this->assertEquals('Dan', $transaction->customerDetails->firstName);
+ $this->assertEquals('Smith', $transaction->customerDetails->lastName);
+ $this->assertEquals('Braintree', $transaction->customerDetails->company);
+ $this->assertEquals('dan@example.com', $transaction->customerDetails->email);
+ $this->assertEquals('419-555-1234', $transaction->customerDetails->phone);
+ $this->assertEquals('419-555-1235', $transaction->customerDetails->fax);
+ $this->assertEquals('http://braintreepayments.com', $transaction->customerDetails->website);
+
+ $this->assertEquals('Carl', $transaction->billingDetails->firstName);
+ $this->assertEquals('Jones', $transaction->billingDetails->lastName);
+ $this->assertEquals('Braintree', $transaction->billingDetails->company);
+ $this->assertEquals('123 E Main St', $transaction->billingDetails->streetAddress);
+ $this->assertEquals('Suite 403', $transaction->billingDetails->extendedAddress);
+ $this->assertEquals('Chicago', $transaction->billingDetails->locality);
+ $this->assertEquals('IL', $transaction->billingDetails->region);
+ $this->assertEquals('60622', $transaction->billingDetails->postalCode);
+ $this->assertEquals('United States of America', $transaction->billingDetails->countryName);
+ $this->assertEquals('US', $transaction->billingDetails->countryCodeAlpha2);
+ $this->assertEquals('USA', $transaction->billingDetails->countryCodeAlpha3);
+ $this->assertEquals('840', $transaction->billingDetails->countryCodeNumeric);
+
+ $this->assertEquals('Andrew', $transaction->shippingDetails->firstName);
+ $this->assertEquals('Mason', $transaction->shippingDetails->lastName);
+ $this->assertEquals('Braintree', $transaction->shippingDetails->company);
+ $this->assertEquals('456 W Main St', $transaction->shippingDetails->streetAddress);
+ $this->assertEquals('Apt 2F', $transaction->shippingDetails->extendedAddress);
+ $this->assertEquals('Bartlett', $transaction->shippingDetails->locality);
+ $this->assertEquals('IL', $transaction->shippingDetails->region);
+ $this->assertEquals('60103', $transaction->shippingDetails->postalCode);
+ $this->assertEquals('United States of America', $transaction->shippingDetails->countryName);
+ $this->assertEquals('US', $transaction->shippingDetails->countryCodeAlpha2);
+ $this->assertEquals('USA', $transaction->shippingDetails->countryCodeAlpha3);
+ $this->assertEquals('840', $transaction->shippingDetails->countryCodeNumeric);
+
+ $this->assertNotNull($transaction->processorAuthorizationCode);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ $this->assertEquals('510510******5100', $transaction->creditCardDetails->maskedNumber);
+ $this->assertEquals('The Cardholder', $transaction->creditCardDetails->cardholderName);
+ $this->assertEquals('05', $transaction->creditCardDetails->expirationMonth);
+ $this->assertEquals('2011', $transaction->creditCardDetails->expirationYear);
+ $this->assertNotNull($transaction->creditCardDetails->imageUrl);
+ }
+
+ function testSale_withCustomFields()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'customFields' => array(
+ 'store_me' => 'custom value'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $customFields = $transaction->customFields;
+ $this->assertEquals('custom value', $customFields['store_me']);
+ }
+
+ function testSale_withExpirationMonthAndYear()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationMonth' => '5',
+ 'expirationYear' => '2012'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('05', $transaction->creditCardDetails->expirationMonth);
+ $this->assertEquals('2012', $transaction->creditCardDetails->expirationYear);
+ }
+
+ function testSale_underscoresAllCustomFields()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'customFields' => array(
+ 'storeMe' => 'custom value'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $customFields = $transaction->customFields;
+ $this->assertEquals('custom value', $customFields['store_me']);
+ }
+
+ function testSale_withInvalidCustomField()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'customFields' => array(
+ 'invalidKey' => 'custom value'
+ )
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('customFields');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_CUSTOM_FIELD_IS_INVALID, $errors[0]->code);
+ $this->assertEquals('Custom field is invalid: invalidKey.', $errors[0]->message);
+ }
+
+ function testSale_withMerchantAccountId()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_TestHelper::nonDefaultMerchantAccountId(), $transaction->merchantAccountId);
+ }
+
+ function testSale_withoutMerchantAccountIdFallsBackToDefault()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_TestHelper::defaultMerchantAccountId(), $transaction->merchantAccountId);
+ }
+
+ function testSale_withShippingAddressId()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/12'
+ )
+ ))->customer;
+
+ $address = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'streetAddress' => '123 Fake St.'
+ ))->address;
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'customerId' => $customer->id,
+ 'shippingAddressId' => $address->id
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('123 Fake St.', $transaction->shippingDetails->streetAddress);
+ $this->assertEquals($address->id, $transaction->shippingDetails->id);
+ }
+
+ function testSale_withBillingAddressId()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/12'
+ )
+ ))->customer;
+
+ $address = Braintree_Address::create(array(
+ 'customerId' => $customer->id,
+ 'streetAddress' => '123 Fake St.'
+ ))->address;
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'customerId' => $customer->id,
+ 'billingAddressId' => $address->id
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('123 Fake St.', $transaction->billingDetails->streetAddress);
+ $this->assertEquals($address->id, $transaction->billingDetails->id);
+ }
+
+ function testSaleNoValidate()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ }
+
+ function testSale_withProcessorDecline()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$decline,
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Transaction::PROCESSOR_DECLINED, $result->transaction->status);
+ $this->assertEquals(2000, $result->transaction->processorResponseCode);
+ $this->assertEquals("Do Not Honor", $result->transaction->processorResponseText);
+ $this->assertEquals("2000 : Do Not Honor", $result->transaction->additionalProcessorResponse);
+ }
+
+ function testSale_withExistingCustomer()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com'
+ ))->customer;
+
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'customerId' => $customer->id,
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/12'
+ )
+ ))->transaction;
+ $this->assertEquals($transaction->creditCardDetails->maskedNumber, '401288******1881');
+ $this->assertNull($transaction->vaultCreditCard());
+ }
+
+ function testSale_andStoreShippingAddressInVault()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com'
+ ))->customer;
+
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'customerId' => $customer->id,
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/12'
+ ),
+ 'shipping' => array(
+ 'firstName' => 'Darren',
+ 'lastName' => 'Stevens'
+ ),
+ 'options' => array(
+ 'storeInVault' => true,
+ 'storeShippingAddressInVault' => true
+ )
+ ))->transaction;
+
+ $customer = Braintree_Customer::find($customer->id);
+ $this->assertEquals('Darren', $customer->addresses[0]->firstName);
+ $this->assertEquals('Stevens', $customer->addresses[0]->lastName);
+ }
+
+ function testSale_withExistingCustomer_storeInVault()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jones',
+ 'company' => 'Jones Co.',
+ 'email' => 'mike.jones@example.com',
+ 'phone' => '419.555.1234',
+ 'fax' => '419.555.1235',
+ 'website' => 'http://example.com'
+ ))->customer;
+
+ $transaction = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'customerId' => $customer->id,
+ 'creditCard' => array(
+ 'cardholderName' => 'The Cardholder',
+ 'number' => Braintree_Test_CreditCardNumbers::$visa,
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'storeInVault' => true
+ )
+ ))->transaction;
+ $this->assertEquals($transaction->creditCardDetails->maskedNumber, '401288******1881');
+ $this->assertEquals($transaction->vaultCreditCard()->maskedNumber, '401288******1881');
+ }
+
+ function testCredit()
+ {
+ $result = Braintree_Transaction::credit(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::CREDIT, $transaction->type);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ }
+
+ function testCreditNoValidate()
+ {
+ $transaction = Braintree_Transaction::creditNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::CREDIT, $transaction->type);
+ $this->assertEquals(Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT, $transaction->status);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ }
+
+ function testCredit_withMerchantAccountId()
+ {
+ $result = Braintree_Transaction::credit(array(
+ 'amount' => '100.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_TestHelper::nonDefaultMerchantAccountId(), $transaction->merchantAccountId);
+ }
+
+ function testCredit_withoutMerchantAccountIdFallsBackToDefault()
+ {
+ $result = Braintree_Transaction::credit(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_TestHelper::defaultMerchantAccountId(), $transaction->merchantAccountId);
+ }
+
+ function testCredit_withServiceFeeNotAllowed()
+ {
+ $result = Braintree_Transaction::credit(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'serviceFeeAmount' => '12.75'
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_SERVICE_FEE_IS_NOT_ALLOWED_ON_CREDITS, $errors[0]->code);
+ }
+
+ function testSubmitForSettlement_nullAmount()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $submitResult = Braintree_Transaction::submitForSettlement($transaction->id);
+ $this->assertEquals(true, $submitResult->success);
+ $this->assertEquals(Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT, $submitResult->transaction->status);
+ $this->assertEquals('100.00', $submitResult->transaction->amount);
+ }
+
+ function testSubmitForSettlement_amountLessThanServiceFee()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '10.00',
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'serviceFeeAmount' => '5.00'
+ ));
+ $submitResult = Braintree_Transaction::submitForSettlement($transaction->id, '1.00');
+ $errors = $submitResult->errors->forKey('transaction')->onAttribute('amount');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_SETTLEMENT_AMOUNT_IS_LESS_THAN_SERVICE_FEE_AMOUNT, $errors[0]->code);
+ }
+
+ function testSubmitForSettlement_withAmount()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $submitResult = Braintree_Transaction::submitForSettlement($transaction->id, '50.00');
+ $this->assertEquals(true, $submitResult->success);
+ $this->assertEquals(Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT, $submitResult->transaction->status);
+ $this->assertEquals('50.00', $submitResult->transaction->amount);
+ }
+
+ function testSubmitForSettlementNoValidate_whenValidWithoutAmount()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $submittedTransaction = Braintree_Transaction::submitForSettlementNoValidate($transaction->id);
+ $this->assertEquals(Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT, $submittedTransaction->status);
+ $this->assertEquals('100.00', $submittedTransaction->amount);
+ }
+
+ function testSubmitForSettlementNoValidate_whenValidWithAmount()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $submittedTransaction = Braintree_Transaction::submitForSettlementNoValidate($transaction->id, '99.00');
+ $this->assertEquals(Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT, $submittedTransaction->status);
+ $this->assertEquals('99.00', $submittedTransaction->amount);
+ }
+
+ function testSubmitForSettlementNoValidate_whenInvalid()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ $submittedTransaction = Braintree_Transaction::submitForSettlementNoValidate($transaction->id, '101.00');
+ }
+
+ function testVoid()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $voidResult = Braintree_Transaction::void($transaction->id);
+ $this->assertEquals(true, $voidResult->success);
+ $this->assertEquals(Braintree_Transaction::VOIDED, $voidResult->transaction->status);
+ }
+
+ function test_countryValidationError_inconsistency()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'billing' => array(
+ 'countryCodeAlpha2' => 'AS',
+ 'countryCodeAlpha3' => 'USA'
+ )
+ ));
+ $this->assertFalse($result->success);
+
+ $errors = $result->errors->forKey('transaction')->forKey('billing')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_INCONSISTENT_COUNTRY, $errors[0]->code);
+ }
+
+ function test_countryValidationError_incorrectAlpha2()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'billing' => array(
+ 'countryCodeAlpha2' => 'ZZ'
+ )
+ ));
+ $this->assertFalse($result->success);
+
+ $errors = $result->errors->forKey('transaction')->forKey('billing')->onAttribute('countryCodeAlpha2');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_CODE_ALPHA2_IS_NOT_ACCEPTED, $errors[0]->code);
+ }
+
+ function test_countryValidationError_incorrectAlpha3()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'billing' => array(
+ 'countryCodeAlpha3' => 'ZZZ'
+ )
+ ));
+ $this->assertFalse($result->success);
+
+ $errors = $result->errors->forKey('transaction')->forKey('billing')->onAttribute('countryCodeAlpha3');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_CODE_ALPHA3_IS_NOT_ACCEPTED, $errors[0]->code);
+ }
+
+ function test_countryValidationError_incorrectNumericCode()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'billing' => array(
+ 'countryCodeNumeric' => '000'
+ )
+ ));
+ $this->assertFalse($result->success);
+
+ $errors = $result->errors->forKey('transaction')->forKey('billing')->onAttribute('countryCodeNumeric');
+ $this->assertEquals(Braintree_Error_Codes::ADDRESS_COUNTRY_CODE_NUMERIC_IS_NOT_ACCEPTED, $errors[0]->code);
+ }
+
+ function testVoid_withValidationError()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $voided = Braintree_Transaction::voidNoValidate($transaction->id);
+ $this->assertEquals(Braintree_Transaction::VOIDED, $voided->status);
+ $result = Braintree_Transaction::void($transaction->id);
+ $this->assertEquals(false, $result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_CANNOT_BE_VOIDED, $errors[0]->code);
+ }
+
+ function testVoidNoValidate()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $voided = Braintree_Transaction::voidNoValidate($transaction->id);
+ $this->assertEquals(Braintree_Transaction::VOIDED, $voided->status);
+ }
+
+ function testVoidNoValidate_throwsIfNotInvalid()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $voided = Braintree_Transaction::voidNoValidate($transaction->id);
+ $this->assertEquals(Braintree_Transaction::VOIDED, $voided->status);
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ $voided = Braintree_Transaction::voidNoValidate($transaction->id);
+ }
+
+ function testFind()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $transaction = Braintree_Transaction::find($result->transaction->id);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $transaction->status);
+ $this->assertEquals(Braintree_Transaction::SALE, $transaction->type);
+ $this->assertEquals('100.00', $transaction->amount);
+ $this->assertEquals('510510', $transaction->creditCardDetails->bin);
+ $this->assertEquals('5100', $transaction->creditCardDetails->last4);
+ }
+
+ function testFindExposesDisbursementDetails()
+ {
+ $transaction = Braintree_Transaction::find("deposittransaction");
+
+ $this->assertEquals(true, $transaction->isDisbursed());
+
+ $disbursementDetails = $transaction->disbursementDetails;
+ $this->assertEquals('100.00', $disbursementDetails->settlementAmount);
+ $this->assertEquals('USD', $disbursementDetails->settlementCurrencyIsoCode);
+ $this->assertEquals('1', $disbursementDetails->settlementCurrencyExchangeRate);
+ $this->assertEquals(false, $disbursementDetails->fundsHeld);
+ $this->assertEquals(true, $disbursementDetails->success);
+ $this->assertEquals(new DateTime('2013-04-10'), $disbursementDetails->disbursementDate);
+ }
+
+ function testFindExposesDisputes()
+ {
+ $transaction = Braintree_Transaction::find("disputedtransaction");
+
+ $dispute = $transaction->disputes[0];
+ $this->assertEquals('250.00', $dispute->amount);
+ $this->assertEquals('USD', $dispute->currencyIsoCode);
+ $this->assertEquals(Braintree_Dispute::FRAUD, $dispute->reason);
+ $this->assertEquals(Braintree_Dispute::WON, $dispute->status);
+ $this->assertEquals(new DateTime('2014-03-01'), $dispute->receivedDate);
+ $this->assertEquals(new DateTime('2014-03-21'), $dispute->replyByDate);
+ $this->assertEquals("disputedtransaction", $dispute->transactionDetails->id);
+ $this->assertEquals("1000.00", $dispute->transactionDetails->amount);
+ }
+
+ function testFindExposesThreeDSecureInfo()
+ {
+ $transaction = Braintree_Transaction::find("threedsecuredtransaction");
+
+ $info = $transaction->threeDSecureInfo;
+ $this->assertEquals("Y", $info->enrolled);
+ $this->assertEquals("authenticate_successful", $info->status);
+ $this->assertTrue($info->liabilityShifted);
+ $this->assertTrue($info->liabilityShiftPossible);
+ }
+
+ function testFindExposesNullThreeDSecureInfo()
+ {
+ $transaction = Braintree_Transaction::find("settledtransaction");
+
+ $this->assertNull($transaction->threeDSecureInfo);
+ }
+
+ function testFindExposesRetrievals()
+ {
+ $transaction = Braintree_Transaction::find("retrievaltransaction");
+
+ $dispute = $transaction->disputes[0];
+ $this->assertEquals('1000.00', $dispute->amount);
+ $this->assertEquals('USD', $dispute->currencyIsoCode);
+ $this->assertEquals(Braintree_Dispute::RETRIEVAL, $dispute->reason);
+ $this->assertEquals(Braintree_Dispute::OPEN, $dispute->status);
+ $this->assertEquals("retrievaltransaction", $dispute->transactionDetails->id);
+ $this->assertEquals("1000.00", $dispute->transactionDetails->amount);
+ }
+
+ function testFindExposesPayPalDetails()
+ {
+ $transaction = Braintree_Transaction::find("settledtransaction");
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->assertNotNull($transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->authorizationId);
+ $this->assertNotNull($transaction->paypalDetails->payerId);
+ $this->assertNotNull($transaction->paypalDetails->payerFirstName);
+ $this->assertNotNull($transaction->paypalDetails->payerLastName);
+ $this->assertNotNull($transaction->paypalDetails->sellerProtectionStatus);
+ $this->assertNotNull($transaction->paypalDetails->captureId);
+ $this->assertNotNull($transaction->paypalDetails->refundId);
+ }
+
+ function testSale_storeInVault()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Card Holder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'customer' => array(
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'email' => 'dan@example.com',
+ 'phone' => '419-555-1234',
+ 'fax' => '419-555-1235',
+ 'website' => 'http://getbraintree.com'
+ ),
+ 'options' => array(
+ 'storeInVault' => true
+ )
+ ));
+ $this->assertNotNull($transaction->creditCardDetails->token);
+ $creditCard = $transaction->vaultCreditCard();
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('Card Holder', $creditCard->cardholderName);
+ $customer = $transaction->vaultCustomer();
+ $this->assertEquals('Dan', $customer->firstName);
+ $this->assertEquals('Smith', $customer->lastName);
+ $this->assertEquals('Braintree', $customer->company);
+ $this->assertEquals('dan@example.com', $customer->email);
+ $this->assertEquals('419-555-1234', $customer->phone);
+ $this->assertEquals('419-555-1235', $customer->fax);
+ $this->assertEquals('http://getbraintree.com', $customer->website);
+ }
+
+ function testSale_storeInVaultOnSuccessWithSuccessfulTransaction()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'cardholderName' => 'Card Holder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'customer' => array(
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'email' => 'dan@example.com',
+ 'phone' => '419-555-1234',
+ 'fax' => '419-555-1235',
+ 'website' => 'http://getbraintree.com'
+ ),
+ 'options' => array(
+ 'storeInVaultOnSuccess' => true
+ )
+ ));
+ $this->assertNotNull($transaction->creditCardDetails->token);
+ $creditCard = $transaction->vaultCreditCard();
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('Card Holder', $creditCard->cardholderName);
+ $customer = $transaction->vaultCustomer();
+ $this->assertEquals('Dan', $customer->firstName);
+ $this->assertEquals('Smith', $customer->lastName);
+ $this->assertEquals('Braintree', $customer->company);
+ $this->assertEquals('dan@example.com', $customer->email);
+ $this->assertEquals('419-555-1234', $customer->phone);
+ $this->assertEquals('419-555-1235', $customer->fax);
+ $this->assertEquals('http://getbraintree.com', $customer->website);
+ }
+
+ function testSale_storeInVaultOnSuccessWithFailedTransaction()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$decline,
+ 'creditCard' => array(
+ 'cardholderName' => 'Card Holder',
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'customer' => array(
+ 'firstName' => 'Dan',
+ 'lastName' => 'Smith',
+ 'company' => 'Braintree',
+ 'email' => 'dan@example.com',
+ 'phone' => '419-555-1234',
+ 'fax' => '419-555-1235',
+ 'website' => 'http://getbraintree.com'
+ ),
+ 'options' => array(
+ 'storeInVaultOnSuccess' => true
+ )
+ ));
+ $transaction = $result->transaction;
+ $this->assertNull($transaction->creditCardDetails->token);
+ $this->assertNull($transaction->vaultCreditCard());
+ $this->assertNull($transaction->customerDetails->id);
+ $this->assertNull($transaction->vaultCustomer());
+ }
+
+ function testSale_withFraudParams()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'deviceSessionId' => '123abc',
+ 'fraudMerchantId' => '456',
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ }
+
+ function testSale_withDescriptor()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'descriptor' => array(
+ 'name' => '123*123456789012345678',
+ 'phone' => '3334445555',
+ 'url' => 'ebay.com'
+ )
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('123*123456789012345678', $transaction->descriptor->name);
+ $this->assertEquals('3334445555', $transaction->descriptor->phone);
+ $this->assertEquals('ebay.com', $transaction->descriptor->url);
+ }
+
+ function testSale_withDescriptorValidation()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'descriptor' => array(
+ 'name' => 'badcompanyname12*badproduct12',
+ 'phone' => '%bad4445555',
+ 'url' => '12345678901234'
+ )
+ ));
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+
+ $errors = $result->errors->forKey('transaction')->forKey('descriptor')->onAttribute('name');
+ $this->assertEquals(Braintree_Error_Codes::DESCRIPTOR_NAME_FORMAT_IS_INVALID, $errors[0]->code);
+
+ $errors = $result->errors->forKey('transaction')->forKey('descriptor')->onAttribute('phone');
+ $this->assertEquals(Braintree_Error_Codes::DESCRIPTOR_PHONE_FORMAT_IS_INVALID, $errors[0]->code);
+
+ $errors = $result->errors->forKey('transaction')->forKey('descriptor')->onAttribute('url');
+ $this->assertEquals(Braintree_Error_Codes::DESCRIPTOR_URL_FORMAT_IS_INVALID, $errors[0]->code);
+ }
+
+ function testSale_withHoldInEscrow()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'holdInEscrow' => true
+ ),
+ 'serviceFeeAmount' => '1.00'
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::ESCROW_HOLD_PENDING, $transaction->escrowStatus);
+ }
+
+ function testSale_withHoldInEscrowFailsForMasterMerchantAccount()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'holdInEscrow' => true
+ )
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('base');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_CANNOT_HOLD_IN_ESCROW,
+ $errors[0]->code
+ );
+ }
+
+ function testSale_withThreeDSecureOptionRequired()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonce_for_new_card(array(
+ "creditCard" => array(
+ "number" => "4111111111111111",
+ "expirationMonth" => "11",
+ "expirationYear" => "2099"
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::threeDSecureMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/09'
+ ),
+ 'options' => array(
+ 'three_d_secure' => array(
+ 'required' => true
+ )
+ )
+ ));
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Transaction::THREE_D_SECURE, $result->transaction->gatewayRejectionReason);
+ }
+
+ function testSale_withThreeDSecureToken()
+ {
+ $threeDSecureToken = Braintree_TestHelper::create3DSVerification(
+ Braintree_TestHelper::threeDSecureMerchantAccountId(),
+ array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '05',
+ 'expirationYear' => '2009'
+ )
+ );
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::threeDSecureMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/09'
+ ),
+ 'threeDSecureToken' => $threeDSecureToken
+ ));
+ $this->assertTrue($result->success);
+ }
+
+ function testSale_returnsErrorIfThreeDSecureToken()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::threeDSecureMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/09'
+ ),
+ 'threeDSecureToken' => NULL
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('threeDSecureToken');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_THREE_D_SECURE_TOKEN_IS_INVALID,
+ $errors[0]->code
+ );
+ }
+
+ function testSale_returnsErrorIf3dsLookupDataDoesNotMatchTransactionData()
+ {
+ $threeDSecureToken = Braintree_TestHelper::create3DSVerification(
+ Braintree_TestHelper::threeDSecureMerchantAccountId(),
+ array(
+ 'number' => '4111111111111111',
+ 'expirationMonth' => '05',
+ 'expirationYear' => '2009'
+ )
+ );
+
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::threeDSecureMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/09'
+ ),
+ 'threeDSecureToken' => $threeDSecureToken
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('threeDSecureToken');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_THREE_D_SECURE_TRANSACTION_DATA_DOESNT_MATCH_VERIFY,
+ $errors[0]->code
+ );
+ }
+
+ function testHoldInEscrow_afterSale()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'serviceFeeAmount' => '1.00'
+ ));
+ $result = Braintree_Transaction::holdInEscrow($result->transaction->id);
+ $this->assertTrue($result->success);
+ $this->assertEquals(Braintree_Transaction::ESCROW_HOLD_PENDING, $result->transaction->escrowStatus);
+ }
+
+ function testHoldInEscrow_afterSaleFailsWithMasterMerchantAccount()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $result = Braintree_Transaction::holdInEscrow($result->transaction->id);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('base');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_CANNOT_HOLD_IN_ESCROW,
+ $errors[0]->code
+ );
+ }
+
+ function testSubmitForRelease_FromEscrow()
+ {
+ $transaction = $this->createEscrowedTransaction();
+ $result = Braintree_Transaction::releaseFromEscrow($transaction->id);
+ $this->assertTrue($result->success);
+ $this->assertEquals(Braintree_Transaction::ESCROW_RELEASE_PENDING, $result->transaction->escrowStatus);
+ }
+
+ function testSubmitForRelease_fromEscrowFailsForTransactionsNotHeldInEscrow()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+ $result = Braintree_Transaction::releaseFromEscrow($result->transaction->id);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('base');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_CANNOT_RELEASE_FROM_ESCROW,
+ $errors[0]->code
+ );
+ }
+
+ function testCancelRelease_fromEscrow()
+ {
+ $transaction = $this->createEscrowedTransaction();
+ $result = Braintree_Transaction::releaseFromEscrow($transaction->id);
+ $result = Braintree_Transaction::cancelRelease($transaction->id);
+ $this->assertTrue($result->success);
+ $this->assertEquals(
+ Braintree_Transaction::ESCROW_HELD,
+ $result->transaction->escrowStatus
+ );
+ }
+
+ function testCancelRelease_fromEscrowFailsIfTransactionNotSubmittedForRelease()
+ {
+ $transaction = $this->createEscrowedTransaction();
+ $result = Braintree_Transaction::cancelRelease($transaction->id);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('base');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_CANNOT_CANCEL_RELEASE,
+ $errors[0]->code
+ );
+ }
+
+ function testCreateFromTransparentRedirect()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createTransactionViaTr(
+ array(
+ 'transaction' => array(
+ 'customer' => array(
+ 'first_name' => 'First'
+ ),
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ )
+ )
+ ),
+ array(
+ 'transaction' => array(
+ 'type' => Braintree_Transaction::SALE,
+ 'amount' => '100.00'
+ )
+ )
+ );
+ $result = Braintree_Transaction::createFromTransparentRedirect($queryString);
+ Braintree_TestHelper::assertPrintable($result);
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals(Braintree_Transaction::SALE, $result->transaction->type);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $result->transaction->status);
+ $creditCard = $result->transaction->creditCardDetails;
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('US', $creditCard->customerLocation);
+ $this->assertEquals('MasterCard', $creditCard->cardType);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('510510******5100', $creditCard->maskedNumber);
+ $customer = $result->transaction->customerDetails;
+ $this->assertequals('First', $customer->firstName);
+ }
+
+ function testCreateFromTransparentRedirectWithInvalidParams()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createTransactionViaTr(
+ array(
+ 'transaction' => array(
+ 'bad_key' => 'bad_value',
+ 'customer' => array(
+ 'first_name' => 'First'
+ ),
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ )
+ )
+ ),
+ array(
+ 'transaction' => array(
+ 'type' => Braintree_Transaction::SALE,
+ 'amount' => '100.00'
+ )
+ )
+ );
+ try {
+ $result = Braintree_Transaction::createFromTransparentRedirect($queryString);
+ $this->fail();
+ } catch (Braintree_Exception_Authorization $e) {
+ $this->assertEquals("Invalid params: transaction[bad_key]", $e->getMessage());
+ }
+ }
+
+ function testCreateFromTransparentRedirect_withParamsInTrData()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createTransactionViaTr(
+ array(
+ ),
+ array(
+ 'transaction' => array(
+ 'type' => Braintree_Transaction::SALE,
+ 'amount' => '100.00',
+ 'customer' => array(
+ 'firstName' => 'First'
+ ),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ )
+ )
+ );
+ $result = Braintree_Transaction::createFromTransparentRedirect($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals(Braintree_Transaction::SALE, $result->transaction->type);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $result->transaction->status);
+ $creditCard = $result->transaction->creditCardDetails;
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('US', $creditCard->customerLocation);
+ $this->assertEquals('MasterCard', $creditCard->cardType);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('510510******5100', $creditCard->maskedNumber);
+ $customer = $result->transaction->customerDetails;
+ $this->assertequals('First', $customer->firstName);
+ }
+
+ function testCreateFromTransparentRedirect_withValidationErrors()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $queryString = $this->createTransactionViaTr(
+ array(
+ 'transaction' => array(
+ 'customer' => array(
+ 'first_name' => str_repeat('x', 256),
+ ),
+ 'credit_card' => array(
+ 'number' => 'invalid',
+ 'expiration_date' => ''
+ )
+ )
+ ),
+ array(
+ 'transaction' => array('type' => Braintree_Transaction::SALE)
+ )
+ );
+ $result = Braintree_Transaction::createFromTransparentRedirect($queryString);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->forKey('customer')->onAttribute('firstName');
+ $this->assertEquals(Braintree_Error_Codes::CUSTOMER_FIRST_NAME_IS_TOO_LONG, $errors[0]->code);
+ $errors = $result->errors->forKey('transaction')->forKey('creditCard')->onAttribute('number');
+ $this->assertTrue(count($errors) > 0);
+ $errors = $result->errors->forKey('transaction')->forKey('creditCard')->onAttribute('expirationDate');
+ $this->assertEquals(Braintree_Error_Codes::CREDIT_CARD_EXPIRATION_DATE_IS_REQUIRED, $errors[0]->code);
+ }
+
+ function testRefund()
+ {
+ $transaction = $this->createTransactionToRefund();
+ $result = Braintree_Transaction::refund($transaction->id);
+ $this->assertTrue($result->success);
+ $refund = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::CREDIT, $refund->type);
+ $this->assertEquals($transaction->id, $refund->refundedTransactionId);
+ $this->assertEquals($refund->id, Braintree_Transaction::find($transaction->id)->refundId);
+ }
+
+ function testRefundWithPartialAmount()
+ {
+ $transaction = $this->createTransactionToRefund();
+ $result = Braintree_Transaction::refund($transaction->id, '50.00');
+ $this->assertTrue($result->success);
+ $this->assertEquals(Braintree_Transaction::CREDIT, $result->transaction->type);
+ $this->assertEquals("50.00", $result->transaction->amount);
+ }
+
+ function testMultipleRefundsWithPartialAmounts()
+ {
+ $transaction = $this->createTransactionToRefund();
+
+ $transaction1 = Braintree_Transaction::refund($transaction->id, '50.00')->transaction;
+ $this->assertEquals(Braintree_Transaction::CREDIT, $transaction1->type);
+ $this->assertEquals("50.00", $transaction1->amount);
+
+ $transaction2 = Braintree_Transaction::refund($transaction->id, '50.00')->transaction;
+ $this->assertEquals(Braintree_Transaction::CREDIT, $transaction2->type);
+ $this->assertEquals("50.00", $transaction2->amount);
+
+ $transaction = Braintree_Transaction::find($transaction->id);
+
+ $expectedRefundIds = array($transaction1->id, $transaction2->id);
+ $refundIds = $transaction->refundIds;
+ sort($expectedRefundIds);
+ sort($refundIds);
+
+ $this->assertEquals($expectedRefundIds, $refundIds);
+ }
+
+ function testRefundWithUnsuccessfulPartialAmount()
+ {
+ $transaction = $this->createTransactionToRefund();
+ $result = Braintree_Transaction::refund($transaction->id, '150.00');
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->onAttribute('amount');
+ $this->assertEquals(
+ Braintree_Error_Codes::TRANSACTION_REFUND_AMOUNT_IS_TOO_LARGE,
+ $errors[0]->code
+ );
+ }
+
+ function testGatewayRejectionOnApplicationIncomplete()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+
+ $result = $gateway->merchant()->create(array(
+ 'email' => 'name@email.com',
+ 'countryCodeAlpha3' => 'USA',
+ 'paymentMethods' => array('credit_card', 'paypal')
+ ));
+
+ $gateway = new Braintree_Gateway(array(
+ 'accessToken' => $result->credentials->accessToken,
+ ));
+
+ $result = $gateway->transaction()->sale(array(
+ 'amount' => '4000.00',
+ 'creditCard' => array(
+ 'number' => '4111111111111111',
+ 'expirationDate' => '05/20'
+ )
+ ));
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::APPLICATION_INCOMPLETE, $transaction->gatewayRejectionReason);
+ }
+
+ function testGatewayRejectionOnAvs()
+ {
+ $old_merchant_id = Braintree_Configuration::merchantId();
+ $old_public_key = Braintree_Configuration::publicKey();
+ $old_private_key = Braintree_Configuration::privateKey();
+
+ Braintree_Configuration::merchantId('processing_rules_merchant_id');
+ Braintree_Configuration::publicKey('processing_rules_public_key');
+ Braintree_Configuration::privateKey('processing_rules_private_key');
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'billing' => array(
+ 'streetAddress' => '200 2nd Street'
+ ),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ )
+ ));
+
+ Braintree_Configuration::merchantId($old_merchant_id);
+ Braintree_Configuration::publicKey($old_public_key);
+ Braintree_Configuration::privateKey($old_private_key);
+
+ $this->assertFalse($result->success);
+ Braintree_TestHelper::assertPrintable($result);
+ $transaction = $result->transaction;
+
+ $this->assertEquals(Braintree_Transaction::AVS, $transaction->gatewayRejectionReason);
+ }
+
+ function testGatewayRejectionOnAvsAndCvv()
+ {
+ $old_merchant_id = Braintree_Configuration::merchantId();
+ $old_public_key = Braintree_Configuration::publicKey();
+ $old_private_key = Braintree_Configuration::privateKey();
+
+ Braintree_Configuration::merchantId('processing_rules_merchant_id');
+ Braintree_Configuration::publicKey('processing_rules_public_key');
+ Braintree_Configuration::privateKey('processing_rules_private_key');
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'billing' => array(
+ 'postalCode' => '20000'
+ ),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '200'
+ )
+ ));
+
+ Braintree_Configuration::merchantId($old_merchant_id);
+ Braintree_Configuration::publicKey($old_public_key);
+ Braintree_Configuration::privateKey($old_private_key);
+
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+
+ $this->assertEquals(Braintree_Transaction::AVS_AND_CVV, $transaction->gatewayRejectionReason);
+ }
+
+ function testGatewayRejectionOnCvv()
+ {
+ $old_merchant_id = Braintree_Configuration::merchantId();
+ $old_public_key = Braintree_Configuration::publicKey();
+ $old_private_key = Braintree_Configuration::privateKey();
+
+ Braintree_Configuration::merchantId('processing_rules_merchant_id');
+ Braintree_Configuration::publicKey('processing_rules_public_key');
+ Braintree_Configuration::privateKey('processing_rules_private_key');
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ 'cvv' => '200'
+ )
+ ));
+
+ Braintree_Configuration::merchantId($old_merchant_id);
+ Braintree_Configuration::publicKey($old_public_key);
+ Braintree_Configuration::privateKey($old_private_key);
+
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+
+ $this->assertEquals(Braintree_Transaction::CVV, $transaction->gatewayRejectionReason);
+ }
+
+ function testGatewayRejectionOnFraud()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '4000111111111511',
+ 'expirationDate' => '05/17',
+ 'cvv' => '333'
+ )
+ ));
+
+ $this->assertFalse($result->success);
+ $this->assertEquals(Braintree_Transaction::FRAUD, $result->transaction->gatewayRejectionReason);
+ }
+
+ function testSnapshotPlanIdAddOnsAndDiscountsFromSubscription()
+ {
+ $creditCard = Braintree_SubscriptionTestHelper::createCreditCard();
+ $plan = Braintree_SubscriptionTestHelper::triallessPlan();
+ $result = Braintree_Subscription::create(array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'planId' => $plan['id'],
+ 'addOns' => array(
+ 'add' => array(
+ array(
+ 'amount' => '11.00',
+ 'inheritedFromId' => 'increase_10',
+ 'quantity' => 2,
+ 'numberOfBillingCycles' => 5
+ ),
+ array(
+ 'amount' => '21.00',
+ 'inheritedFromId' => 'increase_20',
+ 'quantity' => 3,
+ 'numberOfBillingCycles' => 6
+ )
+ ),
+ ),
+ 'discounts' => array(
+ 'add' => array(
+ array(
+ 'amount' => '7.50',
+ 'inheritedFromId' => 'discount_7',
+ 'quantity' => 2,
+ 'neverExpires' => true
+ )
+ )
+ )
+ ));
+
+ $transaction = $result->subscription->transactions[0];
+
+ $this->assertEquals($transaction->planId, $plan['id']);
+
+ $addOns = $transaction->addOns;
+ Braintree_SubscriptionTestHelper::sortModificationsById($addOns);
+
+ $this->assertEquals($addOns[0]->amount, "11.00");
+ $this->assertEquals($addOns[0]->id, "increase_10");
+ $this->assertEquals($addOns[0]->quantity, 2);
+ $this->assertEquals($addOns[0]->numberOfBillingCycles, 5);
+ $this->assertFalse($addOns[0]->neverExpires);
+
+ $this->assertEquals($addOns[1]->amount, "21.00");
+ $this->assertEquals($addOns[1]->id, "increase_20");
+ $this->assertEquals($addOns[1]->quantity, 3);
+ $this->assertEquals($addOns[1]->numberOfBillingCycles, 6);
+ $this->assertFalse($addOns[1]->neverExpires);
+
+ $discounts = $transaction->discounts;
+ $this->assertEquals($discounts[0]->amount, "7.50");
+ $this->assertEquals($discounts[0]->id, "discount_7");
+ $this->assertEquals($discounts[0]->quantity, 2);
+ $this->assertEquals($discounts[0]->numberOfBillingCycles, null);
+ $this->assertTrue($discounts[0]->neverExpires);
+ }
+
+ function createTransactionViaTr($regularParams, $trParams)
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $trData = Braintree_TransparentRedirect::transactionData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+ return Braintree_TestHelper::submitTrRequest(
+ Braintree_Transaction::createTransactionUrl(),
+ $regularParams,
+ $trData
+ );
+ }
+
+ function createTransactionToRefund()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array('submitForSettlement' => true)
+ ));
+ Braintree_TestHelper::settle($transaction->id);
+ return $transaction;
+ }
+
+ function createEscrowedTransaction()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'merchantAccountId' => Braintree_TestHelper::nonDefaultSubMerchantAccountId(),
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12'
+ ),
+ 'options' => array(
+ 'holdInEscrow' => true
+ ),
+ 'serviceFeeAmount' => '1.00'
+ ));
+ Braintree_TestHelper::escrow($result->transaction->id);
+ return $result->transaction;
+ }
+
+ function testCardTypeIndicators()
+ {
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::PREPAID,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals(Braintree_CreditCard::PREPAID_YES, $transaction->creditCardDetails->prepaid);
+
+ $prepaid_card_transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::COMMERCIAL,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals(Braintree_CreditCard::COMMERCIAL_YES, $prepaid_card_transaction->creditCardDetails->commercial);
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::PAYROLL,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals(Braintree_CreditCard::PAYROLL_YES, $transaction->creditCardDetails->payroll);
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::HEALTHCARE,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals(Braintree_CreditCard::HEALTHCARE_YES, $transaction->creditCardDetails->healthcare);
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::DURBIN_REGULATED,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals(Braintree_CreditCard::DURBIN_REGULATED_YES, $transaction->creditCardDetails->durbinRegulated);
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::DEBIT,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals(Braintree_CreditCard::DEBIT_YES, $transaction->creditCardDetails->debit);
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::ISSUING_BANK,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals("NETWORK ONLY", $transaction->creditCardDetails->issuingBank);
+
+ $transaction = Braintree_Transaction::saleNoValidate(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => Braintree_CreditCardNumbers_CardTypeIndicators::COUNTRY_OF_ISSUANCE,
+ 'expirationDate' => '05/12',
+ )
+ ));
+
+ $this->assertEquals("USA", $transaction->creditCardDetails->countryOfIssuance);
+ }
+
+
+ function testCreate_withVaultedPayPal()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $customer = Braintree_Customer::createNoValidate();
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ Braintree_PaymentMethod::create(array(
+ 'customerId' => $customer->id,
+ 'paymentMethodNonce' => $nonce
+ ));
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodToken' => $paymentMethodToken,
+ ));
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ }
+
+ function testCreate_withFuturePayPal()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withPayeeEmail()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'paypalAccount' => array(
+ 'payeeEmail' => 'payee@example.com'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->assertNotNull($transaction->paypalDetails->payeeEmail);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withPayeeEmailInOptions()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'paypalAccount' => array(),
+ 'options' => array(
+ 'payeeEmail' => 'payee@example.com'
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->assertNotNull($transaction->paypalDetails->payeeEmail);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withPayeeEmailInOptionsPayPal()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'paypalAccount' => array(),
+ 'options' => array(
+ 'paypal' => array(
+ 'payeeEmail' => 'payee@example.com'
+ )
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->assertNotNull($transaction->paypalDetails->payeeEmail);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withPayPalCustomField()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'paypalAccount' => array(),
+ 'options' => array(
+ 'paypal' => array(
+ 'customField' => 'custom field stuff'
+ )
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('custom field stuff', $transaction->paypalDetails->customField);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withPayPalReturnsPaymentInstrumentType()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_PaymentInstrumentType::PAYPAL_ACCOUNT, $transaction->paymentInstrumentType);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ }
+
+ function testCreate_withFuturePayPalAndVault()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'consent_code' => 'PAYPAL_CONSENT_CODE',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'storeInVault' => true
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $foundPayPalAccount = Braintree_PaymentMethod::find($paymentMethodToken);
+ $this->assertEquals($paymentMethodToken, $foundPayPalAccount->token);
+ }
+
+ function testCreate_withOnetimePayPal()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'access_token' => 'PAYPAL_ACCESS_TOKEN',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withOnetimePayPalAndDoesNotVault()
+ {
+ $paymentMethodToken = 'PAYPAL_TOKEN-' . strval(rand());
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'access_token' => 'PAYPAL_ACCESS_TOKEN',
+ 'token' => $paymentMethodToken
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'storeInVault' => true
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals('payer@example.com', $transaction->paypalDetails->payerEmail);
+ $this->assertNotNull($transaction->paypalDetails->imageUrl);
+ $this->assertNotNull($transaction->paypalDetails->debugId);
+ $this->setExpectedException('Braintree_Exception_NotFound');
+ Braintree_PaymentMethod::find($paymentMethodToken);
+ }
+
+ function testCreate_withPayPalAndSubmitForSettlement()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($result->success);
+ $transaction = $result->transaction;
+ $this->assertEquals(Braintree_Transaction::SETTLING, $transaction->status);
+ }
+
+ function testCreate_withPayPalHandlesBadUnvalidatedNonces()
+ {
+ $http = new Braintree_HttpClientApi(Braintree_Configuration::$global);
+ $nonce = $http->nonceForPayPalAccount(array(
+ 'paypal_account' => array(
+ 'access_token' => 'PAYPAL_ACCESS_TOKEN',
+ 'consent_code' => 'PAYPAL_CONSENT_CODE'
+ )
+ ));
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->forKey('paypalAccount')->errors;
+ $this->assertEquals(Braintree_Error_Codes::PAYPAL_ACCOUNT_CANNOT_HAVE_BOTH_ACCESS_TOKEN_AND_CONSENT_CODE, $errors[0]->code);
+ }
+
+ function testCreate_withPayPalHandlesNonExistentNonces()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => 'NON_EXISTENT_NONCE',
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->errors;
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_PAYMENT_METHOD_NONCE_UNKNOWN, $errors[0]->code);
+ }
+
+ function testVoid_withPayPal()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce
+ ));
+
+ $this->assertTrue($result->success);
+ $voided_transaction = Braintree_Transaction::voidNoValidate($result->transaction->id);
+ $this->assertEquals(Braintree_Transaction::VOIDED, $voided_transaction->status);
+ }
+
+ function testVoid_failsOnDeclinedPayPal()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$decline,
+ 'paymentMethodNonce' => $nonce
+ ));
+ $this->setExpectedException('Braintree_Exception_ValidationsFailed');
+ Braintree_Transaction::voidNoValidate($result->transaction->id);
+ }
+
+ function testRefund_withPayPal()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($transactionResult->success);
+ Braintree_TestHelper::settle($transactionResult->transaction->id);
+
+ $result = Braintree_Transaction::refund($transactionResult->transaction->id);
+ $this->assertTrue($result->success);
+ $this->assertEquals($result->transaction->type, Braintree_Transaction::CREDIT);
+ }
+
+ function testRefund_withPayPalAssignsRefundId()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($transactionResult->success);
+ $originalTransaction = $transactionResult->transaction;
+ Braintree_TestHelper::settle($transactionResult->transaction->id);
+
+ $result = Braintree_Transaction::refund($transactionResult->transaction->id);
+ $this->assertTrue($result->success);
+ $refundTransaction = $result->transaction;
+ $updatedOriginalTransaction = Braintree_Transaction::find($originalTransaction->id);
+ $this->assertEquals($refundTransaction->id, $updatedOriginalTransaction->refundId);
+ }
+
+ function testRefund_withPayPalAssignsRefundedTransactionId()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($transactionResult->success);
+ $originalTransaction = $transactionResult->transaction;
+ Braintree_TestHelper::settle($transactionResult->transaction->id);
+
+ $result = Braintree_Transaction::refund($transactionResult->transaction->id);
+ $this->assertTrue($result->success);
+ $refundTransaction = $result->transaction;
+ $this->assertEquals($refundTransaction->refundedTransactionId, $originalTransaction->id);
+ }
+
+ function testRefund_withPayPalFailsifAlreadyRefunded()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($transactionResult->success);
+ Braintree_TestHelper::settle($transactionResult->transaction->id);
+
+ $firstRefund = Braintree_Transaction::refund($transactionResult->transaction->id);
+ $this->assertTrue($firstRefund->success);
+ $secondRefund = Braintree_Transaction::refund($transactionResult->transaction->id);
+ $this->assertFalse($secondRefund->success);
+ $errors = $secondRefund->errors->forKey('transaction')->errors;
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_HAS_ALREADY_BEEN_REFUNDED, $errors[0]->code);
+ }
+
+ function testRefund_withPayPalFailsIfNotSettled()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ ));
+
+ $this->assertTrue($transactionResult->success);
+
+ $result = Braintree_Transaction::refund($transactionResult->transaction->id);
+ $this->assertFalse($result->success);
+ $errors = $result->errors->forKey('transaction')->errors;
+ $this->assertEquals(Braintree_Error_Codes::TRANSACTION_CANNOT_REFUND_UNLESS_SETTLED, $errors[0]->code);
+ }
+
+ function testRefund_partialWithPayPal()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($transactionResult->success);
+ Braintree_TestHelper::settle($transactionResult->transaction->id);
+
+ $result = Braintree_Transaction::refund(
+ $transactionResult->transaction->id,
+ $transactionResult->transaction->amount / 2
+ );
+
+ $this->assertTrue($result->success);
+ $this->assertEquals($result->transaction->type, Braintree_Transaction::CREDIT);
+ $this->assertEquals($result->transaction->amount, $transactionResult->transaction->amount / 2);
+ }
+
+ function testRefund_multiplePartialWithPayPal()
+ {
+ $nonce = Braintree_Test_Nonces::$paypalOneTimePayment;
+
+ $transactionResult = Braintree_Transaction::sale(array(
+ 'amount' => Braintree_Test_TransactionAmounts::$authorize,
+ 'paymentMethodNonce' => $nonce,
+ 'options' => array(
+ 'submitForSettlement' => true
+ )
+ ));
+
+ $this->assertTrue($transactionResult->success);
+ $originalTransaction = $transactionResult->transaction;
+ Braintree_TestHelper::settle($originalTransaction->id);
+
+ $firstRefund = Braintree_Transaction::refund(
+ $transactionResult->transaction->id,
+ $transactionResult->transaction->amount / 2
+ );
+ $this->assertTrue($firstRefund->success);
+ $firstRefundTransaction = $firstRefund->transaction;
+
+ $secondRefund = Braintree_Transaction::refund(
+ $transactionResult->transaction->id,
+ $transactionResult->transaction->amount / 2
+ );
+ $this->assertTrue($secondRefund->success);
+ $secondRefundTransaction = $secondRefund->transaction;
+
+
+ $updatedOriginalTransaction = Braintree_Transaction::find($originalTransaction->id);
+ $expectedRefundIds = array($secondRefundTransaction->id, $firstRefundTransaction->id);
+
+ $updatedRefundIds = $updatedOriginalTransaction->refundIds;
+
+ $this->assertTrue(in_array($expectedRefundIds[0],$updatedRefundIds));
+ $this->assertTrue(in_array($expectedRefundIds[1],$updatedRefundIds));
+ }
+
+ function testIncludeProcessorSettlementResponseForSettlementDeclinedTransaction()
+ {
+ $result = Braintree_Transaction::sale(array(
+ "paymentMethodNonce" => Braintree_Test_Nonces::$paypalFuturePayment,
+ "amount" => "100",
+ "options" => array(
+ "submitForSettlement" => true
+ )
+ ));
+
+ $this->assertTrue($result->success);
+
+ $transaction = $result->transaction;
+ Braintree_TestHelper::settlementDecline($transaction->id);
+
+ $inline_transaction = Braintree_Transaction::find($transaction->id);
+ $this->assertEquals($inline_transaction->status, Braintree_Transaction::SETTLEMENT_DECLINED);
+ $this->assertEquals($inline_transaction->processorSettlementResponseCode, "4001");
+ $this->assertEquals($inline_transaction->processorSettlementResponseText, "Settlement Declined");
+ }
+
+ function testIncludeProcessorSettlementResponseForSettlementPendingTransaction()
+ {
+ $result = Braintree_Transaction::sale(array(
+ "paymentMethodNonce" => Braintree_Test_Nonces::$paypalFuturePayment,
+ "amount" => "100",
+ "options" => array(
+ "submitForSettlement" => true
+ )
+ ));
+
+ $this->assertTrue($result->success);
+
+ $transaction = $result->transaction;
+ Braintree_TestHelper::settlementPending($transaction->id);
+
+ $inline_transaction = Braintree_Transaction::find($transaction->id);
+ $this->assertEquals($inline_transaction->status, Braintree_Transaction::SETTLEMENT_PENDING);
+ $this->assertEquals($inline_transaction->processorSettlementResponseCode, "4002");
+ $this->assertEquals($inline_transaction->processorSettlementResponseText, "Settlement Pending");
+ }
+
+ function testSale_withLodgingIndustryData()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'industry' => array(
+ 'industryType' => Braintree_Transaction::LODGING_INDUSTRY,
+ 'data' => array(
+ 'folioNumber' => 'aaa',
+ 'checkInDate' => '2014-07-07',
+ 'checkOutDate' => '2014-07-09',
+ 'roomRate' => '239.00'
+ )
+ )
+ ));
+ $this->assertTrue($result->success);
+ }
+
+ function testSale_withLodgingIndustryDataValidation()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'industry' => array(
+ 'industryType' => Braintree_Transaction::LODGING_INDUSTRY,
+ 'data' => array(
+ 'folioNumber' => 'aaa',
+ 'checkInDate' => '2014-07-07',
+ 'checkOutDate' => '2014-06-09',
+ 'roomRate' => '239.00'
+ )
+ )
+ ));
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+
+ $errors = $result->errors->forKey('transaction')->forKey('industry')->onAttribute('checkOutDate');
+ $this->assertEquals(Braintree_Error_Codes::INDUSTRY_DATA_LODGING_CHECK_OUT_DATE_MUST_FOLLOW_CHECK_IN_DATE, $errors[0]->code);
+ }
+
+ function testSale_withTravelCruiseIndustryData()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'industry' => array(
+ 'industryType' => Braintree_Transaction::TRAVEL_AND_CRUISE_INDUSTRY,
+ 'data' => array(
+ 'travelPackage' => 'flight',
+ 'departureDate' => '2014-07-07',
+ 'lodgingCheckInDate' => '2014-07-09',
+ 'lodgingCheckOutDate' => '2014-07-10',
+ 'lodgingName' => 'Disney',
+ )
+ )
+ ));
+ $this->assertTrue($result->success);
+ }
+
+ function testSale_withTravelCruiseIndustryDataValidation()
+ {
+ $result = Braintree_Transaction::sale(array(
+ 'amount' => '100.00',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ 'industry' => array(
+ 'industryType' => Braintree_Transaction::TRAVEL_AND_CRUISE_INDUSTRY,
+ 'data' => array(
+ 'travelPackage' => 'invalid',
+ 'departureDate' => '2014-07-07',
+ 'lodgingCheckInDate' => '2014-07-09',
+ 'lodgingCheckOutDate' => '2014-07-10',
+ 'lodgingName' => 'Disney',
+ )
+ )
+ ));
+ $this->assertFalse($result->success);
+ $transaction = $result->transaction;
+
+ $errors = $result->errors->forKey('transaction')->forKey('industry')->onAttribute('travelPackage');
+ $this->assertEquals(Braintree_Error_Codes::INDUSTRY_DATA_TRAVEL_CRUISE_TRAVEL_PACKAGE_IS_INVALID, $errors[0]->code);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransparentRedirectTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransparentRedirectTest.php
new file mode 100644
index 0000000..bcaca83
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/integration/TransparentRedirectTest.php
@@ -0,0 +1,348 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_TransparentRedirectTest extends PHPUnit_Framework_TestCase
+{
+ function testRedirectUrl()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $trData = Braintree_TransparentRedirect::createCustomerData(
+ array("redirectUrl" => "http://www.example.com?foo=bar")
+ );
+ $config = Braintree_Configuration::$global;
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ $config->baseUrl() . $config->merchantPath() . '/test/maintenance',
+ array(),
+ $trData
+ );
+ $this->setExpectedException('Braintree_Exception_DownForMaintenance');
+ Braintree_Customer::createFromTransparentRedirect($queryString);
+ }
+
+ function testParseAndValidateQueryString_throwsDownForMaintenanceErrorIfDownForMaintenance()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $trData = Braintree_TransparentRedirect::createCustomerData(
+ array("redirectUrl" => "http://www.example.com")
+ );
+ $config = Braintree_Configuration::$global;
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ $config->baseUrl() . $config->merchantPath() . '/test/maintenance',
+ array(),
+ $trData
+ );
+ $this->setExpectedException('Braintree_Exception_DownForMaintenance');
+ Braintree_Customer::createFromTransparentRedirect($queryString);
+ }
+
+ function testParseAndValidateQueryString_throwsAuthenticationErrorIfBadCredentials()
+ {
+ Braintree_TestHelper::suppressDeprecationWarnings();
+ $privateKey = Braintree_Configuration::privateKey();
+ Braintree_Configuration::privateKey('incorrect');
+ try {
+ $trData = Braintree_TransparentRedirect::createCustomerData(
+ array("redirectUrl" => "http://www.example.com")
+ );
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_Customer::createCustomerUrl(),
+ array(),
+ $trData
+ );
+ $this->setExpectedException('Braintree_Exception_Authentication');
+ Braintree_Customer::createFromTransparentRedirect($queryString);
+ } catch(Exception $e) {
+ }
+ $privateKey = Braintree_Configuration::privateKey($privateKey);
+ if (isset($e)) throw $e;
+ }
+
+ function testCreateTransactionFromTransparentRedirect()
+ {
+ $params = array(
+ 'transaction' => array(
+ 'customer' => array(
+ 'first_name' => 'First'
+ ),
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ )
+ )
+ );
+ $trParams = array(
+ 'transaction' => array(
+ 'type' => Braintree_Transaction::SALE,
+ 'amount' => '100.00'
+ )
+ );
+
+ $trData = Braintree_TransparentRedirect::transactionData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_TransparentRedirect::url(),
+ $params,
+ $trData
+ );
+
+ $result = Braintree_TransparentRedirect::confirm($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals(Braintree_Transaction::SALE, $result->transaction->type);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $result->transaction->status);
+ $creditCard = $result->transaction->creditCardDetails;
+ $this->assertEquals('510510', $creditCard->bin);
+ $this->assertEquals('5100', $creditCard->last4);
+ $this->assertEquals('US', $creditCard->customerLocation);
+ $this->assertEquals('MasterCard', $creditCard->cardType);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('510510******5100', $creditCard->maskedNumber);
+ $customer = $result->transaction->customerDetails;
+ $this->assertequals('First', $customer->firstName);
+ }
+
+ function testGatewayCreateTransactionFromTransparentRedirect()
+ {
+ $params = array(
+ 'transaction' => array(
+ 'customer' => array(
+ 'first_name' => 'First'
+ ),
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ )
+ )
+ );
+ $trParams = array(
+ 'transaction' => array(
+ 'type' => Braintree_Transaction::SALE,
+ 'amount' => '100.00'
+ )
+ );
+
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ $trData = $gateway->transparentRedirect()->transactionData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ $gateway->transparentRedirect()->url(),
+ $params,
+ $trData
+ );
+
+ $result = $gateway->transparentRedirect()->confirm($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('100.00', $result->transaction->amount);
+ $this->assertEquals(Braintree_Transaction::SALE, $result->transaction->type);
+ $this->assertEquals(Braintree_Transaction::AUTHORIZED, $result->transaction->status);
+ $creditCard = $result->transaction->creditCardDetails;
+ $this->assertEquals('US', $creditCard->customerLocation);
+ $this->assertEquals('05/2012', $creditCard->expirationDate);
+ $this->assertEquals('510510******5100', $creditCard->maskedNumber);
+ $customer = $result->transaction->customerDetails;
+ $this->assertequals('First', $customer->firstName);
+ }
+
+ function testCreateTransactionWithServiceFeesFromTransparentRedirect()
+ {
+ $params = array(
+ 'transaction' => array(
+ 'customer' => array(
+ 'first_name' => 'First'
+ ),
+ 'credit_card' => array(
+ 'number' => '5105105105105100',
+ 'expiration_date' => '05/12'
+ ),
+ 'service_fee_amount' => '1.00',
+ 'merchant_account_id' => Braintree_TestHelper::nonDefaultSubMerchantAccountId()
+ )
+ );
+ $trParams = array(
+ 'transaction' => array(
+ 'type' => Braintree_Transaction::SALE,
+ 'amount' => '100.00'
+ )
+ );
+
+ $trData = Braintree_TransparentRedirect::transactionData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_TransparentRedirect::url(),
+ $params,
+ $trData
+ );
+
+ $result = Braintree_TransparentRedirect::confirm($queryString);
+ $this->assertTrue($result->success);
+ $this->assertEquals('1.00', $result->transaction->serviceFeeAmount);
+ }
+
+ function testCreateCustomerFromTransparentRedirect()
+ {
+ $params = array(
+ 'customer' => array(
+ 'first_name' => 'Second'
+ )
+ );
+ $trParams = array(
+ 'customer' => array(
+ 'lastName' => 'Penultimate'
+ )
+ );
+
+ $trData = Braintree_TransparentRedirect::createCustomerData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_TransparentRedirect::url(),
+ $params,
+ $trData
+ );
+
+ $result = Braintree_TransparentRedirect::confirm($queryString);
+ $this->assertTrue($result->success);
+
+ $customer = $result->customer;
+ $this->assertequals('Second', $customer->firstName);
+ $this->assertequals('Penultimate', $customer->lastName);
+ }
+
+ function testUpdateCustomerFromTransparentRedirect()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jonez'
+ ))->customer;
+ $params = array(
+ 'customer' => array(
+ 'first_name' => 'Second'
+ )
+ );
+ $trParams = array(
+ 'customerId' => $customer->id,
+ 'customer' => array(
+ 'lastName' => 'Penultimate'
+ )
+ );
+
+ $trData = Braintree_TransparentRedirect::updateCustomerData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_TransparentRedirect::url(),
+ $params,
+ $trData
+ );
+
+ $result = Braintree_TransparentRedirect::confirm($queryString);
+ $this->assertTrue($result->success);
+
+ $customer = $result->customer;
+ $this->assertequals('Second', $customer->firstName);
+ $this->assertequals('Penultimate', $customer->lastName);
+ }
+
+ function testCreateCreditCardFromTransparentRedirect()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jonez'
+ ))->customer;
+
+ $params = array(
+ 'credit_card' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa
+ )
+ );
+ $trParams = array(
+ 'creditCard' => array(
+ 'customerId' => $customer->id,
+ 'expirationMonth' => '01',
+ 'expirationYear' => '10'
+ )
+ );
+
+ $trData = Braintree_TransparentRedirect::createCreditCardData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_TransparentRedirect::url(),
+ $params,
+ $trData
+ );
+
+ $result = Braintree_TransparentRedirect::confirm($queryString);
+ $this->assertTrue($result->success);
+
+ $creditCard = $result->creditCard;
+ $this->assertequals('401288', $creditCard->bin);
+ $this->assertequals('1881', $creditCard->last4);
+ $this->assertequals('01/2010', $creditCard->expirationDate);
+ }
+
+ function testUpdateCreditCardFromTransparentRedirect()
+ {
+ $customer = Braintree_Customer::create(array(
+ 'firstName' => 'Mike',
+ 'lastName' => 'Jonez'
+ ))->customer;
+ $creditCard = Braintree_CreditCard::create(array(
+ 'customerId' => $customer->id,
+ 'number' => Braintree_Test_CreditCardNumbers::$masterCard,
+ 'expirationMonth' => '10',
+ 'expirationYear' => '10'
+ ))->creditCard;
+
+ $params = array(
+ 'credit_card' => array(
+ 'number' => Braintree_Test_CreditCardNumbers::$visa
+ )
+ );
+ $trParams = array(
+ 'paymentMethodToken' => $creditCard->token,
+ 'creditCard' => array(
+ 'expirationMonth' => '11',
+ 'expirationYear' => '11'
+ )
+ );
+
+ $trData = Braintree_TransparentRedirect::updateCreditCardData(
+ array_merge($trParams, array("redirectUrl" => "http://www.example.com"))
+ );
+
+ $queryString = Braintree_TestHelper::submitTrRequest(
+ Braintree_TransparentRedirect::url(),
+ $params,
+ $trData
+ );
+
+ Braintree_TransparentRedirect::confirm($queryString);
+
+ $creditCard = Braintree_CreditCard::find($creditCard->token);
+ $this->assertequals('401288', $creditCard->bin);
+ $this->assertequals('1881', $creditCard->last4);
+ $this->assertequals('11/2011', $creditCard->expirationDate);
+ }
+
+ function testUrl()
+ {
+ $url = Braintree_TransparentRedirect::url();
+ $developmentPort = getenv("GATEWAY_PORT") ? getenv("GATEWAY_PORT") : 3000;
+ $this->assertEquals("http://localhost:" . $developmentPort . "/merchants/integration_merchant_id/transparent_redirect_requests", $url);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/AddOnTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/AddOnTest.php
new file mode 100644
index 0000000..f0f4adc
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/AddOnTest.php
@@ -0,0 +1,29 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_AddOnTest extends PHPUnit_Framework_TestCase
+{
+ public function testFactory()
+ {
+ $addOn = \Braintree_AddOn::factory(array());
+
+ $this->assertInstanceOf('Braintree_AddOn', $addOn);
+ }
+
+ function testToString()
+ {
+ $addOnParams = array (
+ "amount" => "100.00",
+ "description" => "some description",
+ "id" => "1",
+ "kind" => "add_on",
+ "name" => "php_add_on",
+ "neverExpires" => "false",
+ "numberOfBillingCycles" => "1"
+ );
+
+ $addOn = \Braintree_AddOn::factory($addOnParams);
+
+ $this->assertEquals("Braintree_AddOn[amount=100.00, description=some description, id=1, kind=add_on, name=php_add_on, neverExpires=false, numberOfBillingCycles=1]", (string) $addOn);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/AddressTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/AddressTest.php
new file mode 100644
index 0000000..13d6499
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/AddressTest.php
@@ -0,0 +1,74 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_AddressTest extends PHPUnit_Framework_TestCase
+{
+ function testGet_givesErrorIfInvalidProperty()
+ {
+ $this->setExpectedException('PHPUnit_Framework_Error', 'Undefined property on Braintree_Address: foo');
+ $a = Braintree_Address::factory(array());
+ $a->foo;
+ }
+
+ function testIsEqual()
+ {
+ $first = Braintree_Address::factory(
+ array('customerId' => 'c1', 'id' => 'a1')
+ );
+ $second = Braintree_Address::factory(
+ array('customerId' => 'c1', 'id' => 'a1')
+ );
+
+ $this->assertTrue($first->isEqual($second));
+ $this->assertTrue($second->isEqual($first));
+
+ }
+ function testIsNotEqual() {
+ $first = Braintree_Address::factory(
+ array('customerId' => 'c1', 'id' => 'a1')
+ );
+ $second = Braintree_Address::factory(
+ array('customerId' => 'c1', 'id' => 'not a1')
+ );
+
+ $this->assertFalse($first->isEqual($second));
+ $this->assertFalse($second->isEqual($first));
+ }
+
+ function testCustomerIdNotEqual()
+ {
+ $first = Braintree_Address::factory(
+ array('customerId' => 'c1', 'id' => 'a1')
+ );
+ $second = Braintree_Address::factory(
+ array('customerId' => 'not c1', 'id' => 'a1')
+ );
+
+ $this->assertFalse($first->isEqual($second));
+ $this->assertFalse($second->isEqual($first));
+ }
+
+ function testFindErrorsOnBlankCustomerId()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Address::find('', '123');
+ }
+
+ function testFindErrorsOnBlankAddressId()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Address::find('123', '');
+ }
+
+ function testFindErrorsOnWhitespaceOnlyId()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Address::find('123', ' ');
+ }
+
+ function testFindErrorsOnWhitespaceOnlyCustomerId()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Address::find(' ', '123');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/BraintreeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/BraintreeTest.php
new file mode 100644
index 0000000..983cb50
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/BraintreeTest.php
@@ -0,0 +1,20 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_BraintreeTest extends PHPUnit_Framework_TestCase
+{
+ function testIsset()
+ {
+ $t = Braintree_Transaction::factory(array(
+ 'creditCard' => array('expirationMonth' => '05', 'expirationYear' => '2010', 'bin' => '510510', 'last4' => '5100'),
+ 'customer' => array(),
+ 'billing' => array(),
+ 'descriptor' => array(),
+ 'shipping' => array(),
+ 'subscription' => array('billingPeriodStartDate' => '1983-07-12'),
+ 'statusHistory' => array()
+ ));
+ $this->assertTrue(isset($t->creditCard));
+ $this->assertFalse(empty($t->creditCard));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/ClientApi/ClientTokenTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/ClientApi/ClientTokenTest.php
new file mode 100644
index 0000000..ccc4a8d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/ClientApi/ClientTokenTest.php
@@ -0,0 +1,17 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../../TestHelper.php';
+
+class ClientTokenTest extends PHPUnit_Framework_TestCase
+{
+ function testErrorsWhenCreditCardOptionsGivenWithoutCustomerId()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'invalid keys: options[makeDefault]');
+ Braintree_ClientToken::generate(array("options" => array("makeDefault" => true)));
+ }
+
+ function testErrorsWhenInvalidArgumentIsSupplied()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'invalid keys: customrId');
+ Braintree_ClientToken::generate(array("customrId" => "1234"));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/ConfigurationTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/ConfigurationTest.php
new file mode 100644
index 0000000..ab4e6af
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/ConfigurationTest.php
@@ -0,0 +1,392 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_ConfigurationTest extends PHPUnit_Framework_TestCase
+{
+ function setup()
+ {
+ Braintree_Configuration::reset();
+ $this->config = new Braintree_Configuration();
+ }
+
+ function teardown()
+ {
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+ }
+
+ function testAssertGlobalHasAccessTokenOrKeys()
+ {
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+
+ try {
+ Braintree_Configuration::assertGlobalHasAccessTokenOrKeys();
+ } catch (Exception $notExpected) {
+ $this->fail();
+ }
+
+ $this->assertTrue(TRUE);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::publicKey needs to be set.
+ */
+ function testAssertGlobalHasAccessTokenOrKeysWithoutPublicKey()
+ {
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('');
+ Braintree_Configuration::privateKey('integration_private_key');
+
+ Braintree_Configuration::assertGlobalHasAccessTokenOrKeys();
+ }
+
+ function testConstructWithArrayOfCredentials()
+ {
+ $config = new Braintree_Configuration(array(
+ 'environment' => 'sandbox',
+ 'merchantId' => 'sandbox_merchant_id',
+ 'publicKey' => 'sandbox_public_key',
+ 'privateKey' => 'sandbox_private_key'
+ ));
+
+ $this->assertEquals('sandbox', $config->getEnvironment());
+ $this->assertEquals('sandbox_merchant_id', $config->getMerchantId());
+ }
+
+ function testSetValidEnvironment()
+ {
+ Braintree_Configuration::environment('sandbox');
+ $this->assertEquals('sandbox', Braintree_Configuration::environment());
+ Braintree_Configuration::reset();
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage "invalid" is not a valid environment.
+ */
+ function testSetInvalidEnvironment()
+ {
+ Braintree_Configuration::environment('invalid');
+ Braintree_Configuration::reset();
+ }
+
+ function testMerchantPath()
+ {
+ $this->config->setMerchantId('abc123');
+ $mp = $this->config->merchantPath();
+ $this->assertEquals('/merchants/abc123', $mp);
+ }
+
+ function testCaFile()
+ {
+ $this->config->setEnvironment('development');
+ $this->setExpectedException('Braintree_Exception_SSLCaFileNotFound');
+ $this->config->caFile('/does/not/exist/');
+ }
+
+ function testSSLOn()
+ {
+ $this->config->setEnvironment('development');
+ $on = $this->config->sslOn();
+ $this->assertFalse($on);
+
+ $this->config->setEnvironment('sandbox');
+ $on = $this->config->sslOn();
+ $this->assertTrue($on);
+
+ $this->config->setEnvironment('production');
+ $on = $this->config->sslOn();
+ $this->assertTrue($on);
+ }
+
+ function testPortNumber()
+ {
+ $this->config->setEnvironment('development');
+ $pn = $this->config->portNumber();
+ $this->assertEquals(getenv("GATEWAY_PORT") ? getenv("GATEWAY_PORT") : 3000, $pn);
+
+ $this->config->setEnvironment('sandbox');
+ $pn = $this->config->portNumber();
+ $this->assertEquals(443, $pn);
+
+ $this->config->setEnvironment('production');
+ $pn = $this->config->portNumber();
+ $this->assertEquals(443, $pn);
+ }
+
+
+ function testProtocol()
+ {
+ $this->config->setEnvironment('development');
+ $p = $this->config->protocol();
+ $this->assertEquals('http', $p);
+
+ $this->config->setEnvironment('sandbox');
+ $p = $this->config->protocol();
+ $this->assertEquals('https', $p);
+
+ $this->config->setEnvironment('production');
+ $p = $this->config->protocol();
+ $this->assertEquals('https', $p);
+ }
+
+ function testServerName()
+ {
+ $this->config->setEnvironment('development');
+ $sn = $this->config->serverName();
+ $this->assertEquals('localhost', $sn);
+
+ $this->config->setEnvironment('sandbox');
+ $sn = $this->config->serverName();
+ $this->assertEquals('api.sandbox.braintreegateway.com', $sn);
+
+ $this->config->setEnvironment('production');
+ $sn = $this->config->serverName();
+ $this->assertEquals('api.braintreegateway.com', $sn);
+ }
+
+ function testAuthUrl()
+ {
+ $this->config->setEnvironment('development');
+ $authUrl = $this->config->authUrl();
+ $this->assertEquals('http://auth.venmo.dev:9292', $authUrl);
+
+ $this->config->setEnvironment('qa');
+ $authUrl = $this->config->authUrl();
+ $this->assertEquals('https://auth.qa.venmo.com', $authUrl);
+
+ $this->config->setEnvironment('sandbox');
+ $authUrl = $this->config->authUrl();
+ $this->assertEquals('https://auth.sandbox.venmo.com', $authUrl);
+
+ $this->config->setEnvironment('production');
+ $authUrl = $this->config->authUrl();
+ $this->assertEquals('https://auth.venmo.com', $authUrl);
+ }
+
+ function testBaseUrl()
+ {
+ $this->config->setEnvironment('development');
+ $bu = $this->config->baseUrl();
+ $this->assertEquals('http://localhost:' . $this->config->portNumber(), $bu);
+
+ $fakeConfig = $this->getMockBuilder('Braintree_Configuration')->setMethods(array('portNumber'))->getMock();
+ $fakeConfig->expects($this->once())->method('portNumber')->will($this->returnValue(80));
+ $fakeConfig->setEnvironment('development');
+ $bu = $fakeConfig->baseUrl();
+ $this->assertEquals('http://localhost', $bu);
+
+ $this->config->setEnvironment('qa');
+ $bu = $this->config->baseUrl();
+ $this->assertEquals('https://gateway.qa.braintreepayments.com', $bu);
+
+ $this->config->setEnvironment('sandbox');
+ $bu = $this->config->baseUrl();
+ $this->assertEquals('https://api.sandbox.braintreegateway.com', $bu);
+
+ $this->config->setEnvironment('production');
+ $bu = $this->config->baseUrl();
+ $this->assertEquals('https://api.braintreegateway.com', $bu);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::environment needs to be set.
+ */
+ function testValidateEmptyEnvironment()
+ {
+ //Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+
+ Braintree_Configuration::$global->assertHasAccessTokenOrKeys();
+ }
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree_Gateway).
+ */
+ function testMerchantId()
+ {
+ Braintree_Configuration::environment('development');
+ //Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+
+ Braintree_Configuration::$global->assertHasAccessTokenOrKeys();
+ }
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::publicKey needs to be set.
+ */
+ function testPublicKey()
+ {
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ //Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+
+ Braintree_Configuration::$global->assertHasAccessTokenOrKeys();
+ }
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::privateKey needs to be set.
+ */
+ function testPrivateKey()
+ {
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ //Braintree_Configuration::privateKey('integration_private_key');
+
+ Braintree_Configuration::$global->assertHasAccessTokenOrKeys();
+ }
+
+ function testValidWithOAuthClientCredentials()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+
+ $config->assertHasClientCredentials();
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage clientSecret needs to be passed to Braintree_Gateway.
+ */
+ function testInvalidWithOAuthClientCredentials()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$development$integration_client_id'
+ ));
+
+ $config->assertHasClientCredentials();
+ }
+
+ function testDetectEnvironmentFromClientId()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+
+ $this->assertEquals('development', $config->getEnvironment());
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Mismatched credential environments: clientId environment is sandbox and clientSecret environment is development
+ */
+ function testDetectEnvironmentFromClientIdFail()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$sandbox$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Value passed for clientId is not a clientId
+ */
+ function testClientIdTypeFail()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_secret$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ }
+
+ function testValidWithAccessToken()
+ {
+ $config = new Braintree_Configuration(array(
+ 'accessToken' => 'access_token$development$integration_merchant_id$integration_access_token',
+ ));
+
+ $config->assertHasAccessTokenOrKeys();
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Value passed for accessToken is not an accessToken
+ */
+ function testInvalidAccessTokenType()
+ {
+ $config = new Braintree_Configuration(array(
+ 'accessToken' => 'client_id$development$integration_merchant_id$integration_access_token',
+ ));
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Incorrect accessToken syntax. Expected: type$environment$merchant_id$token
+ */
+ function testInvalidAccessTokenSyntax()
+ {
+ $config = new Braintree_Configuration(array(
+ 'accessToken' => 'client_id$development$integration_client_id',
+ ));
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage "invalid" is not a valid environment.
+ */
+ function testInvalidAccessTokenEnvironment()
+ {
+ $config = new Braintree_Configuration(array(
+ 'accessToken' => 'access_token$invalid$integration_merchant_id$integration_access_token',
+ ));
+ }
+
+
+ function testValidWithOAuthClientCredentialsAndAccessToken()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ 'accessToken' => 'access_token$development$integration_merchant_id$integration_access_token',
+ ));
+
+ $config->assertHasClientCredentials();
+ $config->assertHasAccessTokenOrKeys();
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Mismatched credential environments: clientId environment is development and accessToken environment is sandbox
+ */
+ function testInvalidEnvironmentWithOAuthClientCredentialsAndAccessToken()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ 'accessToken' => 'access_token$sandbox$integration_merchant_id$integration_access_token',
+ ));
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Cannot mix OAuth credentials (clientId, clientSecret, accessToken) with key credentials (publicKey, privateKey, environment, merchantId).
+ */
+ function testCannotMixKeysWithOAuthCredentials()
+ {
+ $config = new Braintree_Configuration(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret',
+ 'environment' => 'development',
+ 'merchantId' => 'integration_merchant_id',
+ 'publicKey' => 'integration_public_key',
+ 'privateKey' => 'integration_private_key'
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/CreditCardTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/CreditCardTest.php
new file mode 100644
index 0000000..230f0bc
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/CreditCardTest.php
@@ -0,0 +1,135 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_CreditCardTest extends PHPUnit_Framework_TestCase
+{
+ function testGet_givesErrorIfInvalidProperty()
+ {
+ $this->setExpectedException('PHPUnit_Framework_Error', 'Undefined property on Braintree_CreditCard: foo');
+ $cc = Braintree_CreditCard::factory(array());
+ $cc->foo;
+ }
+
+ function testCreate_throwsIfInvalidKey()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'invalid keys: invalidKey');
+ Braintree_CreditCard::create(array('invalidKey' => 'foo'));
+ }
+
+ function testIsDefault()
+ {
+ $creditCard = Braintree_CreditCard::factory(array('default' => true));
+ $this->assertTrue($creditCard->isDefault());
+
+ $creditCard = Braintree_CreditCard::factory(array('default' => false));
+ $this->assertFalse($creditCard->isDefault());
+ }
+
+ function testMaskedNumber()
+ {
+ $creditCard = Braintree_CreditCard::factory(array('bin' => '123456', 'last4' => '7890'));
+ $this->assertEquals('123456******7890', $creditCard->maskedNumber);
+ }
+
+ function testCreateSignature()
+ {
+ $expected = array(
+ 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId',
+ 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode',
+ 'deviceData', 'fraudMerchantId', 'paymentMethodNonce',
+ array('options' => array('makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession', 'failOnDuplicatePaymentMethod')),
+ array(
+ 'billingAddress' => array(
+ 'firstName',
+ 'lastName',
+ 'company',
+ 'countryCodeAlpha2',
+ 'countryCodeAlpha3',
+ 'countryCodeNumeric',
+ 'countryName',
+ 'extendedAddress',
+ 'locality',
+ 'region',
+ 'postalCode',
+ 'streetAddress'
+ ),
+ ),
+ 'customerId'
+ );
+ $this->assertEquals($expected, Braintree_CreditCardGateway::createSignature());
+ }
+
+ function testUpdateSignature()
+ {
+ $expected = array(
+ 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId',
+ 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode',
+ 'deviceData', 'fraudMerchantId', 'paymentMethodNonce',
+ array('options' => array('makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession')),
+ array(
+ 'billingAddress' => array(
+ 'firstName',
+ 'lastName',
+ 'company',
+ 'countryCodeAlpha2',
+ 'countryCodeAlpha3',
+ 'countryCodeNumeric',
+ 'countryName',
+ 'extendedAddress',
+ 'locality',
+ 'region',
+ 'postalCode',
+ 'streetAddress',
+ array(
+ 'options' => array(
+ 'updateExisting'
+ )
+ )
+ ),
+ ),
+ );
+ $this->assertEquals($expected, Braintree_CreditCardGateway::updateSignature());
+ }
+
+ function testErrorsOnFindWithBlankArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_CreditCard::find('');
+ }
+
+ function testErrorsOnFindWithWhitespaceArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_CreditCard::find(' ');
+ }
+
+ function testErrorsOnFindWithWhitespaceCharacterArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_CreditCard::find('\t');
+ }
+
+ function testVerificationIsLatestVerification()
+ {
+ $creditCard = Braintree_CreditCard::factory(
+ array(
+ 'verifications' => array(
+ array(
+ 'id' => '123',
+ 'createdAt' => DateTime::createFromFormat('Ymd', '20121212')
+ ),
+ array(
+ 'id' => '932',
+ 'createdAt' => DateTime::createFromFormat('Ymd', '20121215')
+ ),
+ array(
+ 'id' => '456',
+ 'createdAt' => DateTime::createFromFormat('Ymd', '20121213')
+ )
+ )
+ )
+ );
+
+ $this->assertEquals('932', $creditCard->verification->id);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/CustomerTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/CustomerTest.php
new file mode 100644
index 0000000..5120799
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/CustomerTest.php
@@ -0,0 +1,54 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_CustomerTest extends PHPUnit_Framework_TestCase
+{
+ function testGet_givesErrorIfInvalidProperty()
+ {
+ $this->setExpectedException('PHPUnit_Framework_Error', 'Undefined property on Braintree_Customer: foo');
+ $c = Braintree_Customer::factory(array());
+ $c->foo;
+ }
+
+ function testUpdateSignature_doesNotAlterOptionsInCreditCardUpdateSignature()
+ {
+ Braintree_CustomerGateway::updateSignature();
+ foreach(Braintree_CreditCardGateway::updateSignature() AS $key => $value) {
+ if(is_array($value) and array_key_exists('options', $value)) {
+ $this->assertEquals(array(
+ 'makeDefault',
+ 'verificationMerchantAccountId',
+ 'verifyCard',
+ 'verificationAmount',
+ 'venmoSdkSession'
+ ), $value['options']);
+ }
+ }
+ }
+
+ function testCreateSignature_doesNotIncludeCustomerIdOnCreditCard()
+ {
+ $signature = Braintree_CustomerGateway::createSignature();
+ $creditCardSignatures = array_filter($signature, 'Braintree_CustomerTest::findCreditCardArray');
+ $creditCardSignature = array_shift($creditCardSignatures)['creditCard'];
+
+ $this->assertNotContains('customerId', $creditCardSignature);
+ }
+
+ function findCreditCardArray($el)
+ {
+ return is_array($el) && array_key_exists('creditCard', $el);
+ }
+
+ function testFindErrorsOnBlankId()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Customer::find('');
+ }
+
+ function testFindErrorsOnWhitespaceId()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Customer::find('\t');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/DigestTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DigestTest.php
new file mode 100644
index 0000000..81d71fb
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DigestTest.php
@@ -0,0 +1,93 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_DigestTest extends PHPUnit_Framework_TestCase
+{
+
+ function testSecureCompareReturnsTrueForMatches()
+ {
+ $this->assertTrue(Braintree_Digest::secureCompare("a_string", "a_string"));
+ }
+
+ function testSecureCompareReturnsFalseForDifferentLengths()
+ {
+ $this->assertFalse(Braintree_Digest::secureCompare("a_string", "a_string_that_is_longer"));
+ }
+
+ function testSecureCompareReturnsFalseForNonmatchingSameLengthStrings()
+ {
+ $this->assertFalse(Braintree_Digest::secureCompare("a_string", "a_strong"));
+ }
+
+ function testHexDigestSha1()
+ {
+ $key = str_repeat(chr(0xaa),80);
+ $message = 'Test Using Larger Than Block-Size Key - Hash Key First';
+ $d = Braintree_Digest::hexDigestSha1($key, $message);
+
+ $this->assertEquals('aa4ae5e15272d00e95705637ce8a3b55ed402112', $d);
+ }
+
+ function testHexDigestSha1_again()
+ {
+ $key = str_repeat(chr(0xaa),80);
+ $message = 'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data';
+ $d = Braintree_Digest::hexDigestSha1($key, $message);
+
+ $this->assertEquals('e8e99d0f45237d786d6bbaa7965c7808bbff1a91', $d);
+ }
+
+ function testHexDigestSha256()
+ {
+ $key = str_repeat(chr(0xaa),80);
+ $message = 'Test Using Larger Than Block-Size Key - Hash Key First';
+ $d = Braintree_Digest::hexDigestSha256($key, $message);
+
+ $this->assertEquals('6953025ed96f0c09f80a96f78e6538dbe2e7b820e3dd970e7ddd39091b32352f', $d);
+ }
+
+ function testHexDigestSha256_again()
+ {
+ $key = str_repeat(chr(0xaa),80);
+ $message = 'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data';
+ $d = Braintree_Digest::hexDigestSha256($key, $message);
+
+ $this->assertEquals('6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6', $d);
+ }
+
+ function testBuiltInHmacSha1()
+ {
+ Braintree_Configuration::privateKey(str_repeat(chr(0xaa),80));
+ $message = 'Test Using Larger Than Block-Size Key - Hash Key First';
+ $d = Braintree_Digest::_builtInHmacSha1($message, Braintree_Configuration::privateKey());
+
+ $this->assertEquals('aa4ae5e15272d00e95705637ce8a3b55ed402112', $d);
+ }
+
+ function testBuiltInHmacSha1_again()
+ {
+ Braintree_Configuration::privateKey(str_repeat(chr(0xaa),80));
+ $message = 'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data';
+ $d = Braintree_Digest::_builtInHmacSha1($message, Braintree_Configuration::privateKey());
+
+ $this->assertEquals('e8e99d0f45237d786d6bbaa7965c7808bbff1a91', $d);
+ }
+
+ function testHmacSha1()
+ {
+ Braintree_Configuration::privateKey(str_repeat(chr(0xaa),80));
+ $message = 'Test Using Larger Than Block-Size Key - Hash Key First';
+ $d = Braintree_Digest::_hmacSha1($message, Braintree_Configuration::privateKey());
+
+ $this->assertEquals('aa4ae5e15272d00e95705637ce8a3b55ed402112', $d);
+ }
+
+ function testHmacSha1_again()
+ {
+ Braintree_Configuration::privateKey(str_repeat(chr(0xaa),80));
+ $message = 'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data';
+ $d = Braintree_Digest::_hmacSha1($message, Braintree_Configuration::privateKey());
+
+ $this->assertEquals('e8e99d0f45237d786d6bbaa7965c7808bbff1a91', $d);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementDetailsTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementDetailsTest.php
new file mode 100644
index 0000000..949b858
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementDetailsTest.php
@@ -0,0 +1,23 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_DisbursementDetailsTest extends PHPUnit_Framework_TestCase
+{
+ function testIsValidReturnsTrue()
+ {
+ $details = new Braintree_DisbursementDetails(array(
+ "disbursementDate" => new DateTime("2013-04-10")
+ ));
+
+ $this->assertTrue($details->isValid());
+ }
+
+ function testIsValidReturnsFalse()
+ {
+ $details = new Braintree_DisbursementDetails(array(
+ "disbursementDate" => null
+ ));
+
+ $this->assertFalse($details->isValid());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementTest.php
new file mode 100644
index 0000000..83a47a5
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DisbursementTest.php
@@ -0,0 +1,29 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_DisbursementTest extends PHPUnit_Framework_TestCase
+{
+ function testToString()
+ {
+ $disbursement = Braintree_Disbursement::factory(array(
+ "id" => "123456",
+ "merchantAccount" => array(
+ "id" => "sandbox_sub_merchant_account",
+ "masterMerchantAccount" => array(
+ "id" => "sandbox_master_merchant_account",
+ "status" => "active"
+ ),
+ "status" => "active"
+ ),
+ "transactionIds" => array("sub_merchant_transaction"),
+ "exceptionMessage" => "invalid_account_number",
+ "amount" => "100.00",
+ "disbursementDate" => new DateTime("2013-04-10"),
+ "followUpAction" => "update",
+ "retry" => false,
+ "success" => false
+ ));
+
+ $this->assertEquals((string) $disbursement, 'Braintree_Disbursement[id=123456, merchantAccountDetails=id=sandbox_sub_merchant_account, masterMerchantAccount=id=sandbox_master_merchant_account, status=active, status=active, exceptionMessage=invalid_account_number, amount=100.00, disbursementDate=Wednesday, 10-Apr-13 00:00:00 UTC, followUpAction=update, retry=, success=, transactionIds=0=sub_merchant_transaction]');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/DiscountTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DiscountTest.php
new file mode 100644
index 0000000..433c887
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/DiscountTest.php
@@ -0,0 +1,29 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_DiscountTest extends PHPUnit_Framework_TestCase
+{
+ public function testFactory()
+ {
+ $discount = \Braintree_Discount::factory(array());
+
+ $this->assertInstanceOf('Braintree_Discount', $discount);
+ }
+
+ function testToString()
+ {
+ $discountParams = array (
+ "amount" => "100.00",
+ "description" => "some description",
+ "id" => "1",
+ "kind" => "discount",
+ "name" => "php_discount",
+ "neverExpires" => "false",
+ "numberOfBillingCycles" => "1"
+ );
+
+ $discount = \Braintree_Discount::factory($discountParams);
+
+ $this->assertEquals("Braintree_Discount[amount=100.00, description=some description, id=1, kind=discount, name=php_discount, neverExpires=false, numberOfBillingCycles=1]", (string) $discount);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/GatewayTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/GatewayTest.php
new file mode 100644
index 0000000..0e3acaf
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/GatewayTest.php
@@ -0,0 +1,46 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_GatewayTest extends PHPUnit_Framework_TestCase
+{
+ function setup()
+ {
+ Braintree_Configuration::reset();
+ }
+
+ function teardown()
+ {
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree_Gateway).
+ */
+ function testConfigGetsAssertedValid()
+ {
+ Braintree_Configuration::environment('development');
+ //Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('integration_public_key');
+ Braintree_Configuration::privateKey('integration_private_key');
+
+ $gateway = new Braintree_Gateway(Braintree_Configuration::$global);
+ $gateway->addOn();
+ }
+
+ function testConstructWithArrayOfCredentials()
+ {
+ $gateway = new Braintree_Gateway(array(
+ 'environment' => 'sandbox',
+ 'merchantId' => 'sandbox_merchant_id',
+ 'publicKey' => 'sandbox_public_key',
+ 'privateKey' => 'sandbox_private_key'
+ ));
+
+ $this->assertEquals('sandbox', $gateway->config->getEnvironment());
+ $this->assertEquals('sandbox_merchant_id', $gateway->config->getMerchantId());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/InstanceTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/InstanceTest.php
new file mode 100644
index 0000000..f6652e9
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/InstanceTest.php
@@ -0,0 +1,32 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_InstanceTest extends PHPUnit_Framework_TestCase
+{
+ function test__isset()
+ {
+ $transaction = Braintree_Transaction::factory(array(
+ 'creditCard' => array(
+ 'expirationMonth' => '05',
+ 'expirationYear' => '2010',
+ 'bin' => '510510',
+ 'last4' => '5100',
+ 'cardType' => 'MasterCard'
+ ),
+ ));
+ $this->assertEquals('MasterCard', $transaction->creditCardDetails->cardType);
+ $this->assertFalse(empty($transaction->creditCardDetails->cardType));
+ $this->assertTrue(isset($transaction->creditCardDetails->cardType));
+
+ $transaction = Braintree_Transaction::factory(array(
+ 'creditCard' => array(
+ 'expirationMonth' => '05',
+ 'expirationYear' => '2010',
+ 'bin' => '510510',
+ 'last4' => '5100'
+ ),
+ ));
+ $this->assertTrue(empty($transaction->creditCardDetails->cardType));
+ $this->assertFalse(isset($transaction->creditCardDetails->cardType));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/MerchantAccountTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/MerchantAccountTest.php
new file mode 100644
index 0000000..67ec05c
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/MerchantAccountTest.php
@@ -0,0 +1,63 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_MerchantAccountTest extends PHPUnit_Framework_TestCase
+{
+ function testCreateMerchantAccountWithAllParams()
+ {
+ $params = array(
+ "id" => "sub_merchant_account",
+ "status" => "active",
+ "masterMerchantAccount" => array(
+ "id" => "master_merchant_account",
+ "status" => "active"
+ ),
+ "individual" => array(
+ "firstName" => "John",
+ "lastName" => "Doe",
+ "email" => "john.doe@example.com",
+ "dateOfBirth" => "1970-01-01",
+ "phone" => "3125551234",
+ "ssnLast4" => "6789",
+ "address" => array(
+ "streetAddress" => "123 Fake St",
+ "locality" => "Chicago",
+ "region" => "IL",
+ "postalCode" => "60622",
+ )
+ ),
+ "business" => array(
+ "dbaName" => "James's Bloggs",
+ "taxId" => "123456789",
+ ),
+ "funding" => array(
+ "accountNumberLast4" => "8798",
+ "routingNumber" => "071000013",
+ "descriptor" => "Joes Bloggs MI",
+ )
+ );
+ $merchantAccount = Braintree_MerchantAccount::factory($params);
+
+
+ $this->assertEquals($merchantAccount->status, "active");
+ $this->assertEquals($merchantAccount->id, "sub_merchant_account");
+ $this->assertEquals($merchantAccount->masterMerchantAccount->id, "master_merchant_account");
+ $this->assertEquals($merchantAccount->masterMerchantAccount->status, "active");
+ $this->assertEquals($merchantAccount->individualDetails->firstName, "John");
+ $this->assertEquals($merchantAccount->individualDetails->lastName, "Doe");
+ $this->assertEquals($merchantAccount->individualDetails->email, "john.doe@example.com");
+ $this->assertEquals($merchantAccount->individualDetails->dateOfBirth, "1970-01-01");
+ $this->assertEquals($merchantAccount->individualDetails->phone, "3125551234");
+ $this->assertEquals($merchantAccount->individualDetails->ssnLast4, "6789");
+ $this->assertEquals($merchantAccount->individualDetails->addressDetails->streetAddress, "123 Fake St");
+ $this->assertEquals($merchantAccount->individualDetails->addressDetails->locality, "Chicago");
+ $this->assertEquals($merchantAccount->individualDetails->addressDetails->region, "IL");
+ $this->assertEquals($merchantAccount->individualDetails->addressDetails->postalCode, "60622");
+ $this->assertEquals($merchantAccount->businessDetails->dbaName, "James's Bloggs");
+ $this->assertEquals($merchantAccount->businessDetails->taxId, "123456789");
+ $this->assertEquals($merchantAccount->fundingDetails->accountNumberLast4, "8798");
+ $this->assertEquals($merchantAccount->fundingDetails->routingNumber, "071000013");
+ $this->assertEquals($merchantAccount->fundingDetails->descriptor, "Joes Bloggs MI");
+ }
+}
+?>
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueNodeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueNodeTest.php
new file mode 100644
index 0000000..40726b8
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueNodeTest.php
@@ -0,0 +1,19 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_MultipleValueNodeTest extends PHPUnit_Framework_TestCase
+{
+ function testIs()
+ {
+ $node = new Braintree_MultipleValueNode('field');
+ $node->is('value');
+ $this->assertEquals(array('value'), $node->toParam());
+ }
+
+ function testIn()
+ {
+ $node = new Braintree_MultipleValueNode('field');
+ $node->in(array('firstValue', 'secondValue'));
+ $this->assertEquals(array('firstValue', 'secondValue'), $node->toParam());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueOrTextNodeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueOrTextNodeTest.php
new file mode 100644
index 0000000..39f1a92
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/MultipleValueOrTextNodeTest.php
@@ -0,0 +1,47 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_MultipleValueOrTextNodeTest extends PHPUnit_Framework_TestCase
+{
+ function testIn()
+ {
+ $node = new Braintree_MultipleValueOrTextNode('field');
+ $node->in(array('firstValue', 'secondValue'));
+ $this->assertEquals(array('firstValue', 'secondValue'), $node->toParam());
+ }
+
+ function testIs()
+ {
+ $node = new Braintree_MultipleValueOrTextNode('field');
+ $node->is('value');
+ $this->assertEquals(array('is' => 'value'), $node->toParam());
+ }
+
+ function testIsNot()
+ {
+ $node = new Braintree_MultipleValueOrTextNode('field');
+ $node->isNot('value');
+ $this->assertEquals(array('is_not' => 'value'), $node->toParam());
+ }
+
+ function testStartsWith()
+ {
+ $node = new Braintree_MultipleValueOrTextNode('field');
+ $node->startsWith('beginning');
+ $this->assertEquals(array('starts_with' => 'beginning'), $node->toParam());
+ }
+
+ function testEndsWith()
+ {
+ $node = new Braintree_MultipleValueOrTextNode('field');
+ $node->endsWith('end');
+ $this->assertEquals(array('ends_with' => 'end'), $node->toParam());
+ }
+
+ function testContains()
+ {
+ $node = new Braintree_MultipleValueOrTextNode('field');
+ $node->contains('middle');
+ $this->assertEquals(array('contains' => 'middle'), $node->toParam());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/OAuthTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/OAuthTest.php
new file mode 100644
index 0000000..095f8ae
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/OAuthTest.php
@@ -0,0 +1,66 @@
+<?php
+require_once __DIR__ . '/../TestHelper.php';
+
+class Braintree_OAuthTest extends PHPUnit_Framework_TestCase
+{
+ protected $gateway;
+
+ public function setUp()
+ {
+ $this->gateway = new Braintree_Gateway(array(
+ 'clientId' => 'client_id$development$integration_client_id',
+ 'clientSecret' => 'client_secret$development$integration_client_secret'
+ ));
+ }
+
+ public function testMapInvalidGrantCodeToOldError()
+ {
+ $result = $this->_buildResult(array(
+ 'code' => '93801',
+ 'message' => 'Invalid grant: code not found'
+ ));
+
+ $this->gateway->oauth()->_mapError($result);
+
+ $this->assertEquals($result->error, 'invalid_grant');
+ $this->assertEquals($result->errorDescription, 'code not found');
+ }
+
+ public function testMapInvalidCredentialsCodeToOldError()
+ {
+ $result = $this->_buildResult(array(
+ 'code' => '93802',
+ 'message' => 'Invalid credentials: wrong client id or secret'
+ ));
+
+ $this->gateway->oauth()->_mapError($result);
+
+ $this->assertEquals($result->error, 'invalid_credentials');
+ $this->assertEquals($result->errorDescription, 'wrong client id or secret');
+ }
+
+ public function testMapInvalidScopeCodeToOldError()
+ {
+ $result = $this->_buildResult(array(
+ 'code' => '93803',
+ 'message' => 'Invalid scope: scope is invalid'
+ ));
+
+ $this->gateway->oauth()->_mapError($result);
+
+ $this->assertEquals($result->error, 'invalid_scope');
+ $this->assertEquals($result->errorDescription, 'scope is invalid');
+ }
+
+ protected function _buildResult($error)
+ {
+ return new Braintree_Result_Error(array(
+ 'errors' => array(
+ 'errors' => array(),
+ 'credentials' => array(
+ 'errors' => array($error)
+ )
+ )
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/PayPalAccountTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/PayPalAccountTest.php
new file mode 100644
index 0000000..40820dd
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/PayPalAccountTest.php
@@ -0,0 +1,39 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_PayPalAccountTest extends PHPUnit_Framework_TestCase
+{
+ function testGet_givesErrorIfInvalidProperty()
+ {
+ $this->setExpectedException('PHPUnit_Framework_Error', 'Undefined property on Braintree_PayPalAccount: foo');
+ $paypalAccount = Braintree_PayPalAccount::factory(array());
+ $paypalAccount->foo;
+ }
+
+ function testIsDefault()
+ {
+ $paypalAccount = Braintree_PayPalAccount::factory(array('default' => true));
+ $this->assertTrue($paypalAccount->isDefault());
+
+ $paypalAccount = Braintree_PayPalAccount::factory(array('default' => false));
+ $this->assertFalse($paypalAccount->isDefault());
+ }
+
+ function testErrorsOnFindWithBlankArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_PayPalAccount::find('');
+ }
+
+ function testErrorsOnFindWithWhitespaceArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_PayPalAccount::find(' ');
+ }
+
+ function testErrorsOnFindWithWhitespaceCharacterArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_PayPalAccount::find('\t');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/PaymentMethodTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/PaymentMethodTest.php
new file mode 100644
index 0000000..9242965
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/PaymentMethodTest.php
@@ -0,0 +1,54 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_PaymentMethodTest extends PHPUnit_Framework_TestCase
+{
+ function testCreate_throwsIfInvalidKey()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'invalid keys: invalidKey');
+ Braintree_PaymentMethod::create(array('invalidKey' => 'foo'));
+ }
+
+ function testCreateSignature()
+ {
+ $expected = array(
+ 'billingAddressId',
+ 'cardholderName',
+ 'cvv',
+ 'deviceData',
+ 'expirationDate',
+ 'expirationMonth',
+ 'expirationYear',
+ 'number',
+ 'paymentMethodNonce',
+ 'token',
+ array('options' => array(
+ 'failOnDuplicatePaymentMethod',
+ 'makeDefault',
+ 'verificationMerchantAccountId',
+ 'verifyCard'
+ )),
+ array('billingAddress' => Braintree_AddressGateway::createSignature()),
+ 'customerId'
+ );
+ $this->assertEquals($expected, Braintree_PaymentMethodGateway::createSignature());
+ }
+
+ function testErrorsOnFindWithBlankArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_PaymentMethod::find('');
+ }
+
+ function testErrorsOnFindWithWhitespaceArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_PaymentMethod::find(' ');
+ }
+
+ function testErrorsOnFindWithWhitespaceCharacterArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_PaymentMethod::find('\t');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/RangeNodeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/RangeNodeTest.php
new file mode 100644
index 0000000..1282a6a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/RangeNodeTest.php
@@ -0,0 +1,33 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_RangeNodeTest extends PHPUnit_Framework_TestCase
+{
+ function testGreaterThanOrEqualTo()
+ {
+ $node = new Braintree_RangeNode('field');
+ $node->greaterThanOrEqualTo('smallest');
+ $this->assertEquals(array('min' => 'smallest'), $node->toParam());
+ }
+
+ function testLessThanOrEqualTo()
+ {
+ $node = new Braintree_RangeNode('field');
+ $node->lessThanOrEqualTo('biggest');
+ $this->assertEquals(array('max' => 'biggest'), $node->toParam());
+ }
+
+ function testBetween()
+ {
+ $node = new Braintree_RangeNode('field');
+ $node->between('alpha', 'omega');
+ $this->assertEquals(array('min' => 'alpha', 'max' => 'omega'), $node->toParam());
+ }
+
+ function testIs()
+ {
+ $node = new Braintree_RangeNode('field');
+ $node->is('something');
+ $this->assertEquals(array('is' => 'something'), $node->toParam());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/ResourceCollectionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/ResourceCollectionTest.php
new file mode 100644
index 0000000..b5da04a
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/ResourceCollectionTest.php
@@ -0,0 +1,83 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_TestResource
+{
+ public function lookup($id) {
+ return Braintree_ResourceCollectionTest::$values[intval($id)];
+ }
+
+ public function fetch($ids)
+ {
+
+ return array_map("Braintree_TestResource::lookup", $ids);
+ }
+}
+
+class Braintree_ResourceCollectionTest extends PHPUnit_Framework_TestCase
+{
+ public static $values = array("a", "b", "c", "d", "e");
+
+ function testIterateOverResults()
+ {
+
+ $response = array(
+ 'searchResults' => array(
+ 'pageSize' => 2,
+ 'ids' => array('0', '1', '2', '3', '4')
+ )
+ );
+
+ $object = new Braintree_TestResource();
+ $pager = array(
+ 'object' => $object,
+ 'method' => 'fetch',
+ 'methodArgs' => array()
+ );
+
+ $collection = new Braintree_ResourceCollection($response, $pager);
+
+ $count = 0;
+ $index = 0;
+ foreach ($collection as $value)
+ {
+ $this->assertEquals(Braintree_ResourceCollectionTest::$values[$index], $value);
+ $index += 1;
+ $count += 1;
+ }
+
+ $this->assertEquals(5, $count);
+ }
+
+ function testDoesntIterateWhenNoResults()
+ {
+
+ $response = array(
+ 'searchResults' => array(
+ 'pageSize' => 2,
+ 'ids' => array()
+ )
+ );
+
+ $object = new Braintree_TestResource();
+ $pager = array(
+ 'object' => $object,
+ 'method' => 'fetch',
+ 'methodArgs' => array()
+ );
+
+ $collection = new Braintree_ResourceCollection($response, $pager);
+
+ $count = 0;
+ $index = 0;
+ foreach ($collection as $value)
+ {
+ $index += 1;
+ $count += 1;
+ break;
+ }
+
+ $this->assertEquals(0, $count);
+ $this->assertEquals(0, $index);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/ErrorTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/ErrorTest.php
new file mode 100644
index 0000000..6b690c7
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/ErrorTest.php
@@ -0,0 +1,11 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../../TestHelper.php';
+
+class Braintree_Result_ErrorTest extends PHPUnit_Framework_TestCase
+{
+ function testCallingNonExsitingFieldReturnsNull()
+ {
+ $result = new Braintree_Result_Error(array('errors' => array(), 'params' => array(), 'message' => 'briefly describe'));
+ $this->assertNull($result->transaction);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/SuccessfulTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/SuccessfulTest.php
new file mode 100644
index 0000000..9532be8
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Result/SuccessfulTest.php
@@ -0,0 +1,16 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../../TestHelper.php';
+
+class Braintree_Result_SuccessfulTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException PHPUnit_Framework_Error_Notice
+ * @expectedExceptionMessage Undefined property on Braintree_Result_Successful: notAProperty
+ */
+ function testCallingNonExsitingFieldReturnsNull()
+ {
+ $result = new Braintree_Result_Successful(1, "transaction");
+ $this->assertNotNull($result->transaction);
+ $this->assertNull($result->notAProperty);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/SanityTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/SanityTest.php
new file mode 100644
index 0000000..69f86c7
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/SanityTest.php
@@ -0,0 +1,15 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_SanityTest extends PHPUnit_Framework_TestCase
+{
+ function testCodeFiles_allOmitPHPCloseTag()
+ {
+ $codeFiles = explode("\n", shell_exec("find ./lib -name \*.php"));
+ foreach ($codeFiles as $codeFile) {
+ if ($codeFile == "") continue;
+ $code = file_get_contents($codeFile);
+ $this->assertNotContains("?>", $code, "$codeFile should not contain a PHP close tag");
+ }
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionSearchTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionSearchTest.php
new file mode 100644
index 0000000..885640b
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionSearchTest.php
@@ -0,0 +1,59 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_SubscriptionSearchTest extends PHPUnit_Framework_TestCase
+{
+ function testSearch_billingCyclesRemaining_isRangeNode()
+ {
+ $node = Braintree_SubscriptionSearch::billingCyclesRemaining();
+ $this->assertInstanceOf('Braintree_RangeNode', $node);
+ }
+
+ function testSearch_price_isRangeNode()
+ {
+ $node = Braintree_SubscriptionSearch::price();
+ $this->assertInstanceOf('Braintree_RangeNode', $node);
+ }
+
+ function testSearch_daysPastDue_isRangeNode()
+ {
+ $node = Braintree_SubscriptionSearch::daysPastDue();
+ $this->assertInstanceOf('Braintree_RangeNode', $node);
+ }
+
+ function testSearch_id_isTextNode()
+ {
+ $node = Braintree_SubscriptionSearch::id();
+ $this->assertInstanceOf('Braintree_TextNode', $node);
+ }
+
+ function testSearch_ids_isMultipleValueNode()
+ {
+ $node = Braintree_SubscriptionSearch::ids();
+ $this->assertInstanceOf('Braintree_MultipleValueNode', $node);
+ }
+
+ function testSearch_inTrialPeriod_isMultipleValueNode()
+ {
+ $node = Braintree_SubscriptionSearch::inTrialPeriod();
+ $this->assertInstanceOf('Braintree_MultipleValueNode', $node);
+ }
+
+ function testSearch_merchantAccountId_isMultipleValueNode()
+ {
+ $node = Braintree_SubscriptionSearch::merchantAccountId();
+ $this->assertInstanceOf('Braintree_MultipleValueNode', $node);
+ }
+
+ function testSearch_planId_isMultipleValueOrTextNode()
+ {
+ $node = Braintree_SubscriptionSearch::planId();
+ $this->assertInstanceOf('Braintree_MultipleValueOrTextNode', $node);
+ }
+
+ function testSearch_status_isMultipleValueNode()
+ {
+ $node = Braintree_SubscriptionSearch::status();
+ $this->assertInstanceOf('Braintree_MultipleValueNode', $node);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionTest.php
new file mode 100644
index 0000000..00ec665
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/SubscriptionTest.php
@@ -0,0 +1,17 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_SubscriptionTest extends PHPUnit_Framework_TestCase
+{
+ function testErrorsOnFindWithBlankArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Subscription::find('');
+ }
+
+ function testErrorsOnFindWithWhitespaceArgument()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Subscription::find('\t');
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/TextNodeTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/TextNodeTest.php
new file mode 100644
index 0000000..db43056
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/TextNodeTest.php
@@ -0,0 +1,40 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_TextNodeTest extends PHPUnit_Framework_TestCase
+{
+ function testIs()
+ {
+ $node = new Braintree_TextNode('field');
+ $node->is('value');
+ $this->assertEquals(array('is' => 'value'), $node->toParam());
+ }
+
+ function testIsNot()
+ {
+ $node = new Braintree_TextNode('field');
+ $node->isNot('value');
+ $this->assertEquals(array('is_not' => 'value'), $node->toParam());
+ }
+
+ function testStartsWith()
+ {
+ $node = new Braintree_TextNode('field');
+ $node->startsWith('beginning');
+ $this->assertEquals(array('starts_with' => 'beginning'), $node->toParam());
+ }
+
+ function testEndsWith()
+ {
+ $node = new Braintree_TextNode('field');
+ $node->endsWith('end');
+ $this->assertEquals(array('ends_with' => 'end'), $node->toParam());
+ }
+
+ function testContains()
+ {
+ $node = new Braintree_TextNode('field');
+ $node->contains('middle');
+ $this->assertEquals(array('contains' => 'middle'), $node->toParam());
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/TransactionTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/TransactionTest.php
new file mode 100644
index 0000000..336dc78
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/TransactionTest.php
@@ -0,0 +1,45 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_TransactionTest extends PHPUnit_Framework_TestCase
+{
+ function testGet_givesErrorIfInvalidProperty()
+ {
+ $t = Braintree_Transaction::factory(array(
+ 'creditCard' => array('expirationMonth' => '05', 'expirationYear' => '2010', 'bin' => '510510', 'last4' => '5100'),
+ 'customer' => array(),
+ 'billing' => array(),
+ 'descriptor' => array(),
+ 'shipping' => array(),
+ 'subscription' => array('billingPeriodStartDate' => '1983-07-12'),
+ 'statusHistory' => array()
+ ));
+ $this->setExpectedException('PHPUnit_Framework_Error', 'Undefined property on Braintree_Transaction: foo');
+ $t->foo;
+ }
+
+ function testCloneTransaction_RaisesErrorOnInvalidProperty()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Transaction::cloneTransaction('an id', array('amount' => '123.45', 'invalidProperty' => 'foo'));
+ }
+
+ function testErrorsWhenFindWithBlankString()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Transaction::find('');
+ }
+
+ function testErrorsWhenFindWithWhitespaceString()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Transaction::find('\t');
+ }
+
+ function testInitializationWithoutArguments()
+ {
+ $transaction = Braintree_Transaction::factory(array());
+
+ $this->assertTrue($transaction instanceof Braintree_Transaction);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/TransparentRedirectTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/TransparentRedirectTest.php
new file mode 100644
index 0000000..94f7794
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/TransparentRedirectTest.php
@@ -0,0 +1,26 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_TransparentRedirectTest extends PHPUnit_Framework_TestCase
+{
+ function testData_specifiesArgSeparatorAsAmpersand()
+ {
+ $originalSeparator = ini_get("arg_separator.output");
+ ini_set("arg_separator.output", "&amp;");
+ $trData = Braintree_TransparentRedirect::createCustomerData(array('redirectUrl' => 'http://www.example.com'));
+ ini_set("arg_separator.output", $originalSeparator);
+ $this->assertFalse(strpos($trData, "&amp;"));
+ }
+
+ function testData_doesNotClobberDefaultTimezone()
+ {
+ $originalZone = date_default_timezone_get();
+ date_default_timezone_set('Europe/London');
+
+ $trData = Braintree_TransparentRedirect::createCustomerData(array('redirectUrl' => 'http://www.example.com'));
+ $zoneAfterCall = date_default_timezone_get();
+ date_default_timezone_set($originalZone);
+
+ $this->assertEquals('Europe/London', $zoneAfterCall);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/UnknownPaymentMethodTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/UnknownPaymentMethodTest.php
new file mode 100644
index 0000000..b1e1780
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/UnknownPaymentMethodTest.php
@@ -0,0 +1,20 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_UnknownPaymentMethodTest extends PHPUnit_Framework_TestCase
+{
+ function testHandlesUnknownPaymentMethodResponses()
+ {
+ $response = array(
+ 'unkownPaymentMethod' => array(
+ 'token' => 'SOME_TOKEN',
+ 'default' => true
+ )
+ );
+ $unknownPaymentMethodObject = Braintree_UnknownPaymentMethod::factory($response);
+ $this->assertEquals('SOME_TOKEN', $unknownPaymentMethodObject->token);
+ $this->assertTrue($unknownPaymentMethodObject->isDefault());
+ $this->assertEquals('https://assets.braintreegateway.com/payment_method_logo/unknown.png', $unknownPaymentMethodObject->imageUrl);
+ }
+}
+
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/UtilTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/UtilTest.php
new file mode 100644
index 0000000..ba316f9
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/UtilTest.php
@@ -0,0 +1,235 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_UtilTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException Braintree_Exception_Authentication
+ */
+ function testThrow401Exception()
+ {
+ Braintree_Util::throwStatusCodeException(401);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Authorization
+ */
+ function testThrow403Exception()
+ {
+ Braintree_Util::throwStatusCodeException(403);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_NotFound
+ */
+ function testThrow404Exception()
+ {
+ Braintree_Util::throwStatusCodeException(404);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_UpgradeRequired
+ */
+ function testThrow426Exception()
+ {
+ Braintree_Util::throwStatusCodeException(426);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_ServerError
+ */
+ function testThrow500Exception()
+ {
+ Braintree_Util::throwStatusCodeException(500);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_DownForMaintenance
+ */
+ function testThrow503Exception()
+ {
+ Braintree_Util::throwStatusCodeException(503);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Unexpected
+ */
+ function testThrowUnknownException()
+ {
+ Braintree_Util::throwStatusCodeException(999);
+ }
+
+ function testExtractAttributeAsArrayReturnsEmptyArray()
+ {
+ $attributes = array();
+ $this->assertEquals(array(), Braintree_Util::extractAttributeAsArray($attributes, "foo"));
+ }
+
+ function testDelimeterToUnderscore()
+ {
+ $this->assertEquals("a_b_c", Braintree_Util::delimiterToUnderscore("a-b-c"));
+ }
+
+ function testCleanClassName()
+ {
+ $cn = Braintree_Util::cleanClassName('Braintree_Transaction');
+ $this->assertEquals('transaction', $cn);
+ }
+
+ function testimplodeAssociativeArray()
+ {
+ $array = array(
+ 'test1' => 'val1',
+ 'test2' => 'val2',
+ 'test3' => new DateTime('2015-05-15 17:21:00'),
+ );
+ $string = Braintree_Util::implodeAssociativeArray($array);
+ $this->assertEquals('test1=val1, test2=val2, test3=Fri, 15 May 2015 17:21:00 +0000', $string);
+ }
+
+ function testVerifyKeys_withThreeLevels()
+ {
+ $signature = array(
+ 'firstName',
+ array('creditCard' => array('number', array('billingAddress' => array('streetAddress'))))
+ );
+ $data = array(
+ 'firstName' => 'Dan',
+ 'creditCard' => array(
+ 'number' => '5100',
+ 'billingAddress' => array(
+ 'streetAddress' => '1 E Main St'
+ )
+ )
+ );
+ Braintree_Util::verifyKeys($signature, $data);
+ }
+
+ function testVerifyKeys_withArrayOfArrays()
+ {
+ $signature = array(
+ array('addOns' => array(array('update' => array('amount', 'existingId'))))
+ );
+
+ $goodData = array(
+ 'addOns' => array(
+ 'update' => array(
+ array(
+ 'amount' => '50.00',
+ 'existingId' => 'increase_10',
+ ),
+ array(
+ 'amount' => '60.00',
+ 'existingId' => 'increase_20',
+ )
+ )
+ )
+ );
+
+ Braintree_Util::verifyKeys($signature, $goodData);
+
+ $badData = array(
+ 'addOns' => array(
+ 'update' => array(
+ array(
+ 'invalid' => '50.00',
+ )
+ )
+ )
+ );
+
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Util::verifyKeys($signature, $badData);
+ }
+
+ function testVerifyKeys_arrayAsValue()
+ {
+ $signature = array('key');
+ $data = array('key' => array('value'));
+ $this->setExpectedException('InvalidArgumentException');
+ Braintree_Util::verifyKeys($signature, $data);
+ }
+
+ function testVerifyKeys()
+ {
+ $signature = array(
+ 'amount', 'customerId', 'orderId', 'channel', 'paymentMethodToken', 'type',
+
+ array('creditCard' =>
+ array('token', 'cvv', 'expirationDate', 'number'),
+ ),
+ array('customer' =>
+ array(
+ 'id', 'company', 'email', 'fax', 'firstName',
+ 'lastName', 'phone', 'website'),
+ ),
+ array('billing' =>
+ array(
+ 'firstName', 'lastName', 'company', 'countryName',
+ 'extendedAddress', 'locality', 'postalCode', 'region',
+ 'streetAddress'),
+ ),
+ array('shipping' =>
+ array(
+ 'firstName', 'lastName', 'company', 'countryName',
+ 'extendedAddress', 'locality', 'postalCode', 'region',
+ 'streetAddress'),
+ ),
+ array('options' =>
+ array(
+ 'storeInVault', 'submitForSettlement',
+ 'addBillingAddressToPaymentMethod'),
+ ),
+ array('customFields' => array('_anyKey_')
+ ),
+ );
+
+ // test valid
+ $userKeys = array(
+ 'amount' => '100.00',
+ 'customFields' => array('HEY' => 'HO',
+ 'WAY' => 'NO'),
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ );
+
+ $n = Braintree_Util::verifyKeys($signature, $userKeys);
+ $this->assertNull($n);
+
+ $userKeys = array(
+ 'amount' => '100.00',
+ 'customFields' => array('HEY' => 'HO',
+ 'WAY' => 'NO'),
+ 'bogus' => 'FAKE',
+ 'totallyFake' => 'boom',
+ 'creditCard' => array(
+ 'number' => '5105105105105100',
+ 'expirationDate' => '05/12',
+ ),
+ );
+
+ // test invalid
+ $this->setExpectedException('InvalidArgumentException');
+
+ Braintree_Util::verifyKeys($signature, $userKeys);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_ValidationsFailed
+ */
+ function testReturnException()
+ {
+ $this->success = false;
+ Braintree_Util::returnObjectOrThrowException('Braintree_Transaction', $this);
+ }
+
+ function testReturnObject()
+ {
+ $this->success = true;
+ $this->transaction = new stdClass();
+ $t = Braintree_Util::returnObjectOrThrowException('Braintree_Transaction', $this);
+ $this->assertInternalType('object', $t);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/WebhookNotificationTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/WebhookNotificationTest.php
new file mode 100644
index 0000000..61c2c0d
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/WebhookNotificationTest.php
@@ -0,0 +1,408 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_WebhookNotificationTest extends PHPUnit_Framework_TestCase
+{
+ function setup()
+ {
+ integrationMerchantConfig();
+ }
+
+ function testVerify()
+ {
+ $verificationString = Braintree_WebhookNotification::verify('20f9f8ed05f77439fe955c977e4c8a53');
+ $this->assertEquals('integration_public_key|d9b899556c966b3f06945ec21311865d35df3ce4', $verificationString);
+ }
+
+ /**
+ * @expectedException Braintree_Exception_InvalidChallenge
+ * @expectedExceptionMessage challenge contains non-hex characters
+ */
+ function testVerifyRaisesErrorWithInvalidChallenge()
+ {
+ $this->setExpectedException('Braintree_Exception_InvalidChallenge', 'challenge contains non-hex characters');
+
+ Braintree_WebhookNotification::verify('bad challenge');
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree_Gateway).
+ */
+ function testVerifyRaisesErrorWhenEnvironmentNotSet()
+ {
+ Braintree_Configuration::reset();
+
+ Braintree_WebhookNotification::verify('20f9f8ed05f77439fe955c977e4c8a53');
+ }
+
+ function testSampleNotificationReturnsAParsableNotification()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE, $webhookNotification->kind);
+ $this->assertNotNull($webhookNotification->timestamp);
+ $this->assertEquals("my_id", $webhookNotification->subscription->id);
+ }
+
+ function testParsingModifiedSignatureRaisesError()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature', 'signature does not match payload - one has been modified');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'] . "bad",
+ $sampleNotification['bt_payload']
+ );
+ }
+
+ /**
+ * @expectedException Braintree_Exception_Configuration
+ * @expectedExceptionMessage Braintree_Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree_Gateway).
+ */
+ function testParsingWithNoKeysRaisesError()
+ {
+ Braintree_Configuration::reset();
+
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+ }
+
+ function testParsingWebhookWithWrongKeysRaisesError()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ Braintree_Configuration::environment('development');
+ Braintree_Configuration::merchantId('integration_merchant_id');
+ Braintree_Configuration::publicKey('wrong_public_key');
+ Braintree_Configuration::privateKey('wrong_private_key');
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature', 'no matching public key');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ "bad" . $sampleNotification['bt_payload']
+ );
+ }
+
+ function testParsingModifiedPayloadRaisesError()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ "bad" . $sampleNotification['bt_payload']
+ );
+ }
+
+ function testParsingUnknownPublicKeyRaisesError()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ "bad" . $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+ }
+
+ function testParsingInvalidSignatureRaisesError()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ "bad_signature",
+ $sampleNotification['bt_payload']
+ );
+ }
+
+ function testParsingInvalidCharactersRaisesError()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature', 'payload contains illegal characters');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ "~*~*invalid*~*~"
+ );
+ }
+
+ function testParsingAllowsAllValidCharacters()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $this->setExpectedException('Braintree_Exception_InvalidSignature', 'signature does not match payload - one has been modified');
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+=/\n"
+ );
+ }
+
+ function testParsingRetriesPayloadWithANewline()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUBSCRIPTION_WENT_PAST_DUE,
+ 'my_id'
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ rtrim($sampleNotification['bt_payload'])
+ );
+ }
+
+ function testBuildsASampleNotificationForAMerchantAccountApprovedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->merchantAccount->id);
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_ACTIVE, $webhookNotification->merchantAccount->status);
+ $this->assertEquals("master_ma_for_my_id", $webhookNotification->merchantAccount->masterMerchantAccount->id);
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_ACTIVE, $webhookNotification->merchantAccount->masterMerchantAccount->status);
+ }
+
+ function testBuildsASampleNotificationForAMerchantAccountDeclinedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->merchantAccount->id);
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_SUSPENDED, $webhookNotification->merchantAccount->status);
+ $this->assertEquals("master_ma_for_my_id", $webhookNotification->merchantAccount->masterMerchantAccount->id);
+ $this->assertEquals(Braintree_MerchantAccount::STATUS_SUSPENDED, $webhookNotification->merchantAccount->masterMerchantAccount->status);
+ $this->assertEquals("Credit score is too low", $webhookNotification->message);
+ $errors = $webhookNotification->errors->forKey('merchantAccount')->onAttribute('base');
+ $this->assertEquals(Braintree_Error_Codes::MERCHANT_ACCOUNT_DECLINED_OFAC, $errors[0]->code);
+ }
+
+ function testBuildsASampleNotificationForATransactionDisbursedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::TRANSACTION_DISBURSED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::TRANSACTION_DISBURSED, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->transaction->id);
+ $this->assertEquals(100, $webhookNotification->transaction->amount);
+ $this->assertNotNull($webhookNotification->transaction->disbursementDetails->disbursementDate);
+ }
+
+ function testBuildsASampleNotificationForADisputeOpenedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::DISPUTE_OPENED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::DISPUTE_OPENED, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->dispute->id);
+ $this->assertEquals(Braintree_Dispute::OPEN, $webhookNotification->dispute->status);
+ }
+
+ function testBuildsASampleNotificationForADisputeLostWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::DISPUTE_LOST,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::DISPUTE_LOST, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->dispute->id);
+ $this->assertEquals(Braintree_Dispute::LOST, $webhookNotification->dispute->status);
+ }
+
+ function testBuildsASampleNotificationForADisputeWonWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::DISPUTE_WON,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::DISPUTE_WON, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->dispute->id);
+ $this->assertEquals(Braintree_Dispute::WON, $webhookNotification->dispute->status);
+ }
+
+ function testBuildsASampleNotificationForADisbursementExceptionWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::DISBURSEMENT_EXCEPTION,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+
+ $this->assertEquals(Braintree_WebhookNotification::DISBURSEMENT_EXCEPTION, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->disbursement->id);
+ $this->assertEquals(false, $webhookNotification->disbursement->retry);
+ $this->assertEquals(false, $webhookNotification->disbursement->success);
+ $this->assertEquals("bank_rejected", $webhookNotification->disbursement->exceptionMessage);
+ $this->assertEquals(100.00, $webhookNotification->disbursement->amount);
+ $this->assertEquals("update_funding_information", $webhookNotification->disbursement->followUpAction);
+ $this->assertEquals("merchant_account_token", $webhookNotification->disbursement->merchantAccount->id);
+ $this->assertEquals(new DateTime("2014-02-10"), $webhookNotification->disbursement->disbursementDate);
+ $this->assertEquals(array("asdfg", "qwert"), $webhookNotification->disbursement->transactionIds);
+ }
+
+ function testBuildsASampleNotificationForADisbursementWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::DISBURSEMENT,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+
+ $this->assertEquals(Braintree_WebhookNotification::DISBURSEMENT, $webhookNotification->kind);
+ $this->assertEquals("my_id", $webhookNotification->disbursement->id);
+ $this->assertEquals(false, $webhookNotification->disbursement->retry);
+ $this->assertEquals(true, $webhookNotification->disbursement->success);
+ $this->assertEquals(NULL, $webhookNotification->disbursement->exceptionMessage);
+ $this->assertEquals(100.00, $webhookNotification->disbursement->amount);
+ $this->assertEquals(NULL, $webhookNotification->disbursement->followUpAction);
+ $this->assertEquals("merchant_account_token", $webhookNotification->disbursement->merchantAccount->id);
+ $this->assertEquals(new DateTime("2014-02-10"), $webhookNotification->disbursement->disbursementDate);
+ $this->assertEquals(array("asdfg", "qwert"), $webhookNotification->disbursement->transactionIds);
+ }
+ function testBuildsASampleNotificationForAPartnerMerchantConnectedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::PARTNER_MERCHANT_CONNECTED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::PARTNER_MERCHANT_CONNECTED, $webhookNotification->kind);
+ $this->assertEquals("public_id", $webhookNotification->partnerMerchant->merchantPublicId);
+ $this->assertEquals("public_key", $webhookNotification->partnerMerchant->publicKey);
+ $this->assertEquals("private_key", $webhookNotification->partnerMerchant->privateKey);
+ $this->assertEquals("abc123", $webhookNotification->partnerMerchant->partnerMerchantId);
+ $this->assertEquals("cse_key", $webhookNotification->partnerMerchant->clientSideEncryptionKey);
+ }
+
+ function testBuildsASampleNotificationForAPartnerMerchantDisconnectedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::PARTNER_MERCHANT_DISCONNECTED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::PARTNER_MERCHANT_DISCONNECTED, $webhookNotification->kind);
+ $this->assertEquals("abc123", $webhookNotification->partnerMerchant->partnerMerchantId);
+ }
+
+ function testBuildsASampleNotificationForAPartnerMerchantDeclinedWebhook()
+ {
+ $sampleNotification = Braintree_WebhookTesting::sampleNotification(
+ Braintree_WebhookNotification::PARTNER_MERCHANT_DECLINED,
+ "my_id"
+ );
+
+ $webhookNotification = Braintree_WebhookNotification::parse(
+ $sampleNotification['bt_signature'],
+ $sampleNotification['bt_payload']
+ );
+
+ $this->assertEquals(Braintree_WebhookNotification::PARTNER_MERCHANT_DECLINED, $webhookNotification->kind);
+ $this->assertEquals("abc123", $webhookNotification->partnerMerchant->partnerMerchantId);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_GeneratorTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_GeneratorTest.php
new file mode 100644
index 0000000..7ea2cce
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_GeneratorTest.php
@@ -0,0 +1,105 @@
+<?php
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_Xml_GeneratorTest extends PHPUnit_Framework_TestCase
+{
+ function testSetsTypeAttributeForBooleans()
+ {
+ $expected = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <yes type="boolean">true</yes>
+ <no type="boolean">false</no>
+</root>
+
+XML;
+ $xml = Braintree_Xml::buildXmlFromArray(array(
+ 'root' => array('yes' => true, 'no' => false)
+ ));
+ $this->assertEquals($expected, $xml);
+ }
+
+ function testCreatesArrays()
+ {
+ $expected = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <stuff type="array">
+ <item>foo</item>
+ <item>bar</item>
+ </stuff>
+</root>
+
+XML;
+ $xml = Braintree_Xml::buildXmlFromArray(array(
+ 'root' => array('stuff' => array('foo', 'bar'))
+ ));
+ $this->assertEquals($expected, $xml);
+ }
+
+ function testCreatesWithDashes()
+ {
+ $expected = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <some-stuff>
+ <inner-foo type="integer">42</inner-foo>
+ <bar-bar-bar type="integer">3</bar-bar-bar>
+ </some-stuff>
+</root>
+
+XML;
+ $xml = Braintree_Xml::buildXmlFromArray(array(
+ 'root' => array('someStuff' => array('innerFoo' => 42, 'barBarBar' => 3))
+ ));
+ $this->assertEquals($expected, $xml);
+ }
+
+ function testCreatesArraysWithBooleans()
+ {
+ $expected = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <stuff type="array">
+ <item>true</item>
+ <item>false</item>
+ </stuff>
+</root>
+
+XML;
+ $xml = Braintree_Xml::buildXmlFromArray(array(
+ 'root' => array('stuff' => array(true, false))
+ ));
+ $this->assertEquals($expected, $xml);
+ }
+
+ function testHandlesEmptyArrays()
+ {
+ $expected = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <stuff type="array"/>
+</root>
+
+XML;
+ $xml = Braintree_Xml::buildXmlFromArray(array(
+ 'root' => array('stuff' => array())
+ ));
+ $this->assertEquals($expected, $xml);
+ }
+
+ function testEscapingSpecialChars()
+ {
+ $expected = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <stuff>&lt;&gt;&amp;'&quot;</stuff>
+</root>
+
+XML;
+ $xml = Braintree_Xml::buildXmlFromArray(array(
+ 'root' => array('stuff' => '<>&\'"')
+ ));
+ $this->assertEquals($expected, $xml);
+ }
+}
diff --git a/public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_ParserTest.php b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_ParserTest.php
new file mode 100644
index 0000000..81bc5f1
--- /dev/null
+++ b/public/system/storage/vendor/braintree/braintree_php/tests/unit/Xml_ParserTest.php
@@ -0,0 +1,536 @@
+<?php
+
+require_once realpath(dirname(__FILE__)) . '/../TestHelper.php';
+
+class Braintree_Xml_ParserTest extends PHPUnit_Framework_TestCase
+{
+ function testTypeCastIntegers()
+ {
+ $array = Braintree_Xml::buildArrayFromXml('<root><foo type="integer">123</foo></root>');
+ $this->assertEquals($array, array('root' => array('foo' => 123)));
+
+ }
+
+ function testDashesUnderscores()
+ {
+ $xml =<<<XML
+ <root>
+ <dash-es />
+ <under_scores />
+ </root>
+XML;
+
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(array('root' =>
+ array('dashEs' => '', 'underScores' => '')), $array);
+ }
+
+ function testCustomFieldsUnderscore()
+ {
+ $xml =<<<XML
+ <root>
+ <custom-fields>
+ <with-dashes>convert to underscore</with-dashes>
+ </custom-fields>
+ </root>
+XML;
+
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(array('root' =>
+ array('customFields' => array('with_dashes' => 'convert to underscore'))), $array);
+ }
+
+ function testNullOrEmptyString()
+ {
+ $xml = <<<XML
+ <root>
+ <a_nil_value nil="true"></a_nil_value>
+ <an_empty_string></an_empty_string>
+ </root>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(array('root' =>
+ array('aNilValue' => null, 'anEmptyString' => '')), $array);
+ }
+
+ function testTypeCastsDatetimes()
+ {
+ $xml = <<<XML
+ <root>
+ <created-at type="datetime">2009-10-28T10:19:49Z</created-at>
+ </root>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ date_default_timezone_set('UTC');
+ $dateTime = new DateTime('2009-10-28T10:19:49', new DateTimeZone('UTC'));
+ $this->assertEquals(array('root' => array('createdAt' => $dateTime)), $array);
+ $this->assertInstanceOf('DateTime', $array['root']['createdAt']);
+ }
+
+ function testTypeCastsDates()
+ {
+ $xml = <<<XML
+ <root>
+ <some-date type="date">2009-10-28</some-date>
+ </root>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ date_default_timezone_set('UTC');
+ $dateTime = new DateTime('2009-10-28', new DateTimeZone('UTC'));
+ $this->assertEquals(array('root' => array('someDate' => $dateTime)), $array);
+ }
+
+ function testBuildsArray()
+ {
+ $xml = <<<XML
+ <root>
+ <customers type="array">
+ <customer><name>Adam</name></customer>
+ <customer><name>Ben</name></customer>
+ </customers>
+ </root>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(array('root' =>
+ array('customers' =>
+ array(array('name' => 'Adam'),
+ array('name' => 'Ben'))
+ )
+ ), $array
+ );
+
+ }
+
+ function testReturnsBoolean()
+ {
+ $xml = <<<XML
+ <root>
+ <casted-true type="boolean">true</casted-true>
+ <casted-one type="boolean">1</casted-one>
+ <casted-false type="boolean">false</casted-false>
+ <casted-anything type="boolean">anything</casted-anything>
+ <uncasted-true>true</uncasted-true>
+ </root>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(
+ array('root' =>
+ array('castedTrue' => true,
+ 'castedOne' => true,
+ 'castedFalse' => false,
+ 'castedAnything' => false,
+ 'uncastedTrue' => 'true')
+ ), $array);
+
+ }
+
+ function testEmptyArrayAndNestedElements()
+ {
+ $xml = <<<XML
+ <root>
+ <nested-values>
+ <value>1</value>
+ </nested-values>
+ <no-values type="array"/>
+ </root>
+XML;
+
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(
+ array('root' => array(
+ 'noValues' => array(),
+ 'nestedValues' => array(
+ 'value' => 1
+ )
+ )
+ ), $array);
+ }
+
+ function testParsingNilEqualsTrueAfterArray()
+ {
+ $xml = <<<XML
+ <root>
+ <customer>
+ <first-name>Dan</first-name>
+ </customer>
+ <blank nil="true" />
+ </root>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(null, $array['root']['blank']);
+
+ }
+
+ function testTransactionParsingNil()
+ {
+ $xml = <<<XML
+<transaction>
+ <id>8ysndw</id>
+ <status>settled</status>
+ <type>sale</type>
+ <currency>USD</currency>
+ <amount>1.00</amount>
+ <merchant-account-id>default</merchant-account-id>
+ <order-id nil="true"></order-id>
+ <channel nil="true"></channel>
+ <created-at type="datetime">2010-04-01T19:32:23Z</created-at>
+ <updated-at type="datetime">2010-04-02T08:05:35Z</updated-at>
+ <customer>
+ <id nil="true"></id>
+ <first-name>First</first-name>
+ <last-name>Last</last-name>
+ <company nil="true"></company>
+ <email></email>
+ <website nil="true"></website>
+ <phone nil="true"></phone>
+ <fax nil="true"></fax>
+ </customer>
+ <billing>
+ <id nil="true"></id>
+ <first-name nil="true"></first-name>
+ <last-name nil="true"></last-name>
+ <company>Widgets Inc</company>
+ <street-address>1234 My Street</street-address>
+ <extended-address>Apt 1</extended-address>
+ <locality>Ottawa</locality>
+ <region>ON</region>
+ <postal-code>K1C2N6</postal-code>
+ <country-name>Canada</country-name>
+ </billing>
+ <refund-id nil="true"></refund-id>
+ <shipping>
+ <id nil="true"></id>
+ <first-name nil="true"></first-name>
+ <last-name nil="true"></last-name>
+ <company nil="true"></company>
+ <street-address nil="true"></street-address>
+ <extended-address nil="true"></extended-address>
+ <locality nil="true"></locality>
+ <region nil="true"></region>
+ <postal-code nil="true"></postal-code>
+ <country-name nil="true"></country-name>
+ </shipping>
+ <custom-fields>
+ </custom-fields>
+ <avs-error-response-code nil="true"></avs-error-response-code>
+ <avs-postal-code-response-code>M</avs-postal-code-response-code>
+ <avs-street-address-response-code>M</avs-street-address-response-code>
+ <cvv-response-code>M</cvv-response-code>
+ <processor-authorization-code>13390</processor-authorization-code>
+ <processor-response-code>1000</processor-response-code>
+ <processor-response-text>Approved</processor-response-text>
+ <credit-card>
+ <token nil="true"></token>
+ <bin>510510</bin>
+ <last-4>5100</last-4>
+ <card-type>MasterCard</card-type>
+ <expiration-month>09</expiration-month>
+ <expiration-year>2011</expiration-year>
+ <customer-location>US</customer-location>
+ <cardholder-name nil="true"></cardholder-name>
+ </credit-card>
+ <status-history type="array">
+ <status-event>
+ <timestamp type="datetime">2010-04-01T19:32:24Z</timestamp>
+ <status>authorized</status>
+ <amount>1.00</amount>
+ <user>dmanges-am</user>
+ <transaction-source>API</transaction-source>
+ </status-event>
+ <status-event>
+ <timestamp type="datetime">2010-04-01T19:32:25Z</timestamp>
+ <status>submitted_for_settlement</status>
+ <amount>1.00</amount>
+ <user>dmanges-am</user>
+ <transaction-source>API</transaction-source>
+ </status-event>
+ <status-event>
+ <timestamp type="datetime">2010-04-02T08:05:36Z</timestamp>
+ <status>settled</status>
+ <amount>1.00</amount>
+ <user nil="true"></user>
+ <transaction-source></transaction-source>
+ </status-event>
+ </status-history>
+</transaction>
+XML;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(null, $array['transaction']['avsErrorResponseCode']);
+ $this->assertEquals(null, $array['transaction']['refundId']);
+ $this->assertEquals(null, $array['transaction']['orderId']);
+ $this->assertEquals(null, $array['transaction']['channel']);
+ $this->assertEquals(null, $array['transaction']['customer']['fax']);
+ $this->assertEquals(null, $array['transaction']['creditCard']['token']);
+ $this->assertEquals(null, $array['transaction']['creditCard']['cardholderName']);
+ $this->assertEquals('First', $array['transaction']['customer']['firstName']);
+ $this->assertEquals('Approved', $array['transaction']['processorResponseText']);
+
+ }
+
+ function testParsingWithNodeHavingSameNameAsNodesDirectlyUnderCollection()
+ {
+ $xml = <<<END
+<foos type="collection">
+ <page-size>50</page-size>
+ <bar>
+ <baz>one</baz>
+ </bar>
+ <bar>
+ <baz>two</baz>
+ <bar>bug was here</bar>
+ </bar>
+</foos>
+END;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $this->assertEquals(array('baz' => 'two', 'bar' => 'bug was here'), $array['foos']['bar'][1]);
+ }
+
+ function testParsingCreditCardSearchResults()
+ {
+ $xml = <<<END
+<payment-methods type="collection">
+ <current-page-number type="integer">1</current-page-number>
+ <page-size type="integer">50</page-size>
+ <total-items type="integer">8</total-items>
+ <credit-card>
+ <bin>411111</bin>
+ <cardholder-name>John Doe</cardholder-name>
+ <card-type>Visa</card-type>
+ <created-at type="datetime">2010-07-02T15:50:51Z</created-at>
+ <customer-id>589636</customer-id>
+ <default type="boolean">true</default>
+ <expiration-month>05</expiration-month>
+ <expiration-year>2009</expiration-year>
+ <expired type="boolean">true</expired>
+ <customer-location>US</customer-location>
+ <last-4>1111</last-4>
+ <subscriptions type="array"/>
+ <token>22pb</token>
+ <updated-at type="datetime">2010-07-02T15:50:51Z</updated-at>
+ </credit-card>
+ <credit-card>
+ <bin>411111</bin>
+ <cardholder-name></cardholder-name>
+ <card-type>Visa</card-type>
+ <created-at type="datetime">2010-07-02T15:52:09Z</created-at>
+ <customer-id>613603</customer-id>
+ <default type="boolean">false</default>
+ <expiration-month>05</expiration-month>
+ <expiration-year>2009</expiration-year>
+ <expired type="boolean">true</expired>
+ <customer-location>US</customer-location>
+ <last-4>1111</last-4>
+ <subscriptions type="array">
+ <subscription>
+ <id>hzjh8b</id>
+ <price>54.32</price>
+ <plan-id>integration_trialless_plan</plan-id>
+ <first-billing-date type="date">2010-07-02</first-billing-date>
+ <next-billing-date type="date">2010-08-02</next-billing-date>
+ <billing-period-start-date type="date">2010-07-02</billing-period-start-date>
+ <billing-period-end-date type="date">2010-08-01</billing-period-end-date>
+ <merchant-account-id>sandbox_credit_card</merchant-account-id>
+ <trial-period type="boolean">false</trial-period>
+ <status>Active</status>
+ <failure-count type="integer">0</failure-count>
+ <payment-method-token>3wx6</payment-method-token>
+ <trial-duration nil="true"></trial-duration>
+ <trial-duration-unit nil="true"></trial-duration-unit>
+ <transactions type="array">
+ <transaction>
+ <id>2dpk76</id>
+ <status>submitted_for_settlement</status>
+ <type>sale</type>
+ <currency-iso-code>USD</currency-iso-code>
+ <amount>54.32</amount>
+ <merchant-account-id>sandbox_credit_card</merchant-account-id>
+ <order-id nil="true"></order-id>
+ <channel nil="true"></channel>
+ <created-at type="datetime">2010-07-02T15:52:09Z</created-at>
+ <updated-at type="datetime">2010-07-02T15:52:09Z</updated-at>
+ <customer>
+ <id>613603</id>
+ <first-name>Mike</first-name>
+ <last-name>Jones</last-name>
+ <company nil="true"></company>
+ <email nil="true"></email>
+ <website nil="true"></website>
+ <phone nil="true"></phone>
+ <fax nil="true"></fax>
+ </customer>
+ <billing>
+ <id nil="true"></id>
+ <first-name nil="true"></first-name>
+ <last-name nil="true"></last-name>
+ <company nil="true"></company>
+ <street-address nil="true"></street-address>
+ <extended-address nil="true"></extended-address>
+ <locality nil="true"></locality>
+ <region nil="true"></region>
+ <postal-code nil="true"></postal-code>
+ <country-name nil="true"></country-name>
+ <country-code-alpha2 nil="true"></country-code-alpha2>
+ <country-code-alpha3 nil="true"></country-code-alpha3>
+ <country-code-numeric nil="true"></country-code-numeric>
+ </billing>
+ <refund-id nil="true"></refund-id>
+ <refunded-transaction-id nil="true"></refunded-transaction-id>
+ <shipping>
+ <id nil="true"></id>
+ <first-name nil="true"></first-name>
+ <last-name nil="true"></last-name>
+ <company nil="true"></company>
+ <street-address nil="true"></street-address>
+ <extended-address nil="true"></extended-address>
+ <locality nil="true"></locality>
+ <region nil="true"></region>
+ <postal-code nil="true"></postal-code>
+ <country-name nil="true"></country-name>
+ <country-code-alpha2 nil="true"></country-code-alpha2>
+ <country-code-alpha3 nil="true"></country-code-alpha3>
+ <country-code-numeric nil="true"></country-code-numeric>
+ </shipping>
+ <custom-fields>
+ </custom-fields>
+ <avs-error-response-code nil="true"></avs-error-response-code>
+ <avs-postal-code-response-code>I</avs-postal-code-response-code>
+ <avs-street-address-response-code>I</avs-street-address-response-code>
+ <cvv-response-code>I</cvv-response-code>
+ <gateway-rejection-reason nil="true"></gateway-rejection-reason>
+ <processor-authorization-code>9ZR5QB</processor-authorization-code>
+ <processor-response-code>1000</processor-response-code>
+ <processor-response-text>Approved</processor-response-text>
+ <credit-card>
+ <token>sb8w</token>
+ <bin>411111</bin>
+ <last-4>1111</last-4>
+ <card-type>Visa</card-type>
+ <expiration-month>05</expiration-month>
+ <expiration-year>2010</expiration-year>
+ <customer-location>US</customer-location>
+ <cardholder-name></cardholder-name>
+ </credit-card>
+ <status-history type="array">
+ <status-event>
+ <timestamp type="datetime">2010-07-02T15:52:09Z</timestamp>
+ <status>authorized</status>
+ <amount>54.32</amount>
+ <user>merchant</user>
+ <transaction-source>Recurring</transaction-source>
+ </status-event>
+ <status-event>
+ <timestamp type="datetime">2010-07-02T15:52:09Z</timestamp>
+ <status>submitted_for_settlement</status>
+ <amount>54.32</amount>
+ <user>merchant</user>
+ <transaction-source>Recurring</transaction-source>
+ </status-event>
+ </status-history>
+ <subscription-id>hzjh8b</subscription-id>
+ </transaction>
+ </transactions>
+ </subscription>
+ </subscriptions>
+ <token>3wx6</token>
+ <updated-at type="datetime">2010-07-02T15:52:09Z</updated-at>
+ </credit-card>
+</payment-methods>
+END;
+ $array = Braintree_Xml::buildArrayFromXml($xml);
+ $creditCards = $array['paymentMethods']['creditCard'];
+ $creditCardWithSubscription = $creditCards[1];
+ $transaction = $creditCardWithSubscription['subscriptions'][0]['transactions'][0];
+ $this->assertEquals('411111', $transaction['creditCard']['bin']);
+ $this->assertEquals('1111', $transaction['creditCard']['last4']);
+ $this->assertEquals('Visa', $transaction['creditCard']['cardType']);
+ }
+
+ function xmlAndBack($array)
+ {
+ $xml = Braintree_Xml::buildXmlFromArray($array);
+ return Braintree_Xml::buildArrayFromXml($xml);
+
+ }
+
+ function testSimpleCaseRoundtrip()
+ {
+ $array = array('root' => array(
+ 'foo' => 'fooValue',
+ 'bar' => 'barValue')
+ );
+
+ $array2 = $this->xmlAndBack($array);
+ $this->assertEquals($array, $array2);
+ }
+
+ function testArrayRoundtrip()
+ {
+ $array = array('root' => array (
+ 'items' => array(
+ array('name' => 'first'),
+ array('name' => 'second'),
+ )
+ ));
+ $array2 = $this->xmlAndBack($array);
+ $this->assertEquals($array, $array2);
+ }
+
+ function testBooleanRoundtrip()
+ {
+ $array = array('root' => array(
+ 'stringTrue' => true,
+ 'boolTrue' => true,
+ 'stringFalse' => false,
+ 'boolFalse' => false,
+ ));
+ $array2 = $this->xmlAndBack($array);
+ $this->assertEquals($array, $array2);
+
+ }
+ function testTimestampRoundtrip()
+ {
+ date_default_timezone_set('UTC');
+ $array = array('root' => array(
+ 'aTimestamp' => date('D M d H:i:s e Y', mktime(1, 2, 3, 10, 28, 2009)),
+ ));
+ $array2 = $this->xmlAndBack($array);
+ $this->assertEquals($array, $array2);
+
+ }
+
+ function testNullvsEmptyStringToXml()
+ {
+ $array = array('root' => array(
+ 'anEmptyString' => '',
+ 'aNullValue' => null,
+ ));
+ $xml = Braintree_Xml::buildXmlFromArray($array);
+ $xml2 =<<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <an-empty-string></an-empty-string>
+ <a-null-value nil="true"></a-null-value>
+</root>
+
+XML;
+
+ $this->assertEquals($xml, $xml2);
+ }
+
+ function testIncludesTheEncodingRoundtrip()
+ {
+ $array = array('root' => array(
+ 'root' => 'bar',
+ ));
+ $xml = Braintree_Xml::buildXmlFromArray($array);
+ $this->assertRegExp('<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>', $xml);
+
+ }
+
+ function testRootNodeAndStringRoundtrip()
+ {
+ $array = array('id' => '123');
+ $array2 = $this->xmlAndBack($array);
+ $this->assertEquals($array, $array2);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/.gitignore b/public/system/storage/vendor/cardinity/cardinity-sdk-php/.gitignore
new file mode 100644
index 0000000..16a8fef
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/.gitignore
@@ -0,0 +1,8 @@
+vendor/
+bin/
+build/
+specs/
+phpunit.xml
+phpspec.yml
+tests/info.log
+composer.lock
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/.travis.yml b/public/system/storage/vendor/cardinity/cardinity-sdk-php/.travis.yml
new file mode 100644
index 0000000..abbac7b
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/.travis.yml
@@ -0,0 +1,13 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+
+before_script:
+ - composer self-update
+ - composer update
+
+script:
+ - bin/phpspec run --format=pretty
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/LICENSE b/public/system/storage/vendor/cardinity/cardinity-sdk-php/LICENSE
new file mode 100644
index 0000000..e98d925
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Joe Linn
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/README.md b/public/system/storage/vendor/cardinity/cardinity-sdk-php/README.md
new file mode 100644
index 0000000..cbb099d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/README.md
@@ -0,0 +1,69 @@
+
+Cardinity Client PHP Library
+================================================
+[![Build Status](https://travis-ci.org/cardinity/cardinity-sdk-php.svg?branch=master)](http://travis-ci.org/cardinity/cardinity-sdk-php)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/cardinity/cardinity-sdk-php/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/cardinity/cardinity-sdk-php/?branch=master)
+[![SensioLabsInsight](https://insight.sensiolabs.com/projects/536548a5-73e5-4c71-8a8b-d6fdd6e5e7a6/mini.png)](https://insight.sensiolabs.com/projects/536548a5-73e5-4c71-8a8b-d6fdd6e5e7a6)
+
+This is official PHP client library for [Cardinity's](https://developers.cardinity.com/api/v1/) API.
+Library includes all the functionality provided by API. Library was designed to be flexible and self-explanatory for developers to implement.
+
+## Documentation
+More detailed documentation with usage examples can be found [here](https://github.com/cardinity/cardinity-sdk-php/tree/master/docs).
+
+## Usage
+### Installing via [Composer](https://getcomposer.org)
+```bash
+$ php composer.phar require cardinity/cardinity-sdk-php
+```
+### Direct Download
+You can download the [latest release](https://github.com/cardinity/cardinity-sdk-php/releases/latest) file starting with ```cardinity-sdk-php-*.zip```.
+
+### Making API Calls
+#### Initialize the client object
+```php
+use Cardinity\Client;
+$client = Client::create([
+ 'consumerKey' => 'YOUR_CONSUMER_KEY',
+ 'consumerSecret' => 'YOUR_CONSUMER_SECRET',
+]);
+```
+
+#### Create new payment
+```php
+use Cardinity\Method\Payment;
+$method = new Payment\Create([
+ 'amount' => 50.00,
+ 'currency' => 'EUR',
+ 'settle' => false,
+ 'description' => 'some description',
+ 'order_id' => '12345678',
+ 'country' => 'LT',
+ 'payment_method' => Payment\Create::CARD,
+ 'payment_instrument' => [
+ 'pan' => '4111111111111111',
+ 'exp_year' => 2016,
+ 'exp_month' => 12,
+ 'cvc' => '456',
+ 'holder' => 'Mike Dough'
+ ],
+]);
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $client->call($method);
+$paymentId = $payment->getId();
+// serializes object into string for storing in database
+$serialized = serialize($payment);
+```
+
+#### Get existing payment
+```php
+$method = new Payment\Get('cb5e1c95-7685-4499-a2b1-ae0f28297b92');
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $client->call($method);
+```
+
+## API documentation
+[https://developers.cardinity.com/api/v1/](https://developers.cardinity.com/api/v1/)
+
+## Development Status
+All the API __v1__ methods are implemented.
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/composer.json b/public/system/storage/vendor/cardinity/cardinity-sdk-php/composer.json
new file mode 100644
index 0000000..4cf86f2
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/composer.json
@@ -0,0 +1,30 @@
+{
+ "name": "cardinity/cardinity-sdk-php",
+ "description": "Client library for Cardinity credit card processing API",
+ "type": "library",
+ "license": "MIT",
+ "homepage": "http://cardinity.com",
+ "require": {
+ "php" : ">=5.4.0",
+ "guzzlehttp/guzzle" : "~5.1",
+ "guzzlehttp/log-subscriber" : "~1.0",
+ "guzzlehttp/oauth-subscriber": "0.2.*",
+ "symfony/validator" : "~2.6"
+ },
+ "require-dev": {
+ "monolog/monolog" : "~1.0",
+ "phpspec/phpspec" : "~2.1",
+ "phpunit/phpunit" : "~4.3"
+ },
+ "config": {
+ "bin-dir": "bin"
+ },
+ "autoload": {
+ "psr-4": {"Cardinity\\": "src"}
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Cardinity\\Tests\\": "tests/"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/docs/README.md b/public/system/storage/vendor/cardinity/cardinity-sdk-php/docs/README.md
new file mode 100644
index 0000000..6764604
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/docs/README.md
@@ -0,0 +1,399 @@
+# Introduction
+Library includes all the functionality provided by API. Library was designed to be flexible and self-explanatory for developers to implement.
+Client provides use of API in OOP style.
+
+## Authentication
+You don't have to bother about it. Authentication is handled auto-magically behind the scenes.
+
+## Initialize the client object
+```php
+use Cardinity\Client;
+$client = Client::create([
+ 'consumerKey' => 'YOUR_CONSUMER_KEY',
+ 'consumerSecret' => 'YOUR_CONSUMER_SECRET',
+]);
+```
+
+## Payments [API](https://developers.cardinity.com/api/v1/#payments)
+### Create new payment
+```php
+use Cardinity\Method\Payment;
+$method = new Payment\Create([
+ 'amount' => 50.00,
+ 'currency' => 'EUR',
+ 'settle' => false,
+ 'description' => 'some description',
+ 'order_id' => '12345678',
+ 'country' => 'LT',
+ 'payment_method' => Payment\Create::CARD,
+ 'payment_instrument' => [
+ 'pan' => '4111111111111111',
+ 'exp_year' => 2016,
+ 'exp_month' => 12,
+ 'cvc' => 456,
+ 'holder' => 'Mike Dough'
+ ],
+]);
+
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $client->call($method);
+```
+
+### Handling declined payments
+In case payment could not be processed `Cardinity\Exception\Declined`
+exception will be thrown.
+
+```php
+use Cardinity\Exception;
+use Cardinity\Method\Payment;
+
+$method = new Payment\Create([
+ 'amount' => 150.01,
+ 'currency' => 'EUR',
+ 'settle' => false,
+ 'description' => 'some description',
+ 'order_id' => '12345678',
+ 'country' => 'LT',
+ 'payment_method' => Payment\Create::RECURRING,
+ 'payment_instrument' => [
+ 'pan' => '4111111111111111',
+ 'exp_year' => 2016,
+ 'exp_month' => 12,
+ 'cvc' => 456,
+ 'holder' => 'Mike Dough'
+ ],
+]);
+
+try {
+ /** @type Cardinity\Method\Payment\Payment */
+ $payment = $client->call($method);
+} catch (Exception\Declined $exception) {
+ /** @type Cardinity\Method\Payment\Payment */
+ $payment = $exception->getResult();
+ $status = $payment->getStatus(); // value will be 'declined'
+ $errors = $exception->getErrors(); // list of errors occured
+}
+```
+
+### Create recurring payment
+```php
+use Cardinity\Method\Payment;
+$method = new Payment\Create([
+ 'amount' => 50.00,
+ 'currency' => 'EUR',
+ 'settle' => false,
+ 'description' => 'some description',
+ 'order_id' => '12345678',
+ 'country' => 'LT',
+ 'payment_method' => Payment\Create::RECURRING,
+ 'payment_instrument' => [
+ 'payment_id' => $paymentId
+ ],
+]);
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $client->call($method);
+```
+
+### Finalize pending payment
+```php
+use Cardinity\Method\Payment;
+$method = new Payment\Finalize($payment->getId(), $payment->getAuthorizationInformation()->getData());
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $client->call($method);
+```
+
+### Get existing payment
+```php
+use Cardinity\Method\Payment;
+$method = new Payment\Get($payment->getId());
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $client->call($method);
+```
+
+### Get all payments
+```php
+use Cardinity\Method\Payment;
+$method = new Payment\GetAll();
+$result = $client->call($method);
+/** @type Cardinity\Method\Payment\Payment */
+$payment = $result[0];
+```
+
+## Refunds [API](https://developers.cardinity.com/api/v1/#refunds)
+### Create new refund
+```php
+use Cardinity\Method\Refund;
+$method = new Refund\Create(
+ $payment->getId(),
+ 10.00,
+ 'my description'
+);
+/** @type Cardinity\Method\Refund\Refund */
+$refund = $client->call($method);
+```
+
+### Handling declined refunds
+In case refund could not be processed `Cardinity\Exception\Declined`
+exception will be thrown.
+
+```php
+use Cardinity\Exception;
+use Cardinity\Method\Refund;
+
+$method = new Refund\Create(
+ $payment->getId(),
+ 10.00,
+ 'fail'
+);
+
+try {
+ /** @type Cardinity\Method\Refund\Refund */
+ $refund = $client->call($method);
+} catch (Exception\Declined $exception) {
+ /** @type Cardinity\Method\Refund\Refund */
+ $refund = $exception->getResult();
+ $status = $refund->getStatus(); // value will be 'declined'
+ $errors = $exception->getErrors(); // list of errors occured
+}
+```
+
+### Get existing refund
+```php
+use Cardinity\Method\Refund;
+$method = new Refund\Get(
+ $payment->getId(),
+ $refund->getId()
+);
+/** @type Cardinity\Method\Refund\Refund */
+$refund = $client->call($method);
+```
+
+### Get all refunds
+```php
+use Cardinity\Method\Refund;
+$method = new Refund\GetAll(
+ $payment->getId()
+);
+$result = $client->call($method);
+/** @type Cardinity\Method\Refund\Refund */
+$refund = $result[0];
+```
+
+## Settlements [API](https://developers.cardinity.com/api/v1/#settlements)
+### Create new settlement
+```php
+use Cardinity\Method\Settlement;
+$method = new Settlement\Create(
+ $payment->getId(),
+ 10.00,
+ 'my description'
+);
+/** @type Cardinity\Method\Settlement\Settlement */
+$result = $client->call($method);
+```
+
+### Handling declined settlements
+In case settlement could not be processed `Cardinity\Exception\Declined`
+exception will be thrown.
+
+```php
+use Cardinity\Exception;
+use Cardinity\Method\Settlement;
+
+$method = new Settlement\Create(
+ $payment->getId(),
+ 10.00,
+ 'fail'
+);
+
+try {
+ /** @type Cardinity\Method\Settlement\Settlement */
+ $settlement = $client->call($method);
+} catch (Exception\Declined $exception) {
+ /** @type Cardinity\Method\Settlement\Settlement */
+ $settlement = $exception->getResult();
+ $status = $settlement->getStatus(); // value will be 'declined'
+ $errors = $exception->getErrors(); // list of errors occured
+}
+```
+
+### Get existing settlement
+```php
+use Cardinity\Method\Settlement;
+$method = new Settlement\Get(
+ $payment->getId(),
+ $settlement->getId()
+);
+/** @type Cardinity\Method\Settlement\Settlement */
+$settlement = $client->call($method);
+```
+
+### Get all settlements
+```php
+use Cardinity\Method\Settlement;
+$method = new Settlement\GetAll(
+ $payment->getId()
+);
+$result = $client->call($method);
+/** @type Cardinity\Method\Settlement\Settlement */
+$settlement = $result[0];
+```
+
+## Voids [API](https://developers.cardinity.com/api/v1/#voids)
+### Create new void
+```php
+use Cardinity\Method\Void;
+$method = new Void\Create(
+ $payment->getId(),
+ 'my description'
+);
+/** @type Cardinity\Method\Void\Void */
+$result = $client->call($method);
+```
+
+### Handling declined voids
+In case void could not be processed `Cardinity\Exception\Declined`
+exception will be thrown.
+
+```php
+use Cardinity\Exception;
+use Cardinity\Method\Void;
+
+$method = new Void\Create(
+ $payment->getId(),
+ 'fail'
+);
+
+try {
+ /** @type Cardinity\Method\Void\Void */
+ $void = $client->call($method);
+} catch (Exception\Declined $exception) {
+ /** @type Cardinity\Method\Void\Void */
+ $void = $exception->getResult();
+ $status = $void->getStatus(); // value will be 'declined'
+ $errors = $exception->getErrors(); // list of errors occured
+}
+```
+
+### Get existing void
+```php
+use Cardinity\Method\Void;
+$method = new Void\Get(
+ $payment->getId(),
+ $void->getId()
+);
+/** @type Cardinity\Method\Void\Void */
+$void = $client->call($method);
+```
+
+### Get all voids
+```php
+use Cardinity\Method\Void;
+$method = new Void\GetAll(
+ $payment->getId()
+);
+$result = $client->call($method);
+/** @type Cardinity\Method\Void\Void */
+$void = $result[0];
+```
+
+## Exceptions
+### Exceptions representing API error response
+
+#### Base class for API error response exceptions
+Class: `Cardinity\Exception\Request`
+Methods:
+- `getErrors()` returns list of errors occured
+- `getErrorsAsString()` returns list of errors occured in string form
+- `getResult()` returns object, the instance of `ResultObjectInterface`.
+
+#### All classes
+Class: `Cardinity\Exception\ValidationFailed`
+HTTP status: `400`
+
+Class: `Cardinity\Exception\Unauthorized`
+HTTP status: `401`
+
+Class: `Cardinity\Exception\Declined`
+HTTP status: `402`
+
+Class: `Cardinity\Exception\Forbidden`
+HTTP status: `403`
+
+Class: `Cardinity\Exception\MethodNotAllowed`
+HTTP status: `405`
+
+Class: `Cardinity\Exception\NotAcceptable`
+HTTP status: `406`
+
+Class: `Cardinity\Exception\NotFound`
+HTTP status: `404`
+
+Class: `Cardinity\Exception\InternalServerError`
+HTTP status: `500`
+
+Class: `Cardinity\Exception\ServiceUnavailable`
+HTTP status: `503`
+
+
+### Cardinity client exceptions
+
+#### Request timed out
+Class: `Cardinity\Exception\RequestTimeout`
+
+#### Before-request data validation failed
+Class: `Cardinity\Exception\InvalidAttributeValue`
+Methods:
+- `getViolations()` returns list of validation violations
+
+#### Response mapping to result object failure
+Class: `Cardinity\Exception\ResultObjectInterfacePropertyNotFound`
+Got unexpected response? Response object changed?
+
+#### Unexpected error
+Class: `Cardinity\Exception\UnexpectedError`
+
+#### Base exception class for Cardinity client
+Class: `Cardinity\Exception\Runtime`
+Catching this exception ensures that you handle all cardinity failure use cases.
+
+
+## Advanced use cases
+
+### Debug, log request/response
+`Client::create()` accepts second argument, which defines the logger.
+Available values: `Client::LOG_NONE`, `Client::LOG_DEBUG` or PSR-3 `LoggerInterface`.
+- `Client::LOG_NONE` - log disabled.
+- `Client::LOG_DEBUG` - logs request/response with direct output to the screen.
+- `LoggerInterface` - custom logger implementation, for eg. `Monolog`.
+
+```php
+$client = Client::create($config, Client::LOG_DEBUG);
+```
+
+### Use Monolog for logging
+#### 1. Add monolog to your project
+```bash
+$ composer require monolog/monolog
+```
+#### 2. Register logger to the Cardinity client
+```php
+$logger = new Monolog\Logger('requests');
+$logger->pushHandler(new Monolog\Handler\StreamHandler(__DIR__ . '/requests.log', Logger::INFO));
+$client = Client::create($config, $logger);
+```
+
+### Extending components
+Each part of client library can be easily extended or replaced with another suitable component
+through the corresponding interfaces:
+```php
+public function __construct(
+ Cardinity\Http\ClientInterface $client,
+ Cardinity\Method\ValidatorInterface $validator,
+ Cardinity\Method\ResultObjectMapperInterface $mapper
+) { ... }
+```
+
+For example to replace _Guzzle_ with another http client you want simply create adapter
+for your client library, like `Cardinity\Http\Guzzle\ClientAdapter` which implements
+`Cardinity\Http\ClientInterface`. That's it!
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/phpspec.yml.dist b/public/system/storage/vendor/cardinity/cardinity-sdk-php/phpspec.yml.dist
new file mode 100644
index 0000000..6da04f0
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/phpspec.yml.dist
@@ -0,0 +1,4 @@
+suites:
+ cardinity_suite:
+ namespace: Cardinity
+ psr4_prefix: Cardinity
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/phpunit.xml.dist b/public/system/storage/vendor/cardinity/cardinity-sdk-php/phpunit.xml.dist
new file mode 100644
index 0000000..1fd9f28
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/phpunit.xml.dist
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
+<phpunit
+ backupGlobals = "false"
+ backupStaticAttributes = "false"
+ colors = "true"
+ convertErrorsToExceptions = "true"
+ convertNoticesToExceptions = "true"
+ convertWarningsToExceptions = "true"
+ processIsolation = "false"
+ stopOnFailure = "false"
+ syntaxCheck = "false"
+ bootstrap = "vendor/autoload.php"
+ mapTestClassNameToCoveredClassName = "true"
+ forceCoversAnnotation = "false">
+
+ <php>
+ <!-- For integration tests -->
+ <const name="CONSUMER_KEY" value=""/>
+ <const name="CONSUMER_SECRET" value=""/>
+ </php>
+
+ <testsuites>
+ <testsuite name="Default">
+ <directory>./tests</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/ClientSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/ClientSpec.php
new file mode 100644
index 0000000..4ff4dfe
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/ClientSpec.php
@@ -0,0 +1,204 @@
+<?php
+
+namespace spec\Cardinity;
+
+use Cardinity\Http\ClientInterface;
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Cardinity\Method\ValidatorInterface;
+use Cardinity\Method\Payment\Payment;
+use Cardinity\Method\ResultObjectMapperInterface;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ClientSpec extends ObjectBehavior
+{
+ function let(
+ ClientInterface $client,
+ ValidatorInterface $validator,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $this->beConstructedWith(
+ $client,
+ $validator,
+ $mapper
+ );
+ }
+
+ function it_constructs_via_factory()
+ {
+ $this::create(['consumerKey' => '', 'consumerSecret' => ''])->shouldReturnAnInstanceOf('Cardinity\Client');
+ }
+
+ function it_maps_result_to_object_by_posting_json_body(
+ MethodInterface $method,
+ ClientInterface $client,
+ ValidatorInterface $validator,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $result = ['id' => '3c4e8dcf'];
+ $resultObject = new Payment();
+
+ $method->getMethod()->willReturn('POST');
+ $method->getAction()->willReturn('payment');
+ $method->getAttributes()->willReturn([]);
+ $method->createResultObject()->willReturn($resultObject);
+
+ $validator->validate($method)->shouldBeCalled();
+ $mapper->map($result, $resultObject)->shouldBeCalled()->willReturn($resultObject);
+
+ $client
+ ->sendRequest(
+ $method,
+ 'POST',
+ 'payment',
+ [
+ 'headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ 'body' => '{}',
+ ]
+ )
+ ->shouldBeCalled()
+ ->willReturn($result)
+ ;
+
+ $this->call($method)->shouldReturn($resultObject);
+ }
+
+ function it_maps_result_containing_collection_of_items(
+ MethodResultCollectionInterface $method,
+ ClientInterface $client,
+ ValidatorInterface $validator,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $result = [
+ ['id' => '3c4e8dcf']
+ ];
+ $resultObject = new Payment();
+
+ $method->getMethod()->willReturn('POST');
+ $method->getAction()->willReturn('payment');
+ $method->getAttributes()->willReturn([]);
+ $method->createResultObject()->willReturn($resultObject);
+
+ $validator->validate($method)->shouldBeCalled();
+ $mapper->mapCollection($result, $method)->shouldBeCalled()->willReturn([$resultObject]);
+
+ $client
+ ->sendRequest(
+ $method,
+ 'POST',
+ 'payment',
+ [
+ 'headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ 'body' => '{}',
+ ]
+ )
+ ->shouldBeCalled()
+ ->willReturn($result)
+ ;
+
+ $this->call($method)->shouldReturn([$resultObject]);
+ }
+
+ function it_converts_float_numbers_to_string_for_json_body(
+ MethodInterface $method,
+ ClientInterface $client,
+ ValidatorInterface $validator,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $result = ['amount' => 50.00];
+ $resultObject = new Payment();
+
+ $method->getMethod()->willReturn('POST');
+ $method->getAction()->willReturn('payment');
+ $method->getAttributes()->willReturn(['amount' => 50.00]);
+ $method->createResultObject()->willReturn($resultObject);
+
+ $validator->validate($method)->shouldBeCalled();
+ $mapper->map($result, $resultObject)->shouldBeCalled()->willReturn($resultObject);
+
+ $client
+ ->sendRequest(
+ $method,
+ 'POST',
+ 'payment',
+ [
+ 'headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ 'body' => '{"amount":"50.00"}',
+ ]
+ )
+ ->shouldBeCalled()
+ ->willReturn($result)
+ ;
+
+ $this->call($method)->shouldReturn($resultObject);
+ }
+
+ function it_gets_result_object_by_sending_get_query_params(
+ MethodInterface $method,
+ ClientInterface $client,
+ ValidatorInterface $validator,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $result = ['amount' => 50.00];
+ $resultObject = new Payment();
+
+ $method->getMethod()->willReturn('GET');
+ $method->getAction()->willReturn('payment');
+ $method->getAttributes()->willReturn(['field' => 'value']);
+ $method->createResultObject()->willReturn($resultObject);
+
+ $validator->validate($method)->shouldBeCalled();
+ $mapper->map($result, $resultObject)->shouldBeCalled()->willReturn($resultObject);
+
+ $client
+ ->sendRequest(
+ $method,
+ 'GET',
+ 'payment',
+ ['query' => ['field' => 'value']]
+ )
+ ->shouldBeCalled()
+ ->willReturn($result)
+ ;
+
+ $this->call($method)->shouldReturn($resultObject);
+ }
+
+ function it_performs_request_without_validation(
+ MethodInterface $method,
+ ClientInterface $client,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $result = ['amount' => 50.00];
+ $resultObject = new Payment();
+
+ $method->getMethod()->willReturn('GET');
+ $method->getAction()->willReturn('payment');
+ $method->getAttributes()->willReturn(['field' => 'value']);
+ $method->createResultObject()->willReturn($resultObject);
+
+ $mapper->map($result, $resultObject)->shouldBeCalled()->willReturn($resultObject);
+
+ $client
+ ->sendRequest(
+ $method,
+ 'GET',
+ 'payment',
+ ['query' => ['field' => 'value']]
+ )
+ ->shouldBeCalled()
+ ->willReturn($result)
+ ;
+
+ $this->callNoValidate($method)->shouldReturn($resultObject);
+ }
+
+
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/DeclinedSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/DeclinedSpec.php
new file mode 100644
index 0000000..8c201b7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/DeclinedSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class DeclinedSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Declined');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(402);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ForbiddenSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ForbiddenSpec.php
new file mode 100644
index 0000000..0322a07
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ForbiddenSpec.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ForbiddenSpec extends ObjectBehavior
+{
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Forbidden');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(403);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InternalServerErrorSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InternalServerErrorSpec.php
new file mode 100644
index 0000000..9d35c32
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InternalServerErrorSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class InternalServerErrorSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_should_extend_request()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Request');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(500);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InvalidAttributeValueSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InvalidAttributeValueSpec.php
new file mode 100644
index 0000000..7bea5f5
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/InvalidAttributeValueSpec.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+use Symfony\Component\Validator\ConstraintViolationList;
+
+class InvalidAttributeValueSpec extends ObjectBehavior
+{
+ private $violation = 'This value should not be blank.';
+
+ function let(ConstraintViolationList $violations)
+ {
+ $violations->__toString()->willReturn($this->violation);
+
+ $this->beConstructedWith(
+ 'Message',
+ $violations
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('\RuntimeException');
+ }
+
+ function it_returns_message()
+ {
+ $this->getMessage()->shouldStartWith('Message');
+ }
+
+ function it_returns_violations(ConstraintViolationList $violations)
+ {
+ $this->getViolations()->shouldReturn($violations);
+ }
+
+ function it_should_have_message_containing_violations()
+ {
+ $string = 'Violations: ' . $this->violation;
+ $this->getMessage()->shouldEndWith($string);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/MethodNotAllowedSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/MethodNotAllowedSpec.php
new file mode 100644
index 0000000..fdddf4d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/MethodNotAllowedSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class MethodNotAllowedSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\MethodNotAllowed');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(405);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotAcceptableSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotAcceptableSpec.php
new file mode 100644
index 0000000..2fcc9b6
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotAcceptableSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class NotAcceptableSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\NotAcceptable');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(406);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotFoundSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotFoundSpec.php
new file mode 100644
index 0000000..b632984
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/NotFoundSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class NotFoundSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\NotFound');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(404);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestSpec.php
new file mode 100644
index 0000000..7008fe3
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestSpec.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\Error;
+use Cardinity\Method\Payment\Payment;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class RequestSpec extends ObjectBehavior
+{
+ private $result = [
+ 'errors' => [
+ [
+ 'field' => 'currency',
+ 'rejected' => 'EGR',
+ 'message' => 'invalid or unsupported currency',
+ ],
+ [
+ 'field' => 'payment_instrument.exp_month',
+ 'rejected' => 13,
+ 'message' => 'must be between 1 and 12',
+ ]
+ ]
+ ];
+
+ private $error;
+
+ function let(\RuntimeException $exception)
+ {
+ $this->error = new Error();
+ $this->error->setErrors($this->result['errors']);
+
+ $this->beConstructedWith(
+ $exception,
+ $this->error
+ );
+ }
+
+ function it_should_extend_runtime()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Runtime');
+ }
+
+ function it_stores_previous_exception(\RuntimeException $exception)
+ {
+ $this->getPrevious()->shouldReturn($exception);
+ }
+
+ function it_stores_result()
+ {
+ $this->getResult()->shouldReturn($this->error);
+ }
+
+ function it_should_have_message_containing_response_data()
+ {
+ $string = 'Response data: ' . serialize($this->error);
+ $this->getMessage()->shouldEndWith($string);
+ }
+
+ function it_returns_erros_from_error_result_object()
+ {
+ $this->getErrors()->shouldReturn($this->result['errors']);
+ }
+
+ function it_returns_errors_as_string()
+ {
+ $this
+ ->getErrorsAsString()
+ ->shouldReturn("currency: invalid or unsupported currency ('EGR' given);
+payment_instrument.exp_month: must be between 1 and 12 ('13' given);")
+ ;
+ }
+
+ function it_returns_erros_from_payment_result_object(\RuntimeException $exception)
+ {
+ $msg = 'Payment error';
+
+ $payment = new Payment();
+ $payment->setError($msg);
+ $this->beConstructedWith(
+ $exception,
+ $payment
+ );
+
+ $this->getErrors()->shouldReturn([['field' => 'status', 'message' => $msg]]);
+ $this->getErrorsAsString()->shouldReturn("status: Payment error;");
+ }
+
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestTimeoutSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestTimeoutSpec.php
new file mode 100644
index 0000000..9d5daa3
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/RequestTimeoutSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class RequestTimeoutSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_should_extend_request()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Request');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(0);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ServiceUnavailableSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ServiceUnavailableSpec.php
new file mode 100644
index 0000000..cafecc7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ServiceUnavailableSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ServiceUnavailableSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\ServiceUnavailable');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(503);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnauthorizedSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnauthorizedSpec.php
new file mode 100644
index 0000000..2772fb7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnauthorizedSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class UnauthorizedSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Unauthorized');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(401);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedErrorSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedErrorSpec.php
new file mode 100644
index 0000000..1799c0c
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedErrorSpec.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class UnexpectedErrorSpec extends ObjectBehavior
+{
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('\RuntimeException');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedResponseSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedResponseSpec.php
new file mode 100644
index 0000000..16d3e2f
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/UnexpectedResponseSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class UnexpectedResponseSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_should_extend_request()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Request');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(0);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ValidationFailedSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ValidationFailedSpec.php
new file mode 100644
index 0000000..61de3a7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Exception/ValidationFailedSpec.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace spec\Cardinity\Exception;
+
+use Cardinity\Method\ResultObject;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ValidationFailedSpec extends ObjectBehavior
+{
+ function let(\RuntimeException $exception, ResultObject $error)
+ {
+ $this->beConstructedWith(
+ $exception,
+ $error
+ );
+ }
+
+ function it_should_extend_request()
+ {
+ $this->shouldHaveType('Cardinity\Exception\Request');
+ }
+
+ function it_should_return_correct_code()
+ {
+ $this->getCode()->shouldReturn(400);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ClientAdapterSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ClientAdapterSpec.php
new file mode 100644
index 0000000..7f51946
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ClientAdapterSpec.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace spec\Cardinity\Http\Guzzle;
+
+use Cardinity\Exception;
+use Cardinity\Http\ClientInterface;
+use Cardinity\Http\Guzzle\ExceptionMapper;
+use Cardinity\Method\MethodInterface;
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ClientAdapterSpec extends ObjectBehavior
+{
+ function let(
+ Client $client,
+ ExceptionMapper $mapper,
+ RequestInterface $request
+ ) {
+ $this->beConstructedWith($client, $mapper);
+
+ $client
+ ->createRequest('POST', 'https://api.cardinity.com/v1/', [])
+ ->willReturn($request)
+ ;
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('Cardinity\Http\Guzzle\ClientAdapter');
+ }
+
+ function it_sends_post_and_returns_result(
+ MethodInterface $method,
+ Client $client,
+ RequestInterface $request,
+ ResponseInterface $response
+ ) {
+ $response
+ ->json()
+ ->shouldBeCalled()
+ ->willReturn(['foo' => 'bar'])
+ ;
+ $client
+ ->send($request)
+ ->shouldBeCalled()
+ ->willReturn($response)
+ ;
+ $this
+ ->sendRequest($method, 'POST', 'https://api.cardinity.com/v1/', [])
+ ->shouldReturn(['foo' => 'bar'])
+ ;
+ }
+
+ function it_wraps_client_exceptions_with_ours(
+ MethodInterface $method,
+ ClientInterface $client,
+ RequestInterface $request,
+ ExceptionMapper $mapper,
+ ClientException $exception
+ ) {
+ $client
+ ->send($request)
+ ->willThrow($exception->getWrappedObject())
+ ;
+ $mapper
+ ->get($exception->getWrappedObject(), $method)
+ ->shouldBeCalled()
+ ->willThrow('Cardinity\Exception\Request')
+ ;
+ $this
+ ->shouldThrow('Cardinity\Exception\Request')
+ ->duringSendRequest($method, 'POST', 'https://api.cardinity.com/v1/')
+ ;
+ }
+
+ function it_handles_unexpected_exceptions(
+ MethodInterface $method,
+ ClientInterface $client,
+ RequestInterface $request,
+ \Exception $exception
+ )
+ {
+ $client
+ ->send($request)
+ ->willThrow($exception->getWrappedObject())
+ ;
+ $this
+ ->shouldThrow('Cardinity\Exception\UnexpectedError')
+ ->duringSendRequest($method, 'POST', 'https://api.cardinity.com/v1/')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ExceptionMapperSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ExceptionMapperSpec.php
new file mode 100644
index 0000000..6f35625
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Http/Guzzle/ExceptionMapperSpec.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace spec\Cardinity\Http\Guzzle;
+
+use Cardinity\Method\Error;
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\Payment\Payment;
+use Cardinity\Method\ResultObjectMapperInterface;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Message\Request;
+use GuzzleHttp\Message\Response;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ExceptionMapperSpec extends ObjectBehavior
+{
+ function let(
+ ClientException $exception,
+ Request $request,
+ Response $response,
+ ResultObjectMapperInterface $resultMapper
+ ) {
+ $this->beConstructedWith($resultMapper);
+
+ $exception->beConstructedWith([
+ 'Message',
+ $request->getWrappedObject(),
+ $response->getWrappedObject()
+ ]);
+ }
+
+ function it_maps_expected_exception_code(
+ ClientException $exception,
+ Response $response,
+ MethodInterface $method
+ ) {
+ $response->json()->willReturn([]);
+ $response->getStatusCode()->willReturn(400);
+ $exception->getResponse()->willReturn($response);
+
+ $this
+ ->get($exception, $method)
+ ->shouldReturnAnInstanceOf('Cardinity\Exception\ValidationFailed')
+ ;
+ }
+
+ function it_handles_unexpected_exception_code(
+ ClientException $exception,
+ Response $response,
+ MethodInterface $method
+ ) {
+ $response->json()->willReturn([]);
+ $response->getStatusCode()->willReturn(999);
+ $exception->getResponse()->willReturn($response);
+
+ $this
+ ->get($exception, $method)
+ ->shouldReturnAnInstanceOf('Cardinity\Exception\UnexpectedResponse')
+ ;
+ }
+
+ function it_maps_error_response_to_error_result_object(
+ ClientException $exception,
+ Response $response,
+ ResultObjectMapperInterface $resultMapper,
+ MethodInterface $method
+ ) {
+ $result = ['errors' => ['error' => 'Error string']];
+ $resultObject = new Error();
+
+ $response->getStatusCode()->willReturn(400);
+ $response->json()->willReturn($result);
+
+ $method->createResultObject()->willReturn($resultObject);
+ $exception->getResponse()->willReturn($response);
+
+ $resultMapper
+ ->map($result, $resultObject)
+ ->shouldBeCalled()
+ ->willReturn($resultObject)
+ ;
+
+ $this
+ ->get($exception, $method)
+ ->getResult()
+ ->shouldReturn($resultObject)
+ ;
+ }
+
+ function it_maps_declined_response_402_to_payment_result_object(
+ ClientException $exception,
+ Response $response,
+ ResultObjectMapperInterface $resultMapper,
+ MethodInterface $method
+ ) {
+ $result = ['error' => 'Error string'];
+ $resultObject = new Payment();
+
+ $response->getStatusCode()->willReturn(402);
+ $response->json()->willReturn($result);
+
+ $method->createResultObject()->willReturn($resultObject);
+ $exception->getResponse()->willReturn($response);
+
+ $resultMapper
+ ->map($result, $resultObject)
+ ->shouldBeCalled()
+ ->willReturn($resultObject)
+ ;
+
+ $this
+ ->get($exception, $method)
+ ->getResult()
+ ->shouldReturn($resultObject)
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ErrorSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ErrorSpec.php
new file mode 100644
index 0000000..11ed235
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ErrorSpec.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace spec\Cardinity\Method;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ErrorSpec extends ObjectBehavior
+{
+ function it_implements_result_object_behaviour()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+
+ function it_is_serializable()
+ {
+ $this->shouldImplement('\Serializable');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/AuthorizationInformationSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/AuthorizationInformationSpec.php
new file mode 100644
index 0000000..87386f4
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/AuthorizationInformationSpec.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class AuthorizationInformationSpec extends ObjectBehavior
+{
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/CreateSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/CreateSpec.php
new file mode 100644
index 0000000..c0b6c0f
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/CreateSpec.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class CreateSpec extends ObjectBehavior
+{
+ private $options;
+
+ function let()
+ {
+ $this->options = [
+ 'amount' => 12.99,
+ 'currency' => 'EUR',
+ 'settle' => true,
+ 'order_id' => 'ABC123',
+ 'description' => 'Description',
+ 'country' => 'LT',
+ 'payment_method' => 'card',
+ 'payment_instrument' => [
+ 'pan' => '123456789123',
+ 'exp_year' => '2014',
+ 'exp_month' => '12',
+ 'cvc' => '456',
+ 'holder' => 'Mr Tester',
+ ],
+ ];
+ $this->beConstructedWith($this->options);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_contains_loaded_options()
+ {
+ $this->getAttributes()->shouldReturn($this->options);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn('payments');
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('POST');
+ }
+
+ function it_has_body()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Payment\Payment')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/FinalizeSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/FinalizeSpec.php
new file mode 100644
index 0000000..294c15a
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/FinalizeSpec.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class FinalizeSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $authorizeData = 'fGxdUl3451vdas.......';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->authorizeData);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_authorize_data()
+ {
+ $this->getAuthorizeData()->shouldReturn($this->authorizeData);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn('payments/' . $this->paymentId);
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('PATCH');
+ }
+
+ function it_has_body()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Payment\Payment')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetAllSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetAllSpec.php
new file mode 100644
index 0000000..76a5512
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetAllSpec.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetAllSpec extends ObjectBehavior
+{
+ private $limit = 5;
+
+ function let()
+ {
+ $this->beConstructedWith($this->limit);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodResultCollectionInterface');
+ }
+
+ function it_has_limit()
+ {
+ $this->getLimit()->shouldReturn($this->limit);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn('payments');
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_body()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_has_create_result()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Payment\Payment')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetSpec.php
new file mode 100644
index 0000000..4a933f5
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/GetSpec.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn('payments/' . $this->paymentId);
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Payment\Payment')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentCardSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentCardSpec.php
new file mode 100644
index 0000000..e656d7c
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentCardSpec.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class PaymentInstrumentCardSpec extends ObjectBehavior
+{
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentRecurringSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentRecurringSpec.php
new file mode 100644
index 0000000..d0b9c21
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentInstrumentRecurringSpec.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class PaymentInstrumentRecurringSpec extends ObjectBehavior
+{
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentSpec.php
new file mode 100644
index 0000000..086cfeb
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Payment/PaymentSpec.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace spec\Cardinity\Method\Payment;
+
+use Cardinity\Method\Payment\AuthorizationInformation;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class PaymentSpec extends ObjectBehavior
+{
+ function it_implements_result_object_behaviour()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+
+ function it_is_serializable()
+ {
+ $this->shouldImplement('\Serializable');
+
+ $this->setId('foo');
+ $this->setAmount(20.00);
+ $this->setType(null);
+
+ $info = new AuthorizationInformation();
+ $info->setUrl('http://...');
+ $info->setData('some_data');
+
+ $this->setAuthorizationInformation($info);
+ $this->serialize()->shouldReturn('{"id":"foo","amount":"20.00","authorization_information":{"url":"http:\/\/...","data":"some_data"}}');
+ }
+
+ function it_is_able_to_unserialize_authorization_information()
+ {
+ $json = '{"id":"foo.bar.123","amount":"20.00","authorization_information":{"url":"http:\/\/...","data":"some_data"}}';
+ $this->unserialize($json);
+
+ $this->getId()->shouldReturn('foo.bar.123');
+ $this->getAmount()->shouldReturn(20.00);
+ $this->getType()->shouldReturn(null);
+ $this->getAuthorizationInformation()->shouldReturnAnInstanceOf('Cardinity\Method\Payment\AuthorizationInformation');
+ $this->getAuthorizationInformation()->getUrl()->shouldReturn('http://...');
+ $this->getAuthorizationInformation()->getData()->shouldReturn('some_data');
+ }
+
+ function it_is_able_to_unserialize_card_payment_instrument()
+ {
+ $json = '{"payment_method":"card","payment_instrument":{"card_brand":"Visa","pan":"4447","exp_year":2017,"exp_month":5,"holder":"John Smith"}}';
+ $this->unserialize($json);
+
+ $this->getPaymentMethod()->shouldReturn('card');
+ $this->getPaymentInstrument()->shouldReturnAnInstanceOf('Cardinity\Method\Payment\PaymentInstrumentCard');
+ $this->getPaymentInstrument()->getCardBrand()->shouldReturn('Visa');
+ $this->getPaymentInstrument()->getExpYear()->shouldReturn(2017);
+ }
+
+ function it_is_able_to_unserialize_recurring_payment_instrument()
+ {
+ $json = '{"payment_method":"recurring","payment_instrument":{"payment_id":"ba3119f2-9a73"}}';
+ $this->unserialize($json);
+
+ $this->getPaymentMethod()->shouldReturn('recurring');
+ $this->getPaymentInstrument()->shouldReturnAnInstanceOf('Cardinity\Method\Payment\PaymentInstrumentRecurring');
+ $this->getPaymentInstrument()->getPaymentId()->shouldReturn('ba3119f2-9a73');
+ }
+
+ function it_handles_unexpected_values()
+ {
+ $json = '{"payment_instrument":{"payment_id":"ba3119f2-9a73"}}';
+ $this->shouldThrow('Cardinity\Exception\Runtime')->duringUnserialize($json);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/CreateSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/CreateSpec.php
new file mode 100644
index 0000000..5f84e23
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/CreateSpec.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace spec\Cardinity\Method\Refund;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class CreateSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $description = 'description';
+ private $amount = '10.00';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->amount, $this->description);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_contains_loaded_options()
+ {
+ $this->getAttributes()->shouldReturn([
+ 'amount' => $this->amount,
+ 'description' => $this->description,
+ ]);
+ }
+
+ function it_does_not_contain_optional_properties()
+ {
+ $this->beConstructedWith($this->paymentId, $this->amount);
+
+ $this->getAttributes()->shouldReturn([
+ 'amount' => $this->amount,
+ ]);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ sprintf('payments/%s/refunds', $this->paymentId)
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('POST');
+ }
+
+ function it_has_body()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Refund\Refund')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetAllSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetAllSpec.php
new file mode 100644
index 0000000..3f52a8b
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetAllSpec.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace spec\Cardinity\Method\Refund;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetAllSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ 'payments/' . $this->paymentId . '/refunds'
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_has_create_result()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Refund\Refund')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetSpec.php
new file mode 100644
index 0000000..358aca2
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/GetSpec.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace spec\Cardinity\Method\Refund;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $refundId = '25e6f869-6675-4488-bd47-ccd298f74b3f';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->refundId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_refund_id()
+ {
+ $this->getRefundId()->shouldReturn($this->refundId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ 'payments/' . $this->paymentId . '/refunds/' . $this->refundId
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Refund\Refund')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/RefundSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/RefundSpec.php
new file mode 100644
index 0000000..096e913
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Refund/RefundSpec.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace spec\Cardinity\Method\Refund;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class RefundSpec extends ObjectBehavior
+{
+ function it_implements_result_object_behaviour()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+
+ function it_is_serializable()
+ {
+ $this->shouldImplement('\Serializable');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ResultObjectMapperSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ResultObjectMapperSpec.php
new file mode 100644
index 0000000..1b58ddd
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ResultObjectMapperSpec.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace spec\Cardinity;
+
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Cardinity\Method\Payment\AuthorizationInformation;
+use Cardinity\Method\Payment\Payment;
+use Cardinity\Method\Payment\PaymentInstrumentCard;
+use Cardinity\Method\Payment\PaymentInstrumentRecurring;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class ResultObjectMapperSpec extends ObjectBehavior
+{
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\ResultObjectMapperInterface');
+ }
+
+ function it_maps_array_to_object(Payment $object)
+ {
+ $data = [
+ 'id' => 32,
+ 'type' => 'my_type',
+ ];
+
+ $object->setId(32)->shouldBeCalled();
+ $object->setType('my_type')->shouldBeCalled();
+
+ $this->map($data, $object);
+ }
+
+ function it_throws_exception_if_object_property_not_found(Payment $object)
+ {
+ $data = [
+ 'randomField' => 'randomValue',
+ ];
+
+ $this
+ ->shouldThrow('Cardinity\Exception\ResultObjectInterfacePropertyNotFound')
+ ->duringMap($data, $object)
+ ;
+ }
+
+ function it_maps_card_payment_instrument(Payment $payment)
+ {
+ $data = [
+ 'payment_method' => 'card',
+ 'payment_instrument' => [
+ 'card_brand' => 'Visa',
+ 'pan' => '0067',
+ 'exp_year' => 2016,
+ 'exp_month' => 11,
+ 'holder' => 'Mike Dough'
+ ],
+ ];
+
+ $instrument = new PaymentInstrumentCard();
+ $instrument->setCardBrand('Visa');
+ $instrument->setPan('0067');
+ $instrument->setExpYear(2016);
+ $instrument->setExpMonth(11);
+ $instrument->setHolder('Mike Dough');
+
+ $payment->setPaymentMethod('card')->shouldBeCalled();
+ $payment->setPaymentInstrument($instrument)->shouldBeCalled();
+
+ $this->map($data, $payment)->shouldReturn($payment);
+ }
+
+ function it_maps_recurring_payment_instrument(Payment $payment)
+ {
+ $data = [
+ 'payment_method' => 'recurring',
+ 'payment_instrument' => [
+ 'payment_id' => 'ba3119f2-9a73-11e4-89d3-123b93f75cba',
+ ],
+ ];
+
+ $instrument = new PaymentInstrumentRecurring();
+ $instrument->setPaymentId('ba3119f2-9a73-11e4-89d3-123b93f75cba');
+
+ $payment->setPaymentMethod('recurring')->shouldBeCalled();
+ $payment->setPaymentInstrument($instrument)->shouldBeCalled();
+
+ $this->map($data, $payment);
+ }
+
+ function it_throws_exception_for_unknown_payment_method(Payment $payment)
+ {
+ $data = [
+ 'payment_method' => 'non_existing_method',
+ 'payment_instrument' => [],
+ ];
+
+ $this
+ ->shouldThrow('Cardinity\Exception\Runtime')
+ ->duringMap($data, $payment)
+ ;
+ }
+
+ function it_maps_authorization_information(Payment $payment)
+ {
+ $data = [
+ 'authorization_information' => [
+ 'url' => 'https://authorization.url/auth',
+ 'data' => 'eJxdUl1vwj.......',
+ ],
+ ];
+
+ $info = new AuthorizationInformation();
+ $info->setUrl('https://authorization.url/auth');
+ $info->setData('eJxdUl1vwj.......');
+
+ $payment->setAuthorizationInformation($info)->shouldBeCalled();
+
+ $this->map($data, $payment);
+ }
+
+ function it_maps_data_collection(ResultCollectionInterface $method, Payment $object)
+ {
+ $data = [
+ ['id' => 32, 'type' => 'my_type'],
+ ];
+
+ $method
+ ->createResultObject()
+ ->shouldBeCalled()
+ ->willReturn($object)
+ ;
+
+ $object->setId(32)->shouldBeCalled();
+ $object->setType('my_type')->shouldBeCalled();
+
+ $this->mapCollection($data, $method);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/CreateSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/CreateSpec.php
new file mode 100644
index 0000000..c549073
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/CreateSpec.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace spec\Cardinity\Method\Settlement;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class CreateSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $description = 'description';
+ private $amount = '10.00';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->amount, $this->description);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_contains_loaded_options()
+ {
+ $this->getAttributes()->shouldReturn([
+ 'amount' => $this->amount,
+ 'description' => $this->description,
+ ]);
+ }
+
+ function it_does_not_contain_optional_properties()
+ {
+ $this->beConstructedWith($this->paymentId, $this->amount);
+
+ $this->getAttributes()->shouldReturn([
+ 'amount' => $this->amount,
+ ]);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ sprintf('payments/%s/settlements', $this->paymentId)
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('POST');
+ }
+
+ function it_has_body()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Settlement\Settlement')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetAllSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetAllSpec.php
new file mode 100644
index 0000000..c04dbf0
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetAllSpec.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace spec\Cardinity\Method\Settlement;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetAllSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ 'payments/' . $this->paymentId . '/settlements'
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_has_create_result()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Settlement\Settlement')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetSpec.php
new file mode 100644
index 0000000..f87ee92
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/GetSpec.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace spec\Cardinity\Method\Settlement;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $settlementId = '25e6f869-6675-4488-bd47-ccd298f74b3f';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->settlementId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_settlement_id()
+ {
+ $this->getSettlementId()->shouldReturn($this->settlementId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ 'payments/' . $this->paymentId . '/settlements/' . $this->settlementId
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Settlement\Settlement')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/SettlementSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/SettlementSpec.php
new file mode 100644
index 0000000..d8f30df
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Settlement/SettlementSpec.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace spec\Cardinity\Method\Settlement;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class SettlementSpec extends ObjectBehavior
+{
+ function it_implements_result_object_behaviour()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+
+ function it_is_serializable()
+ {
+ $this->shouldImplement('\Serializable');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ValidatorSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ValidatorSpec.php
new file mode 100644
index 0000000..7323073
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/ValidatorSpec.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace spec\Cardinity\Method;
+
+use Cardinity\Method\MethodInterface;
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+use Symfony\Component\Validator\ConstraintViolationList;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+class ValidatorSpec extends ObjectBehavior
+{
+ function let(ValidatorInterface $validator)
+ {
+ $this->beConstructedWith($validator);
+ }
+
+ function it_implements_validator_interface()
+ {
+ $this->shouldImplement('Cardinity\Method\ValidatorInterface');
+ }
+
+ function it_validates_given_method_instance(
+ MethodInterface $method,
+ ValidatorInterface $validator
+ ) {
+ $attributes = ['field' => 'value'];
+ $constraints = ['constraints'];
+
+ $method->getAttributes()->shouldBeCalled()->willReturn($attributes);
+ $method->getValidationConstraints()->shouldBeCalled()->willReturn($constraints);
+
+ $validator->validate($attributes, $constraints)->shouldBeCalled();
+
+ $this->validate($method);
+ }
+
+ function it_throws_exception_on_validation_failure(
+ MethodInterface $method,
+ ValidatorInterface $validator,
+ ConstraintViolationList $violations
+ ) {
+ $attributes = ['field' => 'value'];
+ $constraints = ['constraints'];
+
+ $method->getValidationConstraints()->shouldBeCalled()->willReturn($constraints);
+ $method->getAttributes()->shouldBeCalled()->willReturn($attributes);
+
+ $violations->count()->willReturn(1);
+ $violations->__toString()->willReturn('');
+
+ $validator
+ ->validate($attributes, $constraints)
+ ->willReturn($violations)
+ ;
+
+ $this
+ ->shouldThrow('Cardinity\Exception\InvalidAttributeValue')
+ ->duringValidate($method)
+ ;
+ }
+
+ function it_does_not_validate_method_with_no_constraints(
+ MethodInterface $method,
+ ValidatorInterface $validator
+ ) {
+ $constraints = [];
+
+ $method->getValidationConstraints()->shouldBeCalled()->willReturn($constraints);
+
+ $validator->validate([], $constraints)->shouldNotBeCalled();
+
+ $this->validate($method);
+ }
+}
+ \ No newline at end of file
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/CreateSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/CreateSpec.php
new file mode 100644
index 0000000..915daad
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/CreateSpec.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace spec\Cardinity\Method\Void;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class CreateSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $description = 'description';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->description);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_contains_loaded_options()
+ {
+ $this->getAttributes()->shouldReturn([
+ 'description' => $this->description,
+ ]);
+ }
+
+ function it_does_not_contain_optional_properties()
+ {
+ $this->beConstructedWith($this->paymentId);
+
+ $this->getAttributes()->shouldReturn([]);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ sprintf('payments/%s/voids', $this->paymentId)
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('POST');
+ }
+
+ function it_has_body()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Void\Void')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetAllSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetAllSpec.php
new file mode 100644
index 0000000..4a6c336
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetAllSpec.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace spec\Cardinity\Method\Void;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetAllSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ 'payments/' . $this->paymentId . '/voids'
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_has_create_result()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Void\Void')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetSpec.php
new file mode 100644
index 0000000..a60ea2d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/GetSpec.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace spec\Cardinity\Method\Void;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class GetSpec extends ObjectBehavior
+{
+ private $paymentId = 'cb5e1c95-7685-4499-a2b1-ae0f28297b92';
+ private $voidId = '25e6f869-6675-4488-bd47-ccd298f74b3f';
+
+ function let()
+ {
+ $this->beConstructedWith($this->paymentId, $this->voidId);
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldImplement('Cardinity\Method\MethodInterface');
+ }
+
+ function it_has_payment_id()
+ {
+ $this->getPaymentId()->shouldReturn($this->paymentId);
+ }
+
+ function it_has_settlement_id()
+ {
+ $this->getvoidId()->shouldReturn($this->voidId);
+ }
+
+ function it_has_action()
+ {
+ $this->getAction()->shouldReturn(
+ 'payments/' . $this->paymentId . '/voids/' . $this->voidId
+ );
+ }
+
+ function it_has_method()
+ {
+ $this->getMethod()->shouldReturn('GET');
+ }
+
+ function it_has_query()
+ {
+ $this->getAttributes()->shouldBeArray();
+ }
+
+ function it_creates_result_object()
+ {
+ $this->createResultObject()
+ ->shouldReturnAnInstanceOf('Cardinity\Method\Void\Void')
+ ;
+ }
+
+ function it_has_validation_constraints()
+ {
+ $this
+ ->getValidationConstraints()
+ ->shouldReturnAnInstanceOf('Symfony\Component\Validator\Constraint')
+ ;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/VoidSpec.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/VoidSpec.php
new file mode 100644
index 0000000..e547085
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/spec/Method/Void/VoidSpec.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace spec\Cardinity\Method\Void;
+
+use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+
+class VoidSpec extends ObjectBehavior
+{
+ function it_implements_result_object_behaviour()
+ {
+ $this->shouldImplement('Cardinity\Method\ResultObjectInterface');
+ }
+
+ function it_is_serializable()
+ {
+ $this->shouldImplement('\Serializable');
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Client.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Client.php
new file mode 100644
index 0000000..03fa36a
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Client.php
@@ -0,0 +1,185 @@
+<?php
+
+namespace Cardinity;
+
+use Cardinity\Http\ClientInterface;
+use Cardinity\Http\Guzzle;
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Cardinity\Method\ResultObjectMapper;
+use Cardinity\Method\ResultObjectMapperInterface;
+use Cardinity\Method\Validator;
+use Cardinity\Method\ValidatorInterface;
+use GuzzleHttp\Subscriber\Log\Formatter;
+use GuzzleHttp\Subscriber\Log\LogSubscriber;
+use GuzzleHttp\Subscriber\Oauth\Oauth1;
+use Symfony\Component\Validator\Validation;
+
+class Client
+{
+ /**
+ * Disable logger
+ */
+ const LOG_NONE = false;
+
+ /**
+ * Turn on debug mode
+ */
+ const LOG_DEBUG = null;
+
+ /** @type ClientInterface */
+ private $client;
+
+ /** @type ValidatorInterface */
+ private $validator;
+
+ /** @type ResultObjectMapperInterface */
+ private $mapper;
+
+ /** @type string */
+ private static $url = 'https://api.cardinity.com/v1/';
+
+ /**
+ * Public factory method to create instance of Client.
+ *
+ * @param array $options Available properties: [
+ * 'consumerKey' => 'foo',
+ * 'consumerSecret' => 'bar',
+ * ]
+ * @param mixed $logger Logger used to log
+ * messages. Pass a LoggerInterface to use a PSR-3 logger. Pass a
+ * callable to log messages to a function that accepts a string of
+ * data. Pass a resource returned from ``fopen()`` to log to an open
+ * resource. Pass null or leave empty to write log messages using
+ * ``echo()``.
+ * @return self
+ */
+ public static function create(array $options = [], $logger = Client::LOG_NONE)
+ {
+ $client = new \GuzzleHttp\Client([
+ 'base_url' => self::$url,
+ 'defaults' => ['auth' => 'oauth']
+ ]);
+
+ if ($logger !== false) {
+ $subscriber = new LogSubscriber($logger, Formatter::DEBUG);
+ $client->getEmitter()->attach($subscriber);
+ }
+
+ $oauth = new Oauth1([
+ 'consumer_key' => $options['consumerKey'],
+ 'consumer_secret' => $options['consumerSecret']
+ ]);
+ $client->getEmitter()->attach($oauth);
+
+ $mapper = new ResultObjectMapper();
+
+ return new self(
+ new Guzzle\ClientAdapter($client, new Guzzle\ExceptionMapper($mapper)),
+ new Validator(Validation::createValidator()),
+ $mapper
+ );
+ }
+ /**
+ * @param ClientInterface $client
+ * @param ValidatorInterface $validator
+ * @param ResultObjectMapperInterface $mapper
+ */
+ public function __construct(
+ ClientInterface $client,
+ ValidatorInterface $validator,
+ ResultObjectMapperInterface $mapper
+ ) {
+ $this->client = $client;
+ $this->validator = $validator;
+ $this->mapper = $mapper;
+ }
+
+ /**
+ * Call the given method.
+ * @param MethodInterface $method
+ * @return ResultObjectInterface|array
+ */
+ public function call(MethodInterface $method)
+ {
+ $this->validator->validate($method);
+
+ return $this->handleRequest($method);
+ }
+
+ /**
+ * Call the particular method without data validation
+ * @param MethodInterface $method
+ * @return ResultObjectInterface|array
+ */
+ public function callNoValidate(MethodInterface $method)
+ {
+ return $this->handleRequest($method);
+ }
+
+ /**
+ * Handle all the request/response hard work
+ * @param MethodInterface $method
+ * @return ResultObjectInterface|array
+ */
+ private function handleRequest(MethodInterface $method)
+ {
+ $result = $this->client->sendRequest(
+ $method,
+ $method->getMethod(),
+ $method->getAction(),
+ $this->getOptions($method)
+ );
+
+ if ($method instanceof MethodResultCollectionInterface) {
+ return $this->mapper->mapCollection($result, $method);
+ }
+
+ return $this->mapper->map($result, $method->createResultObject());
+ }
+
+ /**
+ * Prepare request options for particular method
+ * @param MethodInterface $method
+ * @return array
+ */
+ private function getOptions(MethodInterface $method)
+ {
+ if ($method->getMethod() == $method::GET) {
+ return [
+ 'query' => $method->getAttributes(),
+ ];
+ }
+
+ return [
+ 'headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ 'body' => json_encode(
+ $this->prepareAttributes($method->getAttributes()),
+ JSON_FORCE_OBJECT
+ )
+ ];
+ }
+
+ /**
+ * Prepare request attributes
+ * @param array $data
+ * @return array
+ */
+ private function prepareAttributes(array $data)
+ {
+ foreach ($data as $key => &$value) {
+ if (is_array($value)) {
+ $data[$key] = $this->prepareAttributes($value);
+ continue;
+ }
+
+ if (is_float($value)) {
+ $value = sprintf("%01.2f", $value);
+ }
+ }
+
+ return $data;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Declined.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Declined.php
new file mode 100644
index 0000000..29a2f08
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Declined.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class Declined extends Request
+{
+ protected $code = 402;
+ protected $message = 'Request Failed – Your request was valid but it was declined.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Forbidden.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Forbidden.php
new file mode 100644
index 0000000..edf2f25
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Forbidden.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class Forbidden extends Request
+{
+ protected $code = 403;
+ protected $message = 'Forbidden – You do not have access to this resource.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InternalServerError.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InternalServerError.php
new file mode 100644
index 0000000..7148195
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InternalServerError.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class InternalServerError extends Request
+{
+ protected $code = 500;
+ protected $message = 'Internal Server Error – We had a problem on our end. Try again later.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InvalidAttributeValue.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InvalidAttributeValue.php
new file mode 100644
index 0000000..59abdf2
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/InvalidAttributeValue.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Cardinity\Exception;
+
+use Symfony\Component\Validator\ConstraintViolationListInterface;
+
+class InvalidAttributeValue extends Runtime
+{
+ /** @type ConstraintViolationListInterface */
+ private $violations;
+
+ public function __construct($message, ConstraintViolationListInterface $violations)
+ {
+ $message .= ' Violations: ' . $violations->__toString();
+ parent::__construct($message);
+
+ $this->violations = $violations;
+ }
+
+ public function getViolations()
+ {
+ return $this->violations;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/MethodNotAllowed.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/MethodNotAllowed.php
new file mode 100644
index 0000000..8a0294e
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/MethodNotAllowed.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class MethodNotAllowed extends Request
+{
+ protected $code = 405;
+ protected $message = 'Method Not Allowed – You tried to access a resource using an invalid HTTP method.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotAcceptable.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotAcceptable.php
new file mode 100644
index 0000000..123f0b5
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotAcceptable.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class NotAcceptable extends Request
+{
+ protected $code = 406;
+ protected $message = 'Not Acceptable – Wrong Accept headers sent in the request.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotFound.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotFound.php
new file mode 100644
index 0000000..5967ca6
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/NotFound.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class NotFound extends Request
+{
+ protected $code = 404;
+ protected $message = 'Not Found – The specified resource could not be found.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Request.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Request.php
new file mode 100644
index 0000000..912fea6
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Request.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Cardinity\Exception;
+
+use Cardinity\Method\ResultObjectInterface;
+
+class Request extends Runtime
+{
+ /** @type ResultObjectInterface */
+ private $result;
+
+ /**
+ * @param \Exception $previous
+ * @param ResultObjectInterface $result
+ */
+ public function __construct(\Exception $previous = null, ResultObjectInterface $result = null)
+ {
+ $this->message .= ' Response data: ' . serialize($result);
+ parent::__construct($this->message, $this->code, $previous);
+
+ $this->result = $result;
+ }
+
+ /**
+ * Get result object of particular response
+ * @return ResultObjectInterface
+ */
+ public function getResult()
+ {
+ return $this->result;
+ }
+
+ /**
+ * List of errors occured
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->result->getErrors();
+ }
+
+ /**
+ * Errors in string form
+ * @return string
+ */
+ public function getErrorsAsString()
+ {
+ $string = '';
+ foreach ($this->getErrors() as $error) {
+ $string .= sprintf(
+ "%s: %s",
+ $error['field'],
+ $error['message']
+ );
+ if (isset($error['rejected'])) {
+ $string .= sprintf(" ('%s' given)", $error['rejected']);
+ }
+ $string .= ";\n";
+ }
+
+ return trim($string);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/RequestTimeout.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/RequestTimeout.php
new file mode 100644
index 0000000..dcb34d7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/RequestTimeout.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class RequestTimeout extends Request
+{
+ protected $code = 0;
+ protected $message = '';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ResultObjectPropertyNotFound.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ResultObjectPropertyNotFound.php
new file mode 100644
index 0000000..d2bb4a6
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ResultObjectPropertyNotFound.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+use Symfony\Component\Validator\ConstraintViolationListInterface;
+
+class ResultObjectInterfacePropertyNotFound extends Runtime
+{
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Runtime.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Runtime.php
new file mode 100644
index 0000000..348d34d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Runtime.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class Runtime extends \RuntimeException
+{
+
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ServiceUnavailable.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ServiceUnavailable.php
new file mode 100644
index 0000000..8496ed3
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ServiceUnavailable.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class ServiceUnavailable extends Request
+{
+ protected $code = 503;
+ protected $message = 'Service Unavailable – We’re temporarily off-line for
+ maintenance. Please try again later.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Unauthorized.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Unauthorized.php
new file mode 100644
index 0000000..8248586
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/Unauthorized.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class Unauthorized extends Request
+{
+ protected $code = 401;
+ protected $message = 'Unauthorized – Your authorization information was missing or wrong.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedError.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedError.php
new file mode 100644
index 0000000..ff958ba
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedError.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class UnexpectedError extends Runtime
+{
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedResponse.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedResponse.php
new file mode 100644
index 0000000..9e7eb5d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/UnexpectedResponse.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class UnexpectedResponse extends Request
+{
+ protected $code = 0;
+ protected $message = '';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ValidationFailed.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ValidationFailed.php
new file mode 100644
index 0000000..cfbcda1
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Exception/ValidationFailed.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Cardinity\Exception;
+
+class ValidationFailed extends Request
+{
+ protected $code = 400;
+ protected $message = 'Bad Request – Your request contains field or business
+ logic validation errors or provided JSON is malformed.';
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/ClientInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/ClientInterface.php
new file mode 100644
index 0000000..3f457c9
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/ClientInterface.php
@@ -0,0 +1,17 @@
+<?php
+namespace Cardinity\Http;
+
+use Cardinity\Method\MethodInterface;
+
+interface ClientInterface
+{
+ /**
+ * Send HTTP request
+ * @param MethodInterface $method
+ * @param string $requestMethod POST|GET|PATCH
+ * @param string $url http URL
+ * @param array $options query options. Query params goes under 'query' key.
+ * @return array
+ */
+ public function sendRequest(MethodInterface $method, $requestMethod, $url, array $options = []);
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ClientAdapter.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ClientAdapter.php
new file mode 100644
index 0000000..f8572bf
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ClientAdapter.php
@@ -0,0 +1,60 @@
+<?php
+namespace Cardinity\Http\Guzzle;
+
+use Cardinity\Exception;
+use Cardinity\Http\ClientInterface;
+use Cardinity\Http\Guzzle\ExceptionMapper;
+use Cardinity\Method\MethodInterface;
+use GuzzleHttp;
+use GuzzleHttp\Exception\ClientException;
+
+/**
+ * Adapter for GuzzleHttp client
+ */
+class ClientAdapter implements ClientInterface
+{
+ /** @type GuzzleHttp\ClientInterface */
+ private $client;
+
+ /** @type ExceptionMapper */
+ private $mapper;
+
+ /**
+ * @param GuzzleHttp\ClientInterface $client
+ * @param ExceptionMapper $mapper
+ */
+ public function __construct(
+ GuzzleHttp\ClientInterface $client,
+ ExceptionMapper $mapper
+ ) {
+ $this->client = $client;
+ $this->mapper = $mapper;
+ }
+
+ /**
+ * Send HTTP request
+ * @param MethodInterface $method
+ * @param string $requestMethod POST|GET|PATCH
+ * @param string $url http URL
+ * @param array $options query options. Query values goes under 'body' key.
+ *
+ * @return array
+ */
+ public function sendRequest(
+ MethodInterface $method,
+ $requestMethod,
+ $url,
+ array $options = []
+ ) {
+ try {
+ $response = $this->client->send(
+ $this->client->createRequest($requestMethod, $url, $options)
+ );
+ return $response->json();
+ } catch (ClientException $e) {
+ throw $this->mapper->get($e, $method);
+ } catch (\Exception $e) {
+ throw new Exception\UnexpectedError('Unexpected error', $e->getCode(), $e);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ExceptionMapper.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ExceptionMapper.php
new file mode 100644
index 0000000..24ba1eb
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Http/Guzzle/ExceptionMapper.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Cardinity\Http\Guzzle;
+
+use Cardinity\Exception;
+use Cardinity\Method\Error;
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\ResultObjectMapperInterface;
+use GuzzleHttp\Exception\ClientException;
+
+class ExceptionMapper
+{
+ /** @type ResultObjectMapperInterface */
+ private $resultMapper;
+
+ /**
+ * @param ResultObjectMapperInterface $resultMapper
+ */
+ public function __construct(ResultObjectMapperInterface $resultMapper)
+ {
+ $this->resultMapper = $resultMapper;
+ }
+
+ /**
+ * Get mapped exception
+ * @param ClientException $exception
+ * @param MethodInterface $method
+ * @return Cardinity\Exception\Request
+ */
+ public function get(ClientException $exception, MethodInterface $method)
+ {
+ $map = $this->getMap();
+ if ($this->supports($exception, $map)) {
+ return $this->create(
+ $this->getMappedClass($exception, $map),
+ $exception,
+ $method
+ );
+ }
+
+ return $this->create(
+ 'Cardinity\\Exception\\UnexpectedResponse',
+ $exception,
+ $method
+ );
+ }
+
+ private function getMappedClass(ClientException $exception, $map)
+ {
+ return $map[$exception->getCode()];
+ }
+
+ private function supports(ClientException $exception, $map)
+ {
+ return array_key_exists($exception->getCode(), $map);
+ }
+
+ private function getMap()
+ {
+ return [
+ 400 => 'Cardinity\\Exception\\ValidationFailed',
+ 401 => 'Cardinity\\Exception\\Unauthorized',
+ 402 => 'Cardinity\\Exception\\Declined',
+ 403 => 'Cardinity\\Exception\\Forbidden',
+ 404 => 'Cardinity\\Exception\\NotFound',
+ 405 => 'Cardinity\\Exception\\MethodNotAllowed',
+ 406 => 'Cardinity\\Exception\\NotAcceptable',
+ 500 => 'Cardinity\\Exception\\InternalServerError',
+ 503 => 'Cardinity\\Exception\\ServiceUnavailable',
+ ];
+ }
+
+ private function create($class, $exception, MethodInterface $method)
+ {
+ $response = $exception->getResponse()->json();
+
+ // map declined response to result object
+ if ($exception->getCode() == 402) {
+ $resultObject = $method->createResultObject();
+ } else {
+ $resultObject = new Error();
+ }
+
+ $response = $this->resultMapper->map(
+ $response,
+ $resultObject
+ );
+
+ return new $class(
+ $exception,
+ $response
+ );
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Error.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Error.php
new file mode 100644
index 0000000..4711464
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Error.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace Cardinity\Method;
+
+class Error extends ResultObject
+{
+ /** @type string URL to error’s documentation page */
+ private $type;
+
+ /** @type string Title of an error */
+ private $title;
+
+ /** @type string HTTP response code */
+ private $status;
+
+ /** @type string Human readable information about the error */
+ private $detail;
+
+ /** @type array Optional. In case of validation errors all the fields with incorrect information are returned. */
+ private $errors = [];
+
+ /**
+ * Gets the value of type.
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Sets the value of type.
+ * @param mixed $type the type
+ * @return void
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * Gets the value of title.
+ * @return mixed
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Sets the value of title.
+ * @param mixed $title the title
+ * @return void
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * Gets the value of status.
+ * @return mixed
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * Sets the value of status.
+ * @param mixed $status the status
+ * @return void
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ }
+
+ /**
+ * Gets the value of detail.
+ * @return mixed
+ */
+ public function getDetail()
+ {
+ return $this->detail;
+ }
+
+ /**
+ * Sets the value of detail.
+ * @param mixed $detail the detail
+ * @return void
+ */
+ public function setDetail($detail)
+ {
+ $this->detail = $detail;
+ }
+
+ /**
+ * Gets the value of errors.
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * Sets the value of errors.
+ * @param array $errors the errors
+ * @return void
+ */
+ public function setErrors($errors)
+ {
+ $this->errors = $errors;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodInterface.php
new file mode 100644
index 0000000..0ca3889
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodInterface.php
@@ -0,0 +1,53 @@
+<?php
+namespace Cardinity\Method;
+
+/**
+ * Method interface for building queries for API.
+ */
+interface MethodInterface
+{
+ /**
+ * HTTP method POST
+ */
+ const POST = 'POST';
+
+ /**
+ * HTTP method PATCH
+ */
+ const PATCH = 'PATCH';
+
+ /**
+ * HTTP method GET
+ */
+ const GET = 'GET';
+
+ /**
+ * HTTP method to use
+ * @return string
+ */
+ public function getMethod();
+
+ /**
+ * API action name, part of full API request url
+ * @return string
+ */
+ public function getAction();
+
+ /**
+ * Result object for this query result
+ * @return ResultObjectInterface
+ */
+ public function createResultObject();
+
+ /**
+ * Validation constraints for fields
+ * @return \Symfony\Component\Validator\Constraints\Collection
+ */
+ public function getValidationConstraints();
+
+ /**
+ * Field and values association of object attributes
+ * @return array
+ */
+ public function getAttributes();
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodResultCollectionInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodResultCollectionInterface.php
new file mode 100644
index 0000000..d9c4337
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/MethodResultCollectionInterface.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Cardinity\Method;
+
+/**
+ * Method interface identifies method which returns collection of items.
+ */
+interface MethodResultCollectionInterface extends MethodInterface
+{
+
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/AuthorizationInformation.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/AuthorizationInformation.php
new file mode 100644
index 0000000..161095b
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/AuthorizationInformation.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\ResultObject;
+
+class AuthorizationInformation extends ResultObject
+{
+ /** @type string URL where customer should be redirected to complete
+ a payment authorization.
+ Value assigned by Cardinity. */
+ private $url;
+
+ /** @type string Data which must be passed along with the customer being
+ redirected.
+ Value assigned by Cardinity.*/
+ private $data;
+
+ /**
+ * Gets the value of url.
+ * @return mixed
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Sets the value of url.
+ * @param mixed $url the url
+ * @return void
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ }
+
+ /**
+ * Gets the value of data.
+ * @return mixed
+ */
+ public function getData()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Sets the value of data.
+ * @param mixed $data the data
+ * @return void
+ */
+ public function setData($data)
+ {
+ $this->data = $data;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Create.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Create.php
new file mode 100644
index 0000000..1e0fe90
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Create.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Create implements MethodInterface
+{
+ const CARD = 'card';
+ const RECURRING = 'recurring';
+
+ private $attributes;
+
+ public function __construct(array $attributes)
+ {
+ $this->attributes = $attributes;
+ }
+
+ public function getAction()
+ {
+ return 'payments';
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::POST;
+ }
+
+ public function getAttributes()
+ {
+ return $this->attributes;
+ }
+
+ public function createResultObject()
+ {
+ return new Payment();
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([
+ 'amount' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'float'])
+ ]),
+ 'currency' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'min' => 3,
+ 'max' => 3
+ ]),
+ ]),
+ 'settle' => new Assert\Optional([
+ new Assert\Type(['type' => 'bool'])
+ ]),
+ 'order_id' => new Assert\Optional([
+ new Assert\Type(['type' => 'string'])
+ ]),
+ 'description' => new Assert\Optional([
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'max' => 255
+ ]),
+ ]),
+ 'country' => new Assert\Required([
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'min' => 2,
+ 'max' => 2
+ ]),
+ ]),
+ 'payment_method' => new Assert\Required([
+ new Assert\Type(['type' => 'string']),
+ new Assert\Choice([
+ 'choices' => [
+ self::CARD,
+ self::RECURRING
+ ]
+ ])
+ ]),
+ 'payment_instrument' => $this->getPaymentInstrumentConstraints(
+ $this->getAttributes()['payment_method']
+ ),
+ ]);
+ }
+
+ private function getPaymentInstrumentConstraints($method)
+ {
+ switch ($method) {
+ case self::CARD:
+ return new Assert\Collection([
+ 'pan' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Luhn()
+ ]),
+ 'exp_year' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'integer']),
+ new Assert\Length([
+ 'min' => 4,
+ 'max' => 4
+ ]),
+ new Assert\Range([
+ 'min' => date('Y')
+ ]),
+ ]),
+ 'exp_month' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'integer']),
+ ]),
+ 'cvc' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'string']),
+ ]),
+ 'holder' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'max' => 32
+ ]),
+ ]),
+ ]);
+ case self::RECURRING:
+ return new Assert\Collection([
+ 'payment_id' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'string']),
+ ])
+ ]);
+ }
+
+ throw new \InvalidArgumentException(
+ sprintf(
+ 'Payment instrument for payment method "%s" is not expected',
+ $method
+ )
+ );
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Finalize.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Finalize.php
new file mode 100644
index 0000000..b9efa97
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Finalize.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Finalize implements MethodInterface
+{
+ private $paymentId;
+ private $authorizeData;
+
+ public function __construct($paymentId, $authorizeData)
+ {
+ $this->paymentId = $paymentId;
+ $this->authorizeData = $authorizeData;
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+
+ public function getAuthorizeData()
+ {
+ return $this->authorizeData;
+ }
+
+ public function getAction()
+ {
+ return sprintf('payments/%s', $this->getPaymentId());
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::PATCH;
+ }
+
+ public function createResultObject()
+ {
+ return new Payment();
+ }
+
+ public function getAttributes()
+ {
+ return [
+ 'authorize_data' => $this->getAuthorizeData()
+ ];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([
+ 'authorize_data' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'string']),
+ ])
+ ]);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Get.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Get.php
new file mode 100644
index 0000000..0170a95
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Get.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Get implements MethodInterface
+{
+ private $paymentId;
+
+ public function __construct($paymentId)
+ {
+ $this->paymentId = $paymentId;
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+
+ public function getAction()
+ {
+ return sprintf('payments/%s', $this->getPaymentId());
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Payment();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/GetAll.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/GetAll.php
new file mode 100644
index 0000000..c603bab
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/GetAll.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class GetAll implements MethodResultCollectionInterface
+{
+ private $limit;
+
+ public function __construct($limit = 10)
+ {
+ $this->limit = $limit;
+ }
+
+ public function getLimit()
+ {
+ return $this->limit;
+ }
+
+ public function getAction()
+ {
+ return 'payments';
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Payment();
+ }
+
+ public function getAttributes()
+ {
+ return [
+ 'limit' => $this->getLimit()
+ ];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([
+ 'limit' => new Assert\Optional([
+ new Assert\NotNull(),
+ new Assert\Type(['type' => 'integer']),
+ ]),
+ ]);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Payment.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Payment.php
new file mode 100644
index 0000000..90261f7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/Payment.php
@@ -0,0 +1,403 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\ResultObject;
+
+class Payment extends ResultObject
+{
+ /** @type string ID of the payment.
+ Value assigned by Cardinity. */
+ private $id;
+
+ /** @type float Amount charged shown in #0.00 format. */
+ private $amount;
+
+ /** @type string Three-letter ISO currency code representing the currency in
+ which the charge was made.
+ Supported currencies: EUR, USD. */
+ private $currency;
+
+ /** @type string Payment creation time as defined in RFC 3339 Section 5.6.
+ UTC timezone.
+ Value assigned by Cardinity. */
+ private $created;
+
+ /** @type string Payment type.
+ Can be one of the following: authorization, purchase.
+ Value assigned by Cardinity. */
+ private $type;
+
+ /** @type boolean Indicates whether a payment was made in live or testing
+ mode.
+ Value assigned by Cardinity. */
+ private $live;
+
+ /** @type boolean Optional. Default: true.
+ Used to indicate a transaction type while creating a payment: true -
+ purchase, false - authorization. */
+ private $settle;
+
+ /** @type string Payment status.
+ Can be one of the following: pending, approved, declined.
+ Value assigned by Cardinity. */
+ private $status;
+
+ /** @type string Error message.
+ Returned only if status is declined.
+ Provides human readable information why the payment failed.
+ Value assigned by Cardinity. */
+ private $error;
+
+ /** @type string Optional. Order ID provided by a merchant.
+ Must be between 2 and 50 characters [A-Za-z0-9'.-]. */
+ private $orderId;
+
+ /** @type string Payment description provided by a merchant.
+ Maximum length 255 characters. */
+ private $description;
+
+ /** @type string Country of a customer provided by a merchant.
+ ISO 3166-1 alpha-2 country code. */
+ private $country;
+
+ /** @type string Can be one the following: card, recurring. */
+ private $paymentMethod;
+
+ /** @type PaymentInstrumentInterface Payment instrument representing earlier described
+ payment_method.
+ Can be one of the following: card or recurring.
+ */
+ private $paymentInstrument;
+
+ /** @type string Used to provide additional information (PATCH verb) once
+ customer completes authorization process. */
+ private $authorizeData;
+
+ /** @type AuthorizationInformation Specific authorization object returned in case additional
+ payment authorization is needed (i.e. payment status is pending).
+ Value assigned by Cardinity. */
+ private $authorizationInformation;
+
+ /**
+ * Gets the value of id.
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Sets the value of id.
+ * @param mixed $id the id
+ * @return void
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ /**
+ * Gets the value of amount.
+ * @return mixed
+ */
+ public function getAmount()
+ {
+ return $this->amount;
+ }
+
+ /**
+ * Sets the value of amount.
+ * @param mixed $amount the amount
+ * @return void
+ */
+ public function setAmount($amount)
+ {
+ $this->amount = $amount;
+ }
+
+ /**
+ * Gets the value of currency.
+ * @return mixed
+ */
+ public function getCurrency()
+ {
+ return $this->currency;
+ }
+
+ /**
+ * Sets the value of currency.
+ * @param mixed $currency the currency
+ * @return void
+ */
+ public function setCurrency($currency)
+ {
+ $this->currency = $currency;
+ }
+
+ /**
+ * Gets the value of created.
+ * @return mixed
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Sets the value of created.
+ * @param mixed $created the created
+ * @return void
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+ }
+
+ /**
+ * Gets the value of type.
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Sets the value of type.
+ * @param mixed $type the type
+ * @return void
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * Gets the value of live.
+ * @return mixed
+ */
+ public function getLive()
+ {
+ return $this->live;
+ }
+
+ /**
+ * Sets the value of live.
+ * @param mixed $live the live
+ * @return void
+ */
+ public function setLive($live)
+ {
+ $this->live = $live;
+ }
+
+ /**
+ * Gets the value of settle.
+ * @return mixed
+ */
+ public function getSettle()
+ {
+ return $this->settle;
+ }
+
+ /**
+ * Sets the value of settle.
+ * @param mixed $settle the settle
+ * @return void
+ */
+ public function setSettle($settle)
+ {
+ $this->settle = $settle;
+ }
+
+ /**
+ * Gets the value of status.
+ * @return mixed
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * Sets the value of status.
+ * @param mixed $status the status
+ * @return void
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ }
+
+ /**
+ * Gets the value of error.
+ * @return mixed
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ /**
+ * Sets the value of error.
+ * @param mixed $error the error
+ * @return void
+ */
+ public function setError($error)
+ {
+ $this->error = $error;
+ }
+
+ /**
+ * Gets the value of orderId.
+ * @return mixed
+ */
+ public function getOrderId()
+ {
+ return $this->orderId;
+ }
+
+ /**
+ * Sets the value of orderId.
+ * @param mixed $orderId the order id
+ * @return void
+ */
+ public function setOrderId($orderId)
+ {
+ $this->orderId = $orderId;
+ }
+
+ /**
+ * Gets the value of description.
+ * @return mixed
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the value of description.
+ * @param mixed $description the description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+
+ /**
+ * Gets the value of country.
+ * @return mixed
+ */
+ public function getCountry()
+ {
+ return $this->country;
+ }
+
+ /**
+ * Sets the value of country.
+ * @param mixed $country the country
+ * @return void
+ */
+ public function setCountry($country)
+ {
+ $this->country = $country;
+ }
+
+ /**
+ * Gets the value of paymentMethod.
+ * @return mixed
+ */
+ public function getPaymentMethod()
+ {
+ return $this->paymentMethod;
+ }
+
+ /**
+ * Sets the value of paymentMethod.
+ * @param mixed $paymentMethod the payment method
+ * @return void
+ */
+ public function setPaymentMethod($paymentMethod)
+ {
+ $this->paymentMethod = $paymentMethod;
+ }
+
+ /**
+ * Gets the value of paymentInstrument.
+ * @return PaymentInstrumentInterface
+ */
+ public function getPaymentInstrument()
+ {
+ return $this->paymentInstrument;
+ }
+
+ /**
+ * Sets the value of paymentInstrument.
+ * @param PaymentInstrumentInterface $paymentInstrument the payment instrument
+ * @return void
+ */
+ public function setPaymentInstrument(PaymentInstrumentInterface $paymentInstrument)
+ {
+ $this->paymentInstrument = $paymentInstrument;
+ }
+
+ /**
+ * Gets the value of authorizeData.
+ * @return mixed
+ */
+ public function getAuthorizeData()
+ {
+ return $this->authorizeData;
+ }
+
+ /**
+ * Sets the value of authorizeData.
+ * @param mixed $authorizeData the authorize data
+ * @return void
+ */
+ public function setAuthorizeData($authorizeData)
+ {
+ $this->authorizeData = $authorizeData;
+ }
+
+ /**
+ * Gets the value of authorizationInformation.
+ * @return AuthorizationInformation
+ */
+ public function getAuthorizationInformation()
+ {
+ return $this->authorizationInformation;
+ }
+
+ /**
+ * Sets the value of authorizationInformation.
+ * @param AuthorizationInformation $authorizationInformation the authorization information
+ * @return void
+ */
+ public function setAuthorizationInformation(AuthorizationInformation $authorizationInformation)
+ {
+ $this->authorizationInformation = $authorizationInformation;
+ }
+
+ /**
+ * Check if payment is pending
+ * @return boolean
+ */
+ public function isPending()
+ {
+ return $this->getStatus() === 'pending';
+ }
+
+ /**
+ * Check if payment is approved
+ * @return boolean
+ */
+ public function isApproved()
+ {
+ return $this->getStatus() === 'approved';
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentCard.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentCard.php
new file mode 100644
index 0000000..8c25751
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentCard.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\ResultObject;
+
+class PaymentInstrumentCard extends ResultObject implements PaymentInstrumentInterface
+{
+ /** @type string Card brand.
+ Value assigned by Cardinity. */
+ private $cardBrand;
+
+ /** @type string Card number.
+ When creating a payment merchant provide full card number. However while
+ retrieving an existing payments only last 4 digits are returned. */
+ private $pan;
+
+ /** @type integer Expiration year. 4 digits, e.g. 2016. */
+ private $expYear;
+
+ /** @type integer Expiration month, e.g. 9. */
+ private $expMonth;
+
+ /** @type string Card holder’s name. Max length 32 characters. */
+ private $holder;
+
+ /**
+ * Gets the value of cardBrand.
+ * @return mixed
+ */
+ public function getCardBrand()
+ {
+ return $this->cardBrand;
+ }
+
+ /**
+ * Sets the value of cardBrand.
+ * @param mixed $cardBrand the card brand
+ * @return void
+ */
+ public function setCardBrand($cardBrand)
+ {
+ $this->cardBrand = $cardBrand;
+ }
+
+ /**
+ * Gets the value of pan.
+ * @return mixed
+ */
+ public function getPan()
+ {
+ return $this->pan;
+ }
+
+ /**
+ * Sets the value of pan.
+ * @param mixed $pan the pan
+ * @return void
+ */
+ public function setPan($pan)
+ {
+ $this->pan = $pan;
+ }
+
+ /**
+ * Gets the value of expYear.
+ * @return mixed
+ */
+ public function getExpYear()
+ {
+ return $this->expYear;
+ }
+
+ /**
+ * Sets the value of expYear.
+ * @param mixed $expYear the exp year
+ * @return void
+ */
+ public function setExpYear($expYear)
+ {
+ $this->expYear = $expYear;
+ }
+
+ /**
+ * Gets the value of expMonth.
+ * @return mixed
+ */
+ public function getExpMonth()
+ {
+ return $this->expMonth;
+ }
+
+ /**
+ * Sets the value of expMonth.
+ * @param mixed $expMonth the exp month
+ * @return void
+ */
+ public function setExpMonth($expMonth)
+ {
+ $this->expMonth = $expMonth;
+ }
+
+ /**
+ * Gets the value of holder.
+ * @return mixed
+ */
+ public function getHolder()
+ {
+ return $this->holder;
+ }
+
+ /**
+ * Sets the value of holder.
+ * @param mixed $holder the holder
+ * @return void
+ */
+ public function setHolder($holder)
+ {
+ $this->holder = $holder;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentInterface.php
new file mode 100644
index 0000000..b6ac06f
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+interface PaymentInstrumentInterface
+{
+
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentRecurring.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentRecurring.php
new file mode 100644
index 0000000..d019854
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Payment/PaymentInstrumentRecurring.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Cardinity\Method\Payment;
+
+use Cardinity\Method\ResultObject;
+
+class PaymentInstrumentRecurring extends ResultObject implements PaymentInstrumentInterface
+{
+ /** @type string Id of the approved payment in the past.
+ Same card will be used to create a new payment. */
+ private $paymentId;
+
+ /**
+ * Gets the value of paymentId.
+ * @return mixed
+ */
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+
+ /**
+ * Sets the value of paymentId.
+ * @param mixed $paymentId the payment id
+ * @return void
+ */
+ public function setPaymentId($paymentId)
+ {
+ $this->paymentId = $paymentId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Create.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Create.php
new file mode 100644
index 0000000..e5d3d42
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Create.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Cardinity\Method\Refund;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Create implements MethodInterface
+{
+ private $paymentId;
+ private $amount;
+ private $description;
+
+ public function __construct($paymentId, $amount, $description = null)
+ {
+ $this->paymentId = $paymentId;
+ $this->amount = $amount;
+ $this->description = $description;
+ }
+
+ public function getAction()
+ {
+ return sprintf('payments/%s/refunds', $this->paymentId);
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::POST;
+ }
+
+ public function getAttributes()
+ {
+ $return = [
+ 'amount' => $this->amount,
+ ];
+
+ if ($this->description !== null) {
+ $return['description'] = $this->description;
+ }
+
+ return $return;
+ }
+
+ public function createResultObject()
+ {
+ return new Refund();
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([
+ 'amount' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'float'])
+ ]),
+ 'description' => new Assert\Optional([
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'max' => 255
+ ]),
+ ]),
+ ]);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Get.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Get.php
new file mode 100644
index 0000000..adc6284
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Get.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Cardinity\Method\Refund;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Get implements MethodInterface
+{
+ private $paymentId;
+ private $refundId;
+
+ public function __construct($paymentId, $refundId)
+ {
+ $this->paymentId = $paymentId;
+ $this->refundId = $refundId;
+ }
+
+ public function getAction()
+ {
+ return sprintf(
+ 'payments/%s/refunds/%s',
+ $this->getPaymentId(),
+ $this->getRefundId()
+ );
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Refund();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+
+ public function getRefundId()
+ {
+ return $this->refundId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/GetAll.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/GetAll.php
new file mode 100644
index 0000000..2296e4d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/GetAll.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Cardinity\Method\Refund;
+
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class GetAll implements MethodResultCollectionInterface
+{
+ private $paymentId;
+
+ public function __construct($paymentId)
+ {
+ $this->paymentId = $paymentId;
+ }
+
+ public function getAction()
+ {
+ return sprintf(
+ 'payments/%s/refunds',
+ $this->getPaymentId()
+ );
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Refund();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Refund.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Refund.php
new file mode 100644
index 0000000..e3a4012
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Refund/Refund.php
@@ -0,0 +1,268 @@
+<?php
+
+namespace Cardinity\Method\Refund;
+
+use Cardinity\Method\ResultObject;
+
+class Refund extends ResultObject
+{
+ /** @type string ID of the refund.
+ Value assigned by Cardinity. */
+ private $id;
+
+ /** @type float Amount refunded shown in #0.00 format. */
+ private $amount;
+
+ /** @type string Three-letter ISO currency code representing the currency in
+ which the refund was made.
+ Supported currencies: EUR, USD.
+ Value assigned by Cardinity. */
+ private $currency;
+
+ /** @type string Can only be: refund.
+ Value assigned by Cardinity. */
+ private $type;
+
+ /** @type string Refund creation time as defined in RFC 3339 Section 5.6.
+ UTC timezone.
+ Value assigned by Cardinity. */
+ private $created;
+
+ /** @type boolean Indicates whether a refund was made in live or testing
+ mode.
+ Value assigned by Cardinity. */
+ private $live;
+
+ /** @type string ID of the refunded payment.
+ Value assigned by Cardinity. */
+ private $parentId;
+
+ /** @type string Refund status.
+ Can be one of the following: approved, declined.
+ Value assigned by Cardinity. */
+ private $status;
+
+ /** @type string Error message.
+ Returned only if status is declined.
+ Provides human readable information why the refund failed.
+ Value assigned by Cardinity. */
+ private $error;
+
+ /** @type string Optional. Order ID provided by a merchant in initial
+ payment. Must be between 2 and 50 characters [A-Za-z0-9'.-].
+ Value assigned by Cardinity. */
+ private $orderId;
+
+ /** @type string Refund description provided by a merchant.
+ Maximum length 255 characters. */
+ private $description;
+
+ /**
+ * Gets the value of id.
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Sets the value of id.
+ * @param mixed $id the id
+ * @return void
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ /**
+ * Gets the value of amount.
+ * @return mixed
+ */
+ public function getAmount()
+ {
+ return $this->amount;
+ }
+
+ /**
+ * Sets the value of amount.
+ * @param mixed $amount the amount
+ * @return void
+ */
+ public function setAmount($amount)
+ {
+ $this->amount = $amount;
+ }
+
+ /**
+ * Gets the value of currency.
+ * @return mixed
+ */
+ public function getCurrency()
+ {
+ return $this->currency;
+ }
+
+ /**
+ * Sets the value of currency.
+ * @param mixed $currency the currency
+ * @return void
+ */
+ public function setCurrency($currency)
+ {
+ $this->currency = $currency;
+ }
+
+ /**
+ * Gets the value of type.
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Sets the value of type.
+ * @param mixed $type the type
+ * @return void
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * Gets the value of created.
+ * @return mixed
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Sets the value of created.
+ * @param mixed $created the created
+ * @return void
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+ }
+
+ /**
+ * Gets the value of live.
+ * @return mixed
+ */
+ public function getLive()
+ {
+ return $this->live;
+ }
+
+ /**
+ * Sets the value of live.
+ * @param mixed $live the live
+ * @return void
+ */
+ public function setLive($live)
+ {
+ $this->live = $live;
+ }
+
+ /**
+ * Gets the value of parentId.
+ * @return mixed
+ */
+ public function getParentId()
+ {
+ return $this->parentId;
+ }
+
+ /**
+ * Sets the value of parentId.
+ * @param mixed $parentId the parent id
+ * @return void
+ */
+ public function setParentId($parentId)
+ {
+ $this->parentId = $parentId;
+ }
+
+ /**
+ * Gets the value of status.
+ * @return mixed
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * Sets the value of status.
+ * @param mixed $status the status
+ * @return void
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ }
+
+ /**
+ * Gets the value of error.
+ * @return mixed
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ /**
+ * Sets the value of error.
+ * @param mixed $error the error
+ * @return void
+ */
+ public function setError($error)
+ {
+ $this->error = $error;
+ }
+
+ /**
+ * Gets the value of orderId.
+ * @return mixed
+ */
+ public function getOrderId()
+ {
+ return $this->orderId;
+ }
+
+ /**
+ * Sets the value of orderId.
+ * @param mixed $orderId the order id
+ * @return void
+ */
+ public function setOrderId($orderId)
+ {
+ $this->orderId = $orderId;
+ }
+
+ /**
+ * Gets the value of description.
+ * @return mixed
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the value of description.
+ * @param mixed $description the description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObject.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObject.php
new file mode 100644
index 0000000..006d9e7
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObject.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace Cardinity\Method;
+
+use Cardinity\Exception;
+use Cardinity\Method\Payment\AuthorizationInformation;
+use Cardinity\Method\Payment\PaymentInstrumentCard;
+use Cardinity\Method\Payment\PaymentInstrumentRecurring;
+
+abstract class ResultObject implements ResultObjectInterface
+{
+ /**
+ * Wrap single result error into array of errors
+ * @return array
+ */
+ public function getErrors()
+ {
+ return [
+ [
+ 'field' => 'status',
+ 'message' => $this->getError()
+ ]
+ ];
+ }
+
+ /**
+ * Return single error
+ */
+ public function getError()
+ {
+ return '';
+ }
+
+ /**
+ * Serializes result object to json object
+ * @param boolean $toJson encode result to json
+ * @return string
+ */
+ public function serialize($toJson = true)
+ {
+ $data = [];
+
+ $getters = $this->classGetters(get_class($this));
+ foreach ($getters as $method) {
+ $property = $this->propertyName($method);
+ $value = $this->$method();
+
+ if (is_float($value)) {
+ $value = sprintf("%01.2f", $value);
+ } elseif (is_object($value)) {
+ $value = $value->serialize(false);
+ }
+
+ if ($value !== null) {
+ $data[$property] = $value;
+ }
+ }
+
+ if ($toJson === true) {
+ return json_encode($data);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Loads result object values from json object
+ * @param string $string json
+ * @return void
+ */
+ public function unserialize($string)
+ {
+ $data = json_decode($string);
+ foreach ($data as $property => $value) {
+ $method = $this->setterName($property);
+
+ if (is_numeric($value) && strstr($value, '.')) {
+ $value = floatval($value);
+ } elseif (is_object($value)) {
+ if ($property == 'authorization_information') {
+ $object = new AuthorizationInformation();
+ $object->unserialize(json_encode($value));
+ $value = $object;
+ } elseif ($property == 'payment_instrument') {
+ if (!isset($data->payment_method)) {
+ throw new Exception\Runtime('Property "payment_method" is missing');
+ }
+
+ if ($data->payment_method == Payment\Create::CARD) {
+ $object = new PaymentInstrumentCard();
+ } elseif ($data->payment_method == Payment\Create::RECURRING) {
+ $object = new PaymentInstrumentRecurring();
+ }
+ $object->unserialize(json_encode($value));
+ $value = $object;
+ }
+ }
+
+ $this->$method($value);
+ }
+ }
+
+ /**
+ * @param string $class
+ */
+ private function classGetters($class)
+ {
+ $methods = get_class_methods($class);
+ return array_filter($methods, function ($value) use ($methods) {
+ if ($value == 'getErrors') {
+ return false;
+ }
+
+ // no setter means it's inherited property, should be ignored
+ $setter = $this->setterName($this->propertyName($value));
+ if (!in_array($setter, $methods)) {
+ return false;
+ }
+
+ return substr($value, 0, 3) == 'get';
+ });
+ }
+
+ private function propertyName($method)
+ {
+ $method = lcfirst(substr($method, 3));
+ $method = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $method));
+ return $method;
+ }
+
+ private function setterName($property)
+ {
+ $parts = explode('_', $property);
+ $parts = array_map('ucfirst', $parts);
+ $property = implode('', $parts);
+
+ return 'set' . ucfirst($property);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectInterface.php
new file mode 100644
index 0000000..9b7890d
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectInterface.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Cardinity\Method;
+
+/**
+ * Represents value object to store response result data
+ */
+interface ResultObjectInterface extends \Serializable
+{
+ /**
+ * Return errors
+ * @return array
+ */
+ public function getErrors();
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapper.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapper.php
new file mode 100644
index 0000000..b4b1c67
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapper.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace Cardinity\Method;
+
+use Cardinity\Exception;
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Cardinity\Method\Payment\AuthorizationInformation;
+use Cardinity\Method\Payment\PaymentInstrumentCard;
+use Cardinity\Method\Payment\PaymentInstrumentRecurring;
+
+class ResultObjectMapper implements ResultObjectMapperInterface
+{
+ /**
+ * Map each item in response data to instance of ResultObjectInterface
+ * @param array $response
+ * @param MethodResultCollectionInterface $method
+ *
+ * @return array
+ */
+ public function mapCollection(array $response, MethodResultCollectionInterface $method)
+ {
+ $return = [];
+
+ foreach ($response as $item) {
+ $return[] = $this->map($item, $method->createResultObject());
+ }
+
+ return $return;
+ }
+
+ /**
+ * Map response data to instance of ResultObjectInterface
+ * @param array $response
+ * @param ResultObjectInterface $result
+ *
+ * @return ResultObjectInterface
+ */
+ public function map(array $response, ResultObjectInterface $result)
+ {
+ foreach ($response as $field => $value) {
+ $method = $this->getSetterName($field);
+
+ if (!method_exists($result, $method)) {
+ throw new Exception\ResultObjectInterfacePropertyNotFound(
+ sprintf(
+ 'Result object %s property "%s" not found.',
+ get_class($result),
+ $field
+ )
+ );
+ }
+
+ if ($field == 'payment_instrument') {
+ $value = $this->transformPaymentInstrumentValue($value, $response['payment_method']);
+ } elseif ($field == 'authorization_information') {
+ $value = $this->transformAuthorizationInformationValue($value);
+ }
+
+ $result->$method($value);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Extracts camelCased setter name from underscore notation.
+ * Eg. my_field_name => myFieldName
+ * @param string $field
+ * @return string
+ */
+ private function getSetterName($field)
+ {
+ $parts = explode('_', $field);
+ array_map('ucfirst', $parts);
+ $name = 'set' . implode('', $parts);
+
+ return $name;
+ }
+
+ /**
+ * Transform PaymentInstrument result array to object
+ * @param array $data
+ * @param string $method
+ * @return PaymentInstrumentCard|PaymentInstrumentRecurring
+ * @throws Exception\Runtime for unsupported methods
+ */
+ private function transformPaymentInstrumentValue(array $data, $method)
+ {
+ if ($method == 'card') {
+ $instrument = new PaymentInstrumentCard();
+ } elseif ($method == 'recurring') {
+ $instrument = new PaymentInstrumentRecurring();
+ } else {
+ throw new Exception\Runtime(sprintf('Method "%s" is not supported', $method));
+ }
+
+ $this->map($data, $instrument);
+
+ return $instrument;
+ }
+
+ /**
+ * Transform AuthorizationInformation result array to object
+ * @param array $data
+ * @return AuthorizationInformation
+ */
+ private function transformAuthorizationInformationValue($data)
+ {
+ $info = new AuthorizationInformation();
+ $this->map($data, $info);
+
+ return $info;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapperInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapperInterface.php
new file mode 100644
index 0000000..7cf1e64
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ResultObjectMapperInterface.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Cardinity\Method;
+
+interface ResultObjectMapperInterface
+{
+ public function map(array $response, ResultObjectInterface $result);
+ public function mapCollection(array $response, MethodResultCollectionInterface $result);
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Create.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Create.php
new file mode 100644
index 0000000..d3e069f
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Create.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Cardinity\Method\Settlement;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Create implements MethodInterface
+{
+ private $paymentId;
+ private $amount;
+ private $description;
+ public function __construct($paymentId, $amount, $description = null)
+ {
+ $this->paymentId = $paymentId;
+ $this->amount = $amount;
+ $this->description = $description;
+ }
+
+ public function getAction()
+ {
+ return sprintf('payments/%s/settlements', $this->paymentId);
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::POST;
+ }
+
+ public function getAttributes()
+ {
+ $return = [
+ 'amount' => $this->amount,
+ ];
+
+ if ($this->description !== null) {
+ $return['description'] = $this->description;
+ }
+
+ return $return;
+ }
+
+ public function createResultObject()
+ {
+ return new Settlement();
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([
+ 'amount' => new Assert\Required([
+ new Assert\NotBlank(),
+ new Assert\Type(['type' => 'float'])
+ ]),
+ 'description' => new Assert\Optional([
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'max' => 255
+ ]),
+ ]),
+ ]);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Get.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Get.php
new file mode 100644
index 0000000..b5a82b4
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Get.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Cardinity\Method\Settlement;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Get implements MethodInterface
+{
+ private $paymentId;
+ private $settlementId;
+
+ public function __construct($paymentId, $settlementId)
+ {
+ $this->paymentId = $paymentId;
+ $this->settlementId = $settlementId;
+ }
+
+ public function getAction()
+ {
+ return sprintf(
+ 'payments/%s/settlements/%s',
+ $this->getPaymentId(),
+ $this->getSettlementId()
+ );
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Settlement();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+
+ public function getSettlementId()
+ {
+ return $this->settlementId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/GetAll.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/GetAll.php
new file mode 100644
index 0000000..c893f8c
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/GetAll.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Cardinity\Method\Settlement;
+
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class GetAll implements MethodResultCollectionInterface
+{
+ private $paymentId;
+
+ public function __construct($paymentId)
+ {
+ $this->paymentId = $paymentId;
+ }
+
+ public function getAction()
+ {
+ return sprintf(
+ 'payments/%s/settlements',
+ $this->getPaymentId()
+ );
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Settlement();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Settlement.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Settlement.php
new file mode 100644
index 0000000..642871c
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Settlement/Settlement.php
@@ -0,0 +1,268 @@
+<?php
+
+namespace Cardinity\Method\Settlement;
+
+use Cardinity\Method\ResultObject;
+
+class Settlement extends ResultObject
+{
+ /** @type string ID of the settlement.
+ Value assigned by Cardinity. */
+ private $id;
+
+ /** @type float Amount settled shown in #0.00 format. */
+ private $amount;
+
+ /** @type string Three-letter ISO currency code representing the currency in
+ which the settlement was made.
+ Supported currencies: EUR, USD.
+ Value assigned by Cardinity. */
+ private $currency;
+
+ /** @type string Can only be: settlement.
+ Value assigned by Cardinity. */
+ private $type;
+
+ /** @type string Settlement creation time as defined in RFC 3339 Section 5.6.
+ UTC timezone.
+ Value assigned by Cardinity. */
+ private $created;
+
+ /** @type boolean Indicates whether a settlement was made in live or testing
+ mode.
+ Value assigned by Cardinity. */
+ private $live;
+
+ /** @type string ID of the settled payment.
+ Value assigned by Cardinity. */
+ private $parentId;
+
+ /** @type string Settlement status.
+ Can be one of the following: approved, declined.
+ Value assigned by Cardinity. */
+ private $status;
+
+ /** @type string Error message.
+ Returned only if status is declined.
+ Provides human readable information why the settlement failed.
+ Value assigned by Cardinity. */
+ private $error;
+
+ /** @type string Optional. Order ID provided by a merchant in initial
+ payment. Must be between 2 and 50 characters [A-Za-z0-9'.-].
+ Value assigned by Cardinity. */
+ private $orderId;
+
+ /** @type string Settlement description provided by a merchant.
+ Maximum length 255 characters. */
+ private $description;
+
+ /**
+ * Gets the value of id.
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Sets the value of id.
+ * @param mixed $id the id
+ * @return void
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ /**
+ * Gets the value of amount.
+ * @return mixed
+ */
+ public function getAmount()
+ {
+ return $this->amount;
+ }
+
+ /**
+ * Sets the value of amount.
+ * @param mixed $amount the amount
+ * @return void
+ */
+ public function setAmount($amount)
+ {
+ $this->amount = $amount;
+ }
+
+ /**
+ * Gets the value of currency.
+ * @return mixed
+ */
+ public function getCurrency()
+ {
+ return $this->currency;
+ }
+
+ /**
+ * Sets the value of currency.
+ * @param mixed $currency the currency
+ * @return void
+ */
+ public function setCurrency($currency)
+ {
+ $this->currency = $currency;
+ }
+
+ /**
+ * Gets the value of type.
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Sets the value of type.
+ * @param mixed $type the type
+ * @return void
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * Gets the value of created.
+ * @return mixed
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Sets the value of created.
+ * @param mixed $created the created
+ * @return void
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+ }
+
+ /**
+ * Gets the value of live.
+ * @return mixed
+ */
+ public function getLive()
+ {
+ return $this->live;
+ }
+
+ /**
+ * Sets the value of live.
+ * @param mixed $live the live
+ * @return void
+ */
+ public function setLive($live)
+ {
+ $this->live = $live;
+ }
+
+ /**
+ * Gets the value of parentId.
+ * @return mixed
+ */
+ public function getParentId()
+ {
+ return $this->parentId;
+ }
+
+ /**
+ * Sets the value of parentId.
+ * @param mixed $parentId the parent id
+ * @return void
+ */
+ public function setParentId($parentId)
+ {
+ $this->parentId = $parentId;
+ }
+
+ /**
+ * Gets the value of status.
+ * @return mixed
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * Sets the value of status.
+ * @param mixed $status the status
+ * @return void
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ }
+
+ /**
+ * Gets the value of error.
+ * @return mixed
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ /**
+ * Sets the value of error.
+ * @param mixed $error the error
+ * @return void
+ */
+ public function setError($error)
+ {
+ $this->error = $error;
+ }
+
+ /**
+ * Gets the value of orderId.
+ * @return mixed
+ */
+ public function getOrderId()
+ {
+ return $this->orderId;
+ }
+
+ /**
+ * Sets the value of orderId.
+ * @param mixed $orderId the order id
+ * @return void
+ */
+ public function setOrderId($orderId)
+ {
+ $this->orderId = $orderId;
+ }
+
+ /**
+ * Gets the value of description.
+ * @return mixed
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the value of description.
+ * @param mixed $description the description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Validator.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Validator.php
new file mode 100644
index 0000000..8537e07
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Validator.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Cardinity\Method;
+
+use Cardinity\Exception;
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface as BaseValidator;
+
+class Validator implements ValidatorInterface
+{
+ /** @type BaseValidator */
+ private $validator;
+
+ /**
+ * @param BaseValidator $validator
+ */
+ public function __construct(BaseValidator $validator)
+ {
+ $this->validator = $validator;
+ }
+
+ public function validate(MethodInterface $method)
+ {
+ $constraints = $method->getValidationConstraints();
+ if (empty($constraints)) {
+ return;
+ }
+
+ $violations = $this->validator->validate(
+ $method->getAttributes(),
+ $constraints
+ );
+
+ if (count($violations) !== 0) {
+ throw new Exception\InvalidAttributeValue(
+ 'Your method contains invalid attribute value',
+ $violations
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ValidatorInterface.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ValidatorInterface.php
new file mode 100644
index 0000000..f59e71c
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/ValidatorInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Cardinity\Method;
+
+/**
+ * Interface for method validators
+ */
+interface ValidatorInterface
+{
+ /**
+ * Validates given method values against its constraints
+ *
+ * @param MethodInterface $method
+ * @throws Cardinity\Exception\InvalidData
+ */
+ public function validate(MethodInterface $method);
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Create.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Create.php
new file mode 100644
index 0000000..2783abc
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Create.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Cardinity\Method\Void;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Create implements MethodInterface
+{
+ private $paymentId;
+ private $description;
+
+ public function __construct($paymentId, $description = null)
+ {
+ $this->paymentId = $paymentId;
+ $this->description = $description;
+ }
+
+ public function getAction()
+ {
+ return sprintf('payments/%s/voids', $this->paymentId);
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::POST;
+ }
+
+ public function getAttributes()
+ {
+ $return = [];
+
+ if ($this->description !== null) {
+ $return['description'] = $this->description;
+ }
+
+ return $return;
+ }
+
+ public function createResultObject()
+ {
+ return new Void();
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([
+ 'description' => new Assert\Optional([
+ new Assert\Type(['type' => 'string']),
+ new Assert\Length([
+ 'max' => 255
+ ]),
+ ]),
+ ]);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Get.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Get.php
new file mode 100644
index 0000000..203fefa
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Get.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Cardinity\Method\Void;
+
+use Cardinity\Method\MethodInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class Get implements MethodInterface
+{
+ private $paymentId;
+ private $voidId;
+
+ public function __construct($paymentId, $voidId)
+ {
+ $this->paymentId = $paymentId;
+ $this->voidId = $voidId;
+ }
+
+ public function getAction()
+ {
+ return sprintf(
+ 'payments/%s/voids/%s',
+ $this->getPaymentId(),
+ $this->getvoidId()
+ );
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Void();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+
+ public function getvoidId()
+ {
+ return $this->voidId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/GetAll.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/GetAll.php
new file mode 100644
index 0000000..f534e61
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/GetAll.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Cardinity\Method\Void;
+
+use Cardinity\Method\MethodInterface;
+use Cardinity\Method\MethodResultCollectionInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+class GetAll implements MethodResultCollectionInterface
+{
+ private $paymentId;
+
+ public function __construct($paymentId)
+ {
+ $this->paymentId = $paymentId;
+ }
+
+ public function getAction()
+ {
+ return sprintf(
+ 'payments/%s/voids',
+ $this->getPaymentId()
+ );
+ }
+
+ public function getMethod()
+ {
+ return MethodInterface::GET;
+ }
+
+ public function createResultObject()
+ {
+ return new Void();
+ }
+
+ public function getAttributes()
+ {
+ return [];
+ }
+
+ public function getValidationConstraints()
+ {
+ return new Assert\Collection([]);
+ }
+
+ public function getPaymentId()
+ {
+ return $this->paymentId;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Void.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Void.php
new file mode 100644
index 0000000..fb001e3
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/src/Method/Void/Void.php
@@ -0,0 +1,221 @@
+<?php
+
+namespace Cardinity\Method\Void;
+
+use Cardinity\Method\ResultObject;
+
+class Void extends ResultObject
+{
+ /** @type string ID of the vpod.
+ Value assigned by Cardinity. */
+ private $id;
+
+ /** @type string Can only be: void.
+ Value assigned by Cardinity. */
+ private $type;
+
+ /** @type string Void creation time as defined in RFC 3339 Section 5.6.
+ UTC timezone.
+ Value assignedsp by Cardinity. */
+ private $created;
+
+ /** @type boolean Indicates whether a void was made in live or testing
+ mode.
+ Value assigned by Cardinity. */
+ private $live;
+
+ /** @type string ID of the voided payment.
+ Value assigned by Cardinity. */
+ private $parentId;
+
+ /** @type string Void status.
+ Can be one of the following: approved, declined.
+ Value assigned by Cardinity. */
+ private $status;
+
+ /** @type string Error message.
+ Returned only if status is declined.
+ Provides human readable information why a void failed.
+ Value assigned by Cardinity. */
+ private $error;
+
+ /** @type string Optional. Order ID provided by a merchant in initial
+ payment. Must be between 2 and 50 characters [A-Za-z0-9'.-].
+ Value assigned by Cardinity. */
+ private $orderId;
+
+ /** @type string Void description provided by a merchant.
+ Maximum length 255 characters. */
+ private $description;
+
+ /**
+ * Gets the value of id.
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Sets the value of id.
+ * @param mixed $id the id
+ * @return void
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ /**
+ * Gets the value of type.
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Sets the value of type.
+ * @param mixed $type the type
+ * @return void
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * Gets the value of created.
+ * @return mixed
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Sets the value of created.
+ * @param mixed $created the created
+ * @return void
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+ }
+
+ /**
+ * Gets the value of live.
+ * @return mixed
+ */
+ public function getLive()
+ {
+ return $this->live;
+ }
+
+ /**
+ * Sets the value of live.
+ * @param mixed $live the live
+ * @return void
+ */
+ public function setLive($live)
+ {
+ $this->live = $live;
+ }
+
+ /**
+ * Gets the value of parentId.
+ * @return mixed
+ */
+ public function getParentId()
+ {
+ return $this->parentId;
+ }
+
+ /**
+ * Sets the value of parentId.
+ * @param mixed $parentId the parent id
+ * @return void
+ */
+ public function setParentId($parentId)
+ {
+ $this->parentId = $parentId;
+ }
+
+ /**
+ * Gets the value of status.
+ * @return mixed
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * Sets the value of status.
+ * @param mixed $status the status
+ * @return void
+ */
+ public function setStatus($status)
+ {
+ $this->status = $status;
+ }
+
+ /**
+ * Gets the value of error.
+ * @return mixed
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ /**
+ * Sets the value of error.
+ * @param mixed $error the error
+ * @return void
+ */
+ public function setError($error)
+ {
+ $this->error = $error;
+ }
+
+ /**
+ * Gets the value of orderId.
+ * @return mixed
+ */
+ public function getOrderId()
+ {
+ return $this->orderId;
+ }
+
+ /**
+ * Sets the value of orderId.
+ * @param mixed $orderId the order id
+ * @return void
+ */
+ public function setOrderId($orderId)
+ {
+ $this->orderId = $orderId;
+ }
+
+ /**
+ * Gets the value of description.
+ * @return mixed
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the value of description.
+ * @param mixed $description the description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ClientTestCase.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ClientTestCase.php
new file mode 100644
index 0000000..6091965
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ClientTestCase.php
@@ -0,0 +1,56 @@
+<?php
+namespace Cardinity\Tests;
+
+use Cardinity\Client;
+
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+use Cardinity\Method\Payment;
+
+class ClientTestCase extends \PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $log = Client::LOG_NONE;
+
+ // @NOTE uncomment if request/response debugging is needed
+ // Use 'null' value for printing request to console
+ // $log = Client::LOG_DEBUG;
+
+ // Use monolog logger to log requests into the file
+ // $log = new Logger('requests');
+ // $log->pushHandler(new StreamHandler(__DIR__ . '/info.log', Logger::INFO));
+
+ $this->client = Client::create($this->getConfig(), $log);
+
+ $this->assertInstanceOf('Cardinity\Client', $this->client);
+ }
+
+ protected function getConfig()
+ {
+ return [
+ 'consumerKey' => CONSUMER_KEY,
+ 'consumerSecret' => CONSUMER_SECRET,
+ ];
+ }
+
+ protected function getPaymentParams()
+ {
+ return [
+ 'amount' => 50.00,
+ 'currency' => 'EUR',
+ 'settle' => false,
+ 'description' => 'some description',
+ 'order_id' => '12345678',
+ 'country' => 'LT',
+ 'payment_method' => Payment\Create::CARD,
+ 'payment_instrument' => [
+ 'pan' => '4111111111111111',
+ 'exp_year' => 2016,
+ 'exp_month' => 12,
+ 'cvc' => '456',
+ 'holder' => 'Mike Dough'
+ ],
+ ];
+ }
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ErrorTest.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ErrorTest.php
new file mode 100644
index 0000000..b1a3d77
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/ErrorTest.php
@@ -0,0 +1,98 @@
+<?php
+namespace Cardinity\Tests;
+
+use Cardinity\Client;
+use Cardinity\Method\Payment;
+
+class ErrorTest extends ClientTestCase
+{
+ public function testErrorResultObjectForErrorResponse()
+ {
+ $method = $this
+ ->getMockBuilder('Cardinity\Method\Payment\Get')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $method->method('getAction')->willReturn('payments');
+ $method->method('getAttributes')->willReturn([]);
+ $method->method('getMethod')->willReturn(Payment\Get::POST);
+
+ try {
+ $this->client->call($method);
+ } catch (\Cardinity\Exception\ValidationFailed $e) {
+ $result = $e->getResult();
+ $this->assertInstanceOf('Cardinity\Method\Error', $result);
+ $this->assertSame('https://developers.cardinity.com/api/v1/#400', $result->getType());
+ $this->assertSame('Validation Failed', $result->getTitle());
+ $this->assertContains('validation errors', $result->getDetail());
+ $this->assertTrue(is_array($result->getErrors()));
+ $this->assertNotEmpty($result->getErrors());
+ }
+ }
+
+ /**
+ * @expectedException Cardinity\Exception\Unauthorized
+ */
+ public function testUnauthorizedResponse()
+ {
+ $client = Client::create([
+ 'consumerKey' => 'no',
+ 'consumerSecret' => 'yes',
+ ]);
+
+ $method = new Payment\Get('xxxyyy');
+
+ $client->call($method);
+ }
+
+ /**
+ * @expectedException Cardinity\Exception\ValidationFailed
+ */
+ public function testBadRequest()
+ {
+ $method = $this
+ ->getMockBuilder('Cardinity\Method\Payment\Get')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $method->method('getAction')->willReturn('payments');
+ $method->method('getAttributes')->willReturn([]);
+ $method->method('getMethod')->willReturn(Payment\Get::POST);
+
+ $this->client->call($method);
+ }
+
+ /**
+ * @expectedException Cardinity\Exception\NotFound
+ */
+ public function testNotFound()
+ {
+ $method = $this
+ ->getMockBuilder('Cardinity\Method\Payment\Get')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $method->method('getAction')->willReturn('my_dreamy_action');
+ $method->method('getAttributes')->willReturn([]);
+ $method->method('getMethod')->willReturn(Payment\Get::POST);
+
+ $this->client->call($method);
+ }
+
+ /**
+ * @expectedException Cardinity\Exception\MethodNotAllowed
+ */
+ public function testMethodNotAllowed()
+ {
+ $method = $this
+ ->getMockBuilder('Cardinity\Method\Payment\Get')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $method->method('getAction')->willReturn('payments');
+ $method->method('getAttributes')->willReturn([]);
+ $method->method('getMethod')->willReturn('DELETE');
+
+ $this->client->call($method);
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/PaymentTest.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/PaymentTest.php
new file mode 100644
index 0000000..d97318f
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/PaymentTest.php
@@ -0,0 +1,267 @@
+<?php
+namespace Cardinity\Tests;
+
+use Cardinity\Exception;
+use Cardinity\Method\Payment;
+
+class PaymentTest extends ClientTestCase
+{
+ public function testResultObjectSerialization()
+ {
+ $payment = new Payment\Payment();
+ $payment->setId('foo');
+ $payment->setType('bar');
+ $payment->setCurrency(null);
+ $payment->setAmount('55.00');
+ $payment->setPaymentMethod(Payment\Create::CARD);
+
+ $card = new Payment\PaymentInstrumentCard();
+ $card->setCardBrand('Visa');
+ $card->setPan('4447');
+ $card->setExpYear(2017);
+ $card->setExpMonth(5);
+ $card->setHolder('John Smith');
+ $payment->setPaymentInstrument($card);
+
+ $info = new Payment\AuthorizationInformation();
+ $info->setUrl('http://...');
+ $info->setData('some_data');
+ $payment->setAuthorizationInformation($info);
+
+ $this->assertSame(
+ '{"id":"foo","amount":"55.00","type":"bar","payment_method":"card","payment_instrument":{"card_brand":"Visa","pan":"4447","exp_year":2017,"exp_month":5,"holder":"John Smith"},"authorization_information":{"url":"http:\/\/...","data":"some_data"}}',
+ $payment->serialize()
+ );
+ }
+
+ public function testResultObjectUnserialization()
+ {
+ $json = '{"id":"foo","amount":"55.00","type":"bar","payment_method":"card","payment_instrument":{"card_brand":"Visa","pan":"4447","exp_year":2017,"exp_month":5,"holder":"John Smith"},"authorization_information":{"url":"http:\/\/...","data":"some_data"}}';
+
+ $payment = new Payment\Payment();
+ $payment->unserialize($json);
+
+ $this->assertSame('foo', $payment->getId());
+ $this->assertSame('bar', $payment->getType());
+ $this->assertSame(null, $payment->getCurrency());
+ $this->assertSame(55.00, $payment->getAmount());
+ $this->assertInstanceOf('Cardinity\Method\Payment\AuthorizationInformation', $payment->getAuthorizationInformation());
+ $this->assertSame('http://...', $payment->getAuthorizationInformation()->getUrl());
+ $this->assertInstanceOf('Cardinity\Method\Payment\PaymentInstrumentCard', $payment->getPaymentInstrument());
+ $this->assertSame('John Smith', $payment->getPaymentInstrument()->getHolder());
+ }
+
+ /**
+ * @expectedException Cardinity\Exception\InvalidAttributeValue
+ * @dataProvider invalidaAmountValuesData
+ */
+ public function testAmountValidationConstraint($amount)
+ {
+ $params = $this->getPaymentParams();
+ $params['amount'] = $amount;
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+ }
+
+ public function invalidaAmountValuesData()
+ {
+ return [
+ ['150.01'],
+ [150],
+ ];
+ }
+
+ /**
+ * @expectedException Cardinity\Exception\InvalidAttributeValue
+ */
+ public function testMissingRequiredAttribute()
+ {
+ $params = $this->getPaymentParams();
+ unset($params['currency']);
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+ }
+
+ /**
+ * In order to simulate a failed payment:
+ * status declined: Amount larger than 150.00 will trigger a declined payment.
+ */
+ public function testCreateDeclined()
+ {
+ $params = $this->getPaymentParams();
+ $params['amount'] = 150.01;
+
+ try {
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+ } catch (Exception\Declined $e) {
+ $result = $e->getResult();
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('declined', $result->getStatus());
+ $this->assertSame('CRD-TEST: Do Not Honor', $result->getError());
+ $this->assertContains('status: CRD-TEST: Do Not Honor;', $e->getErrorsAsString());
+
+ return;
+ }
+
+ $this->fail('An expected exception has not been raised.');
+ }
+
+ /**
+ * Invalid data. Check error message.
+ */
+ public function testCreateFailPanValidation()
+ {
+ $params = $this->getPaymentParams();
+ $params['payment_instrument']['pan'] = '4242424242424241';
+
+ try {
+ $method = new Payment\Create($params);
+ $result = $this->client->callNoValidate($method);
+ } catch (Exception\ValidationFailed $e) {
+ $result = $e->getResult();
+
+ $this->assertInstanceOf('Cardinity\Method\Error', $result);
+ $this->assertSame('invalid credit card number.', $e->getErrors()[0]['message']);
+ return;
+ }
+
+ $this->fail('An expected exception has not been raised.');
+ }
+
+ /**
+ * Invalid data. Generic handling.
+ * @expectedException Cardinity\Exception\ValidationFailed
+ */
+ public function testCreateFailMonthValidation()
+ {
+ $params = $this->getPaymentParams();
+ $params['payment_instrument']['exp_month'] = 13;
+
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+ }
+
+ public function testCreate()
+ {
+ $params = $this->getPaymentParams();
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('approved', $result->getStatus());
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testCreateRecurring(Payment\Payment $payment)
+ {
+ $params = $this->getPaymentParams();
+ $params['payment_method'] = Payment\Create::RECURRING;
+ $params['payment_instrument'] = [
+ 'payment_id' => $payment->getId()
+ ];
+
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('approved', $result->getStatus());
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGet(Payment\Payment $payment)
+ {
+ $method = new Payment\Get($payment->getId());
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('approved', $result->getStatus());
+ }
+
+ public function testGetAll()
+ {
+ $method = new Payment\GetAll(5);
+ $result = $this->client->call($method);
+
+ $this->assertCount(5, $result);
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result[0]);
+ }
+
+ public function testCreate3dFail()
+ {
+ $params = $this->getPaymentParams();
+ $params['description'] = '3d-fail';
+
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('pending', $result->getStatus());
+ $this->assertSame('3d-fail', $result->getAuthorizationInformation()->getData());
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate3dFail
+ */
+ public function testFinalizePaymentFail(Payment\Payment $payment)
+ {
+ $paymentId = $payment->getId();
+ $authorizationInformation = $payment->getAuthorizationInformation()->getData();
+
+ try {
+ $method = new Payment\Finalize($paymentId, $authorizationInformation);
+ $result = $this->client->call($method);
+ } catch (Exception\Declined $e) {
+ $result = $e->getResult();
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('declined', $result->getStatus());
+ $this->assertContains('status: 33333: 3D Secure Authorization Failed.;', $e->getErrorsAsString());
+
+ return;
+ }
+
+ $this->fail('An expected exception has not been raised.');
+ }
+
+ public function testCreate3dPass()
+ {
+ $params = $this->getPaymentParams();
+ $params['description'] = '3d-pass';
+
+ $method = new Payment\Create($params);
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('pending', $result->getStatus());
+ $this->assertSame('3d-pass', $result->getAuthorizationInformation()->getData());
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate3dPass
+ */
+ public function testFinalizePaymentPass(Payment\Payment $payment)
+ {
+ $paymentId = $payment->getId();
+ $authorizationInformation = $payment->getAuthorizationInformation()->getData();
+
+ $method = new Payment\Finalize($paymentId, $authorizationInformation);
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Payment\Payment', $result);
+ $this->assertSame('approved', $result->getStatus());
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/RefundTest.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/RefundTest.php
new file mode 100644
index 0000000..1014ace
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/RefundTest.php
@@ -0,0 +1,115 @@
+<?php
+namespace Cardinity\Tests;
+
+use Cardinity\Method\Refund;
+use Cardinity\Method\Payment;
+
+class RefundTest extends ClientTestCase
+{
+ public function testResultObjectSerialization()
+ {
+ $refund = new Refund\Refund();
+ $refund->setId('foo');
+ $refund->setType('bar');
+ $refund->setCurrency(null);
+ $refund->setAmount('55.00');
+
+ $this->assertSame(
+ '{"id":"foo","amount":"55.00","type":"bar"}',
+ $refund->serialize()
+ );
+ }
+
+ public function testResultObjectUnserialization()
+ {
+ $json = '{"id":"foo","amount":"55.00","type":"bar"}';
+
+ $payment = new Refund\Refund();
+ $payment->unserialize($json);
+
+ $this->assertSame('foo', $payment->getId());
+ $this->assertSame('bar', $payment->getType());
+ $this->assertSame(null, $payment->getCurrency());
+ $this->assertSame(55.00, $payment->getAmount());
+ }
+
+ /**
+ * @return Payment\Payment
+ */
+ public function testCreatePayment()
+ {
+ $params = $this->getPaymentParams();
+ $params['settle'] = true;
+
+ $method = new Payment\Create($params);
+ $payment = $this->client->call($method);
+
+ return $payment;
+ }
+
+ /**
+ * @depends testCreatePayment
+ * @expectedException Cardinity\Exception\Declined
+ */
+ public function testCreateFail(Payment\Payment $payment)
+ {
+ $method = new Refund\Create(
+ $payment->getId(),
+ 10.00,
+ 'fail'
+ );
+ $this->client->call($method);
+ }
+
+ /**
+ * @depends testCreatePayment
+ * @return Refund\Refund
+ */
+ public function testCreate(Payment\Payment $payment)
+ {
+ $method = new Refund\Create(
+ $payment->getId(),
+ 10.00,
+ 'my description'
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Refund\Refund', $result);
+ $this->assertSame('10.00', $result->getAmount());
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGet(Refund\Refund $refund)
+ {
+ $method = new Refund\Get(
+ $refund->getParentId(),
+ $refund->getId()
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Refund\Refund', $result);
+ $this->assertSame($refund->getParentId(), $result->getParentId());
+ $this->assertSame('refund', $result->getType());
+ $this->assertSame('10.00', $result->getAmount());
+ $this->assertSame('my description', $result->getDescription());
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGetAll(Refund\Refund $refund)
+ {
+ $method = new Refund\GetAll(
+ $refund->getParentId()
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Refund\Refund', $result[0]);
+ $this->assertSame($refund->getId(), $result[0]->getId());
+ $this->assertSame($refund->getParentId(), $result[0]->getParentId());
+ }
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/SettlementTest.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/SettlementTest.php
new file mode 100644
index 0000000..cc6b08e
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/SettlementTest.php
@@ -0,0 +1,111 @@
+<?php
+namespace Cardinity\Tests;
+
+use Cardinity\Method\Settlement;
+use Cardinity\Method\Payment;
+
+class SettlementTest extends ClientTestCase
+{
+ public function testResultObjectSerialization()
+ {
+ $refund = new Settlement\Settlement();
+ $refund->setId('foo');
+ $refund->setType('bar');
+ $refund->setCurrency(null);
+ $refund->setAmount('55.00');
+
+ $this->assertSame(
+ '{"id":"foo","amount":"55.00","type":"bar"}',
+ $refund->serialize()
+ );
+ }
+
+ public function testResultObjectUnserialization()
+ {
+ $json = '{"id":"foo","amount":"55.00","type":"bar"}';
+
+ $payment = new Settlement\Settlement();
+ $payment->unserialize($json);
+
+ $this->assertSame('foo', $payment->getId());
+ $this->assertSame('bar', $payment->getType());
+ $this->assertSame(null, $payment->getCurrency());
+ $this->assertSame(55.00, $payment->getAmount());
+ }
+
+ /**
+ * @return Payment\Payment
+ */
+ public function testCreatePayment()
+ {
+ $method = new Payment\Create($this->getPaymentParams());
+ $payment = $this->client->call($method);
+
+ return $payment;
+ }
+
+ /**
+ * @depends testCreatePayment
+ * @expectedException Cardinity\Exception\Declined
+ */
+ public function testCreateFail(Payment\Payment $payment)
+ {
+ $method = new Settlement\Create(
+ $payment->getId(),
+ 10.00,
+ 'fail'
+ );
+ $this->client->call($method);
+ }
+
+ /**
+ * @depends testCreatePayment
+ */
+ public function testCreate(Payment\Payment $payment)
+ {
+ $method = new Settlement\Create(
+ $payment->getId(),
+ 10.00,
+ 'my description'
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Settlement\Settlement', $result);
+ $this->assertSame('10.00', $result->getAmount());
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGet(Settlement\Settlement $settlement)
+ {
+ $method = new Settlement\Get(
+ $settlement->getParentId(),
+ $settlement->getId()
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Settlement\Settlement', $result);
+ $this->assertSame($settlement->getParentId(), $result->getParentId());
+ $this->assertSame('10.00', $result->getAmount());
+ $this->assertSame('settlement', $result->getType());
+ $this->assertSame('my description', $result->getDescription());
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGetAll(Settlement\Settlement $settlement)
+ {
+ $method = new Settlement\GetAll(
+ $settlement->getParentId()
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Settlement\Settlement', $result[0]);
+ $this->assertSame($settlement->getId(), $result[0]->getId());
+ $this->assertSame($settlement->getParentId(), $result[0]->getParentId());
+ }
+}
diff --git a/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/VoidTest.php b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/VoidTest.php
new file mode 100644
index 0000000..1c468d9
--- /dev/null
+++ b/public/system/storage/vendor/cardinity/cardinity-sdk-php/tests/VoidTest.php
@@ -0,0 +1,105 @@
+<?php
+namespace Cardinity\Tests;
+
+use Cardinity\Method\Void;
+use Cardinity\Method\Payment;
+
+class VoidTest extends ClientTestCase
+{
+ public function testResultObjectSerialization()
+ {
+ $refund = new Void\Void();
+ $refund->setId('foo');
+ $refund->setType('bar');
+ $refund->setCreated(null);
+
+ $this->assertSame(
+ '{"id":"foo","type":"bar"}',
+ $refund->serialize()
+ );
+ }
+
+ public function testResultObjectUnserialization()
+ {
+ $json = '{"id":"foo","type":"bar"}';
+
+ $payment = new Void\Void();
+ $payment->unserialize($json);
+
+ $this->assertSame('foo', $payment->getId());
+ $this->assertSame('bar', $payment->getType());
+ $this->assertSame(null, $payment->getDescription());
+ }
+
+ /**
+ * @return Payment\Payment
+ */
+ public function testCreatePayment()
+ {
+ $method = new Payment\Create($this->getPaymentParams());
+ $payment = $this->client->call($method);
+
+ return $payment;
+ }
+
+ /**
+ * @depends testCreatePayment
+ * @expectedException Cardinity\Exception\Declined
+ */
+ public function testCreateFail(Payment\Payment $payment)
+ {
+ $method = new Void\Create(
+ $payment->getId(),
+ 'fail'
+ );
+ $this->client->call($method);
+ }
+
+ /**
+ * @depends testCreatePayment
+ */
+ public function testCreate(Payment\Payment $payment)
+ {
+ $method = new Void\Create(
+ $payment->getId(),
+ 'my description'
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Void\Void', $result);
+
+ return $result;
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGet(Void\Void $void)
+ {
+ $method = new Void\Get(
+ $void->getParentId(),
+ $void->getId()
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Void\Void', $result);
+ $this->assertSame($void->getParentId(), $result->getParentId());
+ $this->assertSame('void', $result->getType());
+ $this->assertSame('my description', $result->getDescription());
+ }
+
+ /**
+ * @depends testCreate
+ */
+ public function testGetAll(Void\Void $void)
+ {
+ $method = new Void\GetAll(
+ $void->getParentId()
+ );
+ $result = $this->client->call($method);
+
+ $this->assertInstanceOf('Cardinity\Method\Void\Void', $result[0]);
+ $this->assertSame($void->getId(), $result[0]->getId());
+ $this->assertSame($void->getParentId(), $result[0]->getParentId());
+ }
+}
diff --git a/public/system/storage/vendor/composer/ClassLoader.php b/public/system/storage/vendor/composer/ClassLoader.php
new file mode 100644
index 0000000..fce8549
--- /dev/null
+++ b/public/system/storage/vendor/composer/ClassLoader.php
@@ -0,0 +1,445 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ // PSR-4
+ private $prefixLengthsPsr4 = array();
+ private $prefixDirsPsr4 = array();
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ private $prefixesPsr0 = array();
+ private $fallbackDirsPsr0 = array();
+
+ private $useIncludePath = false;
+ private $classMap = array();
+ private $classMapAuthoritative = false;
+ private $missingClasses = array();
+ private $apcuPrefix;
+
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
+ }
+
+ return array();
+ }
+
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ (array) $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath . '\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ if (file_exists($file = $dir . $pathEnd)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+ include $file;
+}
diff --git a/public/system/storage/vendor/composer/LICENSE b/public/system/storage/vendor/composer/LICENSE
new file mode 100644
index 0000000..f27399a
--- /dev/null
+++ b/public/system/storage/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/public/system/storage/vendor/composer/autoload_classmap.php b/public/system/storage/vendor/composer/autoload_classmap.php
new file mode 100644
index 0000000..0d884ae
--- /dev/null
+++ b/public/system/storage/vendor/composer/autoload_classmap.php
@@ -0,0 +1,15 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname(dirname(dirname($vendorDir))));
+
+return array(
+ 'scss_formatter' => $vendorDir . '/leafo/scssphp/scss.inc.php',
+ 'scss_formatter_compressed' => $vendorDir . '/leafo/scssphp/scss.inc.php',
+ 'scss_formatter_nested' => $vendorDir . '/leafo/scssphp/scss.inc.php',
+ 'scss_parser' => $vendorDir . '/leafo/scssphp/scss.inc.php',
+ 'scss_server' => $vendorDir . '/leafo/scssphp/scss.inc.php',
+ 'scssc' => $vendorDir . '/leafo/scssphp/scss.inc.php',
+);
diff --git a/public/system/storage/vendor/composer/autoload_files.php b/public/system/storage/vendor/composer/autoload_files.php
new file mode 100644
index 0000000..e4a930d
--- /dev/null
+++ b/public/system/storage/vendor/composer/autoload_files.php
@@ -0,0 +1,12 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname(dirname(dirname($vendorDir))));
+
+return array(
+ 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+ '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
+);
diff --git a/public/system/storage/vendor/composer/autoload_namespaces.php b/public/system/storage/vendor/composer/autoload_namespaces.php
new file mode 100644
index 0000000..1587c87
--- /dev/null
+++ b/public/system/storage/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,11 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname(dirname(dirname($vendorDir))));
+
+return array(
+ 'Divido' => array($vendorDir . '/divido/divido-php/lib'),
+ 'Braintree' => array($vendorDir . '/braintree/braintree_php/lib'),
+);
diff --git a/public/system/storage/vendor/composer/autoload_psr4.php b/public/system/storage/vendor/composer/autoload_psr4.php
new file mode 100644
index 0000000..f072e63
--- /dev/null
+++ b/public/system/storage/vendor/composer/autoload_psr4.php
@@ -0,0 +1,23 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname(dirname(dirname(dirname($vendorDir))));
+
+return array(
+ 'Wechat\\' => array($vendorDir . '/zoujingli/wechat-php-sdk/Wechat'),
+ 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
+ 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
+ 'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'),
+ 'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
+ 'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+ 'GuzzleHttp\\Subscriber\\Oauth\\' => array($vendorDir . '/guzzlehttp/oauth-subscriber/src'),
+ 'GuzzleHttp\\Subscriber\\Log\\' => array($vendorDir . '/guzzlehttp/log-subscriber/src'),
+ 'GuzzleHttp\\Stream\\' => array($vendorDir . '/guzzlehttp/streams/src'),
+ 'GuzzleHttp\\Ring\\' => array($vendorDir . '/guzzlehttp/ringphp/src'),
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
+ 'Cardinity\\' => array($vendorDir . '/cardinity/cardinity-sdk-php/src'),
+ '' => array($vendorDir . '/klarna/kco_rest/src'),
+);
diff --git a/public/system/storage/vendor/composer/autoload_real.php b/public/system/storage/vendor/composer/autoload_real.php
new file mode 100644
index 0000000..8410aa5
--- /dev/null
+++ b/public/system/storage/vendor/composer/autoload_real.php
@@ -0,0 +1,70 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit4356ab4fdc794d105db4fa48b241456c
+{
+ private static $loader;
+
+ public static function loadClassLoader($class)
+ {
+ if ('Composer\Autoload\ClassLoader' === $class) {
+ require __DIR__ . '/ClassLoader.php';
+ }
+ }
+
+ public static function getLoader()
+ {
+ if (null !== self::$loader) {
+ return self::$loader;
+ }
+
+ spl_autoload_register(array('ComposerAutoloaderInit4356ab4fdc794d105db4fa48b241456c', 'loadClassLoader'), true, true);
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+ spl_autoload_unregister(array('ComposerAutoloaderInit4356ab4fdc794d105db4fa48b241456c', 'loadClassLoader'));
+
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+ if ($useStaticLoader) {
+ require_once __DIR__ . '/autoload_static.php';
+
+ call_user_func(\Composer\Autoload\ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::getInitializer($loader));
+ } else {
+ $map = require __DIR__ . '/autoload_namespaces.php';
+ foreach ($map as $namespace => $path) {
+ $loader->set($namespace, $path);
+ }
+
+ $map = require __DIR__ . '/autoload_psr4.php';
+ foreach ($map as $namespace => $path) {
+ $loader->setPsr4($namespace, $path);
+ }
+
+ $classMap = require __DIR__ . '/autoload_classmap.php';
+ if ($classMap) {
+ $loader->addClassMap($classMap);
+ }
+ }
+
+ $loader->register(true);
+
+ if ($useStaticLoader) {
+ $includeFiles = Composer\Autoload\ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::$files;
+ } else {
+ $includeFiles = require __DIR__ . '/autoload_files.php';
+ }
+ foreach ($includeFiles as $fileIdentifier => $file) {
+ composerRequire4356ab4fdc794d105db4fa48b241456c($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
+
+function composerRequire4356ab4fdc794d105db4fa48b241456c($fileIdentifier, $file)
+{
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ require $file;
+
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+ }
+}
diff --git a/public/system/storage/vendor/composer/autoload_static.php b/public/system/storage/vendor/composer/autoload_static.php
new file mode 100644
index 0000000..598ec7f
--- /dev/null
+++ b/public/system/storage/vendor/composer/autoload_static.php
@@ -0,0 +1,145 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInit4356ab4fdc794d105db4fa48b241456c
+{
+ public static $files = array (
+ 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+ '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'W' =>
+ array (
+ 'Wechat\\' => 7,
+ ),
+ 'S' =>
+ array (
+ 'Symfony\\Polyfill\\Mbstring\\' => 26,
+ 'Symfony\\Polyfill\\Ctype\\' => 23,
+ 'Symfony\\Component\\Validator\\' => 28,
+ 'Symfony\\Component\\Translation\\' => 30,
+ ),
+ 'R' =>
+ array (
+ 'React\\Promise\\' => 14,
+ ),
+ 'P' =>
+ array (
+ 'Psr\\Log\\' => 8,
+ ),
+ 'G' =>
+ array (
+ 'GuzzleHttp\\Subscriber\\Oauth\\' => 28,
+ 'GuzzleHttp\\Subscriber\\Log\\' => 26,
+ 'GuzzleHttp\\Stream\\' => 18,
+ 'GuzzleHttp\\Ring\\' => 16,
+ 'GuzzleHttp\\' => 11,
+ ),
+ 'C' =>
+ array (
+ 'Cardinity\\' => 10,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Wechat\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/zoujingli/wechat-php-sdk/Wechat',
+ ),
+ 'Symfony\\Polyfill\\Mbstring\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
+ ),
+ 'Symfony\\Polyfill\\Ctype\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
+ ),
+ 'Symfony\\Component\\Validator\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/validator',
+ ),
+ 'Symfony\\Component\\Translation\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/translation',
+ ),
+ 'React\\Promise\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/react/promise/src',
+ ),
+ 'Psr\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+ ),
+ 'GuzzleHttp\\Subscriber\\Oauth\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/oauth-subscriber/src',
+ ),
+ 'GuzzleHttp\\Subscriber\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/log-subscriber/src',
+ ),
+ 'GuzzleHttp\\Stream\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/streams/src',
+ ),
+ 'GuzzleHttp\\Ring\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/ringphp/src',
+ ),
+ 'GuzzleHttp\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
+ ),
+ 'Cardinity\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/cardinity/cardinity-sdk-php/src',
+ ),
+ );
+
+ public static $fallbackDirsPsr4 = array (
+ 0 => __DIR__ . '/..' . '/klarna/kco_rest/src',
+ );
+
+ public static $prefixesPsr0 = array (
+ 'D' =>
+ array (
+ 'Divido' =>
+ array (
+ 0 => __DIR__ . '/..' . '/divido/divido-php/lib',
+ ),
+ ),
+ 'B' =>
+ array (
+ 'Braintree' =>
+ array (
+ 0 => __DIR__ . '/..' . '/braintree/braintree_php/lib',
+ ),
+ ),
+ );
+
+ public static $classMap = array (
+ 'scss_formatter' => __DIR__ . '/..' . '/leafo/scssphp/scss.inc.php',
+ 'scss_formatter_compressed' => __DIR__ . '/..' . '/leafo/scssphp/scss.inc.php',
+ 'scss_formatter_nested' => __DIR__ . '/..' . '/leafo/scssphp/scss.inc.php',
+ 'scss_parser' => __DIR__ . '/..' . '/leafo/scssphp/scss.inc.php',
+ 'scss_server' => __DIR__ . '/..' . '/leafo/scssphp/scss.inc.php',
+ 'scssc' => __DIR__ . '/..' . '/leafo/scssphp/scss.inc.php',
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::$prefixDirsPsr4;
+ $loader->fallbackDirsPsr4 = ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::$fallbackDirsPsr4;
+ $loader->prefixesPsr0 = ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::$prefixesPsr0;
+ $loader->classMap = ComposerStaticInit4356ab4fdc794d105db4fa48b241456c::$classMap;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/public/system/storage/vendor/composer/installed.json b/public/system/storage/vendor/composer/installed.json
new file mode 100644
index 0000000..ac23707
--- /dev/null
+++ b/public/system/storage/vendor/composer/installed.json
@@ -0,0 +1,899 @@
+[
+ {
+ "name": "braintree/braintree_php",
+ "version": "3.2.0",
+ "version_normalized": "3.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/braintree/braintree_php.git",
+ "reference": "c7e0e2d1ae21d659cddb5507fb0bf181813b5733"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/braintree/braintree_php/zipball/c7e0e2d1ae21d659cddb5507fb0bf181813b5733",
+ "reference": "c7e0e2d1ae21d659cddb5507fb0bf181813b5733",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-dom": "*",
+ "ext-hash": "*",
+ "ext-openssl": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*"
+ },
+ "time": "2015-07-15T15:07:13+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Braintree": "lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Braintree",
+ "homepage": "http://www.braintreepayments.com"
+ }
+ ],
+ "description": "Braintree PHP Client Library"
+ },
+ {
+ "name": "cardinity/cardinity-sdk-php",
+ "version": "v1.0.3",
+ "version_normalized": "1.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cardinity/cardinity-sdk-php.git",
+ "reference": "f51f6fbacee393b4eeff7b80be2b1cee77896b4c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cardinity/cardinity-sdk-php/zipball/f51f6fbacee393b4eeff7b80be2b1cee77896b4c",
+ "reference": "f51f6fbacee393b4eeff7b80be2b1cee77896b4c",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~5.1",
+ "guzzlehttp/log-subscriber": "~1.0",
+ "guzzlehttp/oauth-subscriber": "0.2.*",
+ "php": ">=5.4.0",
+ "symfony/validator": "~2.6"
+ },
+ "require-dev": {
+ "monolog/monolog": "~1.0",
+ "phpspec/phpspec": "~2.1",
+ "phpunit/phpunit": "~4.3"
+ },
+ "time": "2016-12-29T09:57:23+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Cardinity\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Client library for Cardinity credit card processing API",
+ "homepage": "http://cardinity.com"
+ },
+ {
+ "name": "divido/divido-php",
+ "version": "v1.15-stable",
+ "version_normalized": "1.15.0.0",
+ "source": {
+ "type": "git",
+ "url": "git@github.com:DividoFinancialServices/divido-api-php.git",
+ "reference": "8edd902ec2be8151331985021107031292b41ca1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DividoFinancialServices/divido-api-php/zipball/8edd902ec2be8151331985021107031292b41ca1",
+ "reference": "8edd902ec2be8151331985021107031292b41ca1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.2.0"
+ },
+ "time": "2018-01-21T15:38:57+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "master": "2.0-dev",
+ "v1.1.1": "1.1.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Divido": "lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Divido PHP library",
+ "homepage": "https://www.divido.com/",
+ "keywords": [
+ "api",
+ "divido",
+ "finance",
+ "instalments",
+ "payment processing"
+ ]
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "5.3.3",
+ "version_normalized": "5.3.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "93bbdb30d59be6cd9839495306c65f2907370eb9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/93bbdb30d59be6cd9839495306c65f2907370eb9",
+ "reference": "93bbdb30d59be6cd9839495306c65f2907370eb9",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/ringphp": "^1.1",
+ "php": ">=5.4.0",
+ "react/promise": "^2.2"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.0"
+ },
+ "time": "2018-07-31T13:33:10+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ]
+ },
+ {
+ "name": "guzzlehttp/log-subscriber",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/log-subscriber.git",
+ "reference": "99c3c0004165db721d8ef7bbef60c996210e538a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/log-subscriber/zipball/99c3c0004165db721d8ef7bbef60c996210e538a",
+ "reference": "99c3c0004165db721d8ef7bbef60c996210e538a",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~4.0 | ~5.0",
+ "php": ">=5.4.0",
+ "psr/log": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "time": "2014-10-13T03:31:43+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Subscriber\\Log\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Logs HTTP requests and responses as they are sent over the wire (Guzzle 4+)",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "Guzzle",
+ "log",
+ "plugin"
+ ]
+ },
+ {
+ "name": "guzzlehttp/oauth-subscriber",
+ "version": "0.2.0",
+ "version_normalized": "0.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/oauth-subscriber.git",
+ "reference": "03f1ebe31d3112526106d0570c80eba6820e86e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/oauth-subscriber/zipball/03f1ebe31d3112526106d0570c80eba6820e86e5",
+ "reference": "03f1ebe31d3112526106d0570c80eba6820e86e5",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~4.0|~5.0",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "time": "2014-10-23T22:19:02+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Subscriber\\Oauth\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle OAuth 1.0 subscriber",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "Guzzle",
+ "oauth"
+ ]
+ },
+ {
+ "name": "guzzlehttp/ringphp",
+ "version": "1.1.1",
+ "version_normalized": "1.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/RingPHP.git",
+ "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/5e2a174052995663dd68e6b5ad838afd47dd615b",
+ "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/streams": "~3.0",
+ "php": ">=5.4.0",
+ "react/promise": "~2.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0"
+ },
+ "suggest": {
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
+ },
+ "time": "2018-07-31T13:22:33+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Ring\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function."
+ },
+ {
+ "name": "guzzlehttp/streams",
+ "version": "3.0.0",
+ "version_normalized": "3.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/streams.git",
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "time": "2014-10-12T19:18:40+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Stream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Provides a simple abstraction over streams of data",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "Guzzle",
+ "stream"
+ ]
+ },
+ {
+ "name": "klarna/kco_rest",
+ "version": "v2.2.0",
+ "version_normalized": "2.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/klarna/kco_rest_php.git",
+ "reference": "8a2142a2ebb087bb61901d51d1bb9698790e78c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/klarna/kco_rest_php/zipball/8a2142a2ebb087bb61901d51d1bb9698790e78c5",
+ "reference": "8a2142a2ebb087bb61901d51d1bb9698790e78c5",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": ">=4.2,<6.0",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "apigen/apigen": "4.0.*",
+ "klarna/apigen-theme": "~1.0",
+ "phploc/phploc": "2.0.*",
+ "phpmd/phpmd": "2.1.*",
+ "phpunit/phpunit": "4.2.*",
+ "satooshi/php-coveralls": "0.6.*",
+ "sebastian/phpcpd": "2.0.*",
+ "squizlabs/php_codesniffer": "1.5.*"
+ },
+ "time": "2015-12-07T09:51:35+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Klarna AB",
+ "email": "integration@klarna.com"
+ }
+ ],
+ "description": "Klarna Checkout PHP SDK",
+ "homepage": "http://developers.klarna.com"
+ },
+ {
+ "name": "leafo/scssphp",
+ "version": "v0.0.12",
+ "version_normalized": "0.0.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/leafo/scssphp.git",
+ "reference": "ff76df3e45af45e808f3fcd516a2cb5cbc77f45e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/leafo/scssphp/zipball/ff76df3e45af45e808f3fcd516a2cb5cbc77f45e",
+ "reference": "ff76df3e45af45e808f3fcd516a2cb5cbc77f45e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "php": ">=5.3.0",
+ "phpunit/phpunit": "3.7.*"
+ },
+ "time": "2014-07-07T01:51:39+00:00",
+ "bin": [
+ "pscss"
+ ],
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "scss.inc.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Leaf Corcoran",
+ "email": "leafot@gmail.com",
+ "homepage": "http://leafo.net"
+ }
+ ],
+ "description": "scssphp is a compiler for SCSS written in PHP.",
+ "homepage": "http://leafo.net/scssphp/"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.0",
+ "version_normalized": "1.1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2018-11-20T15:27:04+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ]
+ },
+ {
+ "name": "react/promise",
+ "version": "v2.7.1",
+ "version_normalized": "2.7.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/promise.git",
+ "reference": "31ffa96f8d2ed0341a57848cbb84d88b89dd664d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/31ffa96f8d2ed0341a57848cbb84d88b89dd664d",
+ "reference": "31ffa96f8d2ed0341a57848cbb84d88b89dd664d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ },
+ "time": "2019-01-07T21:25:54+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com"
+ }
+ ],
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "keywords": [
+ "promise",
+ "promises"
+ ]
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.11.0",
+ "version_normalized": "1.11.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "82ebae02209c21113908c229e9883c419720738a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
+ "reference": "82ebae02209c21113908c229e9883c419720738a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "time": "2019-02-06T07:57:58+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.11-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ },
+ {
+ "name": "Gert de Pagter",
+ "email": "backendtea@gmail.com"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ]
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.11.0",
+ "version_normalized": "1.11.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
+ "reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2019-02-06T07:57:58+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.11-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ]
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v3.0.9",
+ "version_normalized": "3.0.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/eee6c664853fd0576f21ae25725cfffeafe83f26",
+ "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/config": "<2.8"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/intl": "~2.8|~3.0",
+ "symfony/yaml": "~2.8|~3.0"
+ },
+ "suggest": {
+ "psr/log": "To use logging capability in translator",
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "time": "2016-07-30T07:22:48+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Translation Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "symfony/validator",
+ "version": "v2.8.49",
+ "version_normalized": "2.8.49.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/validator.git",
+ "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/validator/zipball/d5d2090bba3139d8ddb79959fbf516e87238fe3a",
+ "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/translation": "~2.4|~3.0.0"
+ },
+ "require-dev": {
+ "doctrine/annotations": "~1.0",
+ "doctrine/cache": "~1.0",
+ "egulias/email-validator": "^1.2.1",
+ "symfony/config": "~2.2|~3.0.0",
+ "symfony/expression-language": "~2.4|~3.0.0",
+ "symfony/http-foundation": "~2.3|~3.0.0",
+ "symfony/intl": "~2.7.25|^2.8.18|~3.2.5",
+ "symfony/property-access": "~2.3|~3.0.0",
+ "symfony/yaml": "^2.0.5|~3.0.0"
+ },
+ "suggest": {
+ "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
+ "doctrine/cache": "For using the default cached annotation reader and metadata cache.",
+ "egulias/email-validator": "Strict (RFC compliant) email validation",
+ "symfony/config": "",
+ "symfony/expression-language": "For using the 2.4 Expression validator",
+ "symfony/http-foundation": "",
+ "symfony/intl": "",
+ "symfony/property-access": "For using the 2.4 Validator API",
+ "symfony/yaml": ""
+ },
+ "time": "2018-11-14T14:06:48+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Validator\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Validator Component",
+ "homepage": "https://symfony.com"
+ },
+ {
+ "name": "zoujingli/wechat-php-sdk",
+ "version": "v1.3.17",
+ "version_normalized": "1.3.17.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/zoujingli/wechat-php-sdk.git",
+ "reference": "afb0dfd1a0fd71cfe58b6811d559b6b0fc8f9de0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/zoujingli/wechat-php-sdk/zipball/afb0dfd1a0fd71cfe58b6811d559b6b0fc8f9de0",
+ "reference": "afb0dfd1a0fd71cfe58b6811d559b6b0fc8f9de0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "time": "2018-10-23T09:57:56+00:00",
+ "type": "project",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Wechat\\": "./Wechat"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "WeChat development of SDK",
+ "homepage": "http://www.kancloud.cn/zoujingli/wechat-php-sdk",
+ "keywords": [
+ "wechat-php-sdk"
+ ]
+ }
+]
diff --git a/public/system/storage/vendor/divido/divido-php/.gitignore b/public/system/storage/vendor/divido/divido-php/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/public/system/storage/vendor/divido/divido-php/Example.php b/public/system/storage/vendor/divido/divido-php/Example.php
new file mode 100644
index 0000000..88de621
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/Example.php
@@ -0,0 +1,138 @@
+<?php
+$apiKey = "";
+
+$amount = 1200;
+$sandbox = true;
+
+require_once('./lib/Divido.php');
+Divido::setMerchant($apiKey);
+
+if ($_POST) {
+ $response = Divido_CreditRequest::create(array(
+ "country" => "GB",
+ "finance" => $_POST['finance'],
+ "reference"=>$_POST['reference'],
+ "customer" => array(
+ "title" => $_POST['title'],
+ "first_name" => $_POST['firstName'],
+ "middle_name" => $_POST['middleName'],
+ "last_name" => $_POST['lastName'],
+ "email" => $_POST['email'],
+ "mobileNumber" => $_POST['mobileNumber'],
+ "phoneNumber" => $_POST['phoneNumber'],
+ "postcode" => $_POST['postCode'],
+ "country" => $_POST['country'],
+ ),
+ "metadata"=>array(
+ "orderNumber"=>10001,
+ "checksum"=>md5('10001:mySecret')
+ ),
+ "products"=>array(
+ array(
+ "type"=>"product",
+ "text"=>"Gibson Les Paul Studio Raw Guitar",
+ "quantity"=>1,
+ "value"=>1153.00,
+ ),
+ array(
+ "type"=>"service",
+ "text"=>"Restring Upgrade",
+ "quantity"=>1,
+ "value"=>100.00,
+ ),
+ ),
+ "response_url"=>"http://www.webshop.com/callback.php",
+ 'checkout_url'=>'http://www.webshop.com/checkout',
+ "redirect_url"=>"http://www.webshop.com/success.php",
+ ));
+
+ if ($response->status == 'ok') {
+ header("Location:".$response->url);
+ } else {
+ print_r($response->__toArray());
+ }
+
+} else {
+ ?>
+ <form method="post">
+
+ <table width="400">
+ <tr>
+ <td>Finance:</td>
+ <td><select name="finance">
+ <?php
+ $response = Divido_Finances::all();
+
+ if ($response->status == 'ok') {
+ foreach($response->finances as $finance) {
+ print '<option value="'.$finance->id.'">'.$finance->text.' ('.$finance->interest_rate.'% APR)</option>';
+ }
+ }
+ ?>
+ </select></td>
+ </tr>
+ <tr>
+ <td>Reference:</td>
+ <td><input type="text" name="reference" value="11001"></td>
+ </tr>
+ <tr>
+ <td>Amount:</td>
+ <td>&pound; <?php print number_format($amount); ?></td>
+ </tr>
+ <tr>
+ <td>Deposit:</td>
+ <td>&pound; <input type="text" name="deposit" value="100"></td>
+ </tr>
+ <tr>
+ <td colspan="2">&nbsp;</td>
+ </tr>
+ <tr>
+ <td>Title:</td>
+ <td><select name="title">
+ <option value="Mr">Mr</option>
+ <option value="Mrs" selected>Mrs</option>
+ </select></td>
+ </tr>
+ <tr>
+ <td>First Name:</td>
+ <td><input type="text" name="firstName" value="Ann"></td>
+ </tr>
+ <tr>
+ <td>Middle Name:</td>
+ <td><input type="text" name="middleName" value=""></td>
+ </tr>
+ <tr>
+ <td>Last Name:</td>
+ <td><input type="text" name="lastName" value="Heselden"></td>
+ </tr>
+ <tr>
+ <td>Phone:</td>
+ <td><input type="text" name="phoneNumber" value="0201234567"></td>
+ </tr>
+ <tr>
+ <td>Mobile:</td>
+ <td><input type="text" name="mobileNumber" value="0701234567"></td>
+ </tr>
+ <tr>
+ <td>Email:</td>
+ <td><input type="text" name="email" value="hallsten@me.com"></td>
+ </tr>
+ <tr>
+ <td>Post Code:</td>
+ <td><input type="text" name="postCode" value="BA13 3BN"></td>
+ </tr>
+ <tr>
+ <td>Country:</td>
+ <td><select name="country">
+ <option value="GB" selected>GB</option>
+ </select></td>
+ </tr>
+ </table>
+
+
+
+ <input type="submit" name="test" value="Continue to Divido" />
+
+ </form>
+ <?
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/divido/divido-php/README.md b/public/system/storage/vendor/divido/divido-php/README.md
new file mode 100644
index 0000000..6fca063
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/README.md
@@ -0,0 +1,1771 @@
+Divido API
+=======
+
+This is the documentation for the Divido API.
+
+Sign up for an account to get instant access to our sandbox environment.
+
+*Current version: v1.15*
+
+
+Getting started
+---------------
+
+There are several distinct parts of a complete integration with the Divido API:
+
+ * Deal Calculator
+ * Finances
+ * Credit Request
+ * Finalize Credit Request
+ * Activation
+ * Cancellation
+ * Refund
+ * List all applications
+ * Retrieve an application
+ * Reporting / List all payment batches
+ * Reporting / Retrieve records from a payment batch
+
+
+### Deal Calculator
+
+Calculate APR, monthly repayments, duration etc
+
+### Finances
+
+List Rate Card and all financial products available for a specific merchant.
+
+### Credit Request
+
+Create a new credit proposal and return an url to application form
+
+### Finalize Credit Request
+
+Finalize an existing accepted credit application, will update the loan agreement and return an url to the contract signing.
+
+### Activation
+
+Activate whole or part of application
+
+### Cancellation
+
+Cancel a deactivated application
+
+### Refund
+
+Refund a part or whole of an activated application
+
+### List all applications
+
+Returns a list of your applications. The applications are returned sorted by creation date, with the most recently created applications appearing first.
+
+### Retrieve an application
+
+Retrieves the details of an existing application. Supply the application ID and the API will return the corresponding application.
+
+### Reporting / List all payment batches
+
+Retrieves all payment batches.
+
+### Reporting / Retrieve records from a payment batch
+
+Retrieves the content of a payment batch. Supply the batch ID and the API will return all records.
+
+
+Change log
+------------
+
+#### 2018-01-21
+- Internal changes and bug fixes
+
+#### 2017-11-03
+- Updated example response from Applications endpoint to include `url` and `lenderLoanReference`
+
+#### 2017-04-21
+- Added text element to address object, used for mergining one address line into flat, street, buildingNumber, buildingName.
+
+#### 2017-03-25
+- Added amount, products and reference to Cancellation Request. This allows partial cancellation of current unactivated amount
+
+#### 2017-03-13
+- Added shipping address to Credit Request
+
+#### 2016-12-20
+- Added Deal Calculator
+- Added directSign to Credit Request
+- Added Finalize Credit Request
+- Added activation status
+
+#### 2016-11-28
+
+- Added reference on activate and refund
+- Security enhancement: Added support for signing all api calls with a shared secret, contact Divido Support for more info.
+
+#### 2016-11-16
+
+- Added filter on proposal for List all applications
+- Updated the webhook response
+- Added reference in Credit Request
+
+
+#### 2016-11-07
+
+- Added product amount for refund and activation
+
+#### 2016-11-02
+
+- Added product lines for refund and activation
+
+#### 2016-11-01
+
+- Renamed fulfillment to activation
+- Added reporting
+
+
+#### 2016-10-30
+
+- Added refunds, fulfillments, fulfillmentStatus to respones
+
+#### 2016-10-18
+
+- Removed Deal Calculator
+- Added new statuses
+- Changed the product dataset
+- Updated the responses from the API
+
+
+#### 2016-09-27
+
+- Added partial fulfillment
+- Added refund
+- Added list all applications
+- Added retrieve an application
+- Added new statuses
+- Bug fixes
+
+#### 2016-06-28
+
+- Added cancellation method
+- Checkout URL
+- Bug fixes
+- Added more community libraries
+
+#### 2016-01-28
+
+- Added fulfillment method
+
+#### 2015-06-21
+
+- Added product to credit request
+- Campaigns changed to Finances
+
+
+Offical Libraries
+---------------
+
+We strongly encourage use of our official libraries for accessing the Divido API. Our official libraries are listed below, as well as community supported libraries.
+
+#### PHP
+
+Install from source
+
+ `git clone https://github.com/DividoFinancialServices/divido-api-php.git`
+
+
+Community libraries
+---------------
+
+Please submit a pull request to this page to add any missing libraries that should be featured here. Please note that Divido does not offer any support for community libraries.
+
+#### Magento 1.*
+
+ - [Divido for Magento 1.*](https://github.com/DividoFinancialServices/divido-magento)
+
+#### Magento 2
+
+ - [Divido for Magento 2](https://github.com/DividoFinancialServices/magento2-module)
+
+#### WooCommerce
+
+ - [Divido for WooCommerce](https://wordpress.org/plugins/divido-for-woocommerce/)
+
+#### OpenCart
+
+ - [Divido for OpenCart](https://github.com/DividoFinancialServices/divido-opencart)
+
+
+Using the API
+===========
+
+API endpoints
+---------------
+To use the Divido API to query data, you will need to send a request to the correct endpoint. Request endpoints should depend on whether you wish to query the live or sandbox environment:
+
+ - Sandbox: `https://secure.sandbox.divido.com/v1/`
+ - Live: `https://secure.divido.com/v1/`
+
+HTTP response codes
+---------------
+You may encounter the following response codes. Any unsuccessful response codes will contain more information to help you identify the cause of the problem.
+
+ - `200` The request has succeeded.
+
+ - `201` The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field.
+
+ - `404` Not Found. The requested resource was not found. The response body will explain which resource was not found.
+
+ - `500` Internal Server Error. The server encountered an error while processing your request and failed. Please report this to the Divido support team.
+
+
+
+Webhooks
+===========
+
+To alert you of any changes in the status of your resources, Divido provides webhooks. These are POST requests to your server that are sent as soon as a resource changes status. The body of the request contains details of the change.
+
+Request
+---------------
+The API server will send a POST request to the `response_url` associated with the application or `webhook_url` set by Divido support team.
+
+
+#### Parameters
+
+
+`application` Application ID
+
+`proposal` Proposal ID
+
+`reference` Third party reference (if supplied as part of the application)
+
+`status` New status
+
+`metadata` Metadata (if supplied as part of the application)
+
+
+#### Example Request
+
+JSON example
+
+``` json
+{
+ "application": "C84047A6D-89B2-FECF-D2B4-168444F5178C",
+ "event": "application-status-update",
+ "metadata": {
+ "Invoice Number": "844001",
+ "Order Number": "100019"
+ },
+ "name": "John Doe",
+ "proposal": "PAA717844-EE9D-78AF-D11C-EDCC1D180F87",
+ "reference": "100019",
+ "status": "ACCEPTED"
+}
+```
+
+Possible statuses
+---------------
+
+ - `DRAFT` - Proposal send to Underwriter, waiting for decision
+
+ - `ACCEPTED` - Application accepted by Underwriter
+
+ - `DECLINED` - Applicaiton declined by Underwriter
+
+ - `REFERRED` - Application referred by Underwriter, waiting for new status
+
+ - `INFO-NEEDED` - More information is required before decision
+
+ - `ACTION-CUSTOMER` - Waiting for more information from Customer
+
+ - `ACTION-RETAILER` - Waiting for more information from Merchant
+
+ - `ACTION-LENDER` - Waiting for more information from Underwriter
+
+ - `DEPOSIT-PAID` - Deposit paid by customer
+
+ - `SIGNED` - Customer has signed all contracts
+
+ - `AWAITING-ACTIVATION` - Waiting for confirmation from Underwriter
+
+ - `AWAITING-CANCELLATION` - Waiting for confirmation from Underwriter
+
+ - `PARTIALLY-ACTIVATED` - Application partially activated by merchant
+
+ - `ACTIVATED` - Application activated and confirmed by Underwriter
+
+ - `CANCELLED` - Application cancelled
+
+ - `REFUNDED` - Whole Application refunded
+
+ - `DISPUTED` - Dispute raised by Merchant or Underwriter
+
+ - `LOAN-REVERSAL` - Loan reversal in progress
+
+ - `COMPLETED` - Application completed (after cool down period)
+
+
+
+Resources
+===========
+
+Finances
+------------------
+
+Returns an array with all finance options available for merchant
+
+#### Example Request
+ `GET` https://secure.divido.com/v1/finances?merchant={MERCHANT}&country={COUNTRY} `HTTP/1.1`
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "finances": [
+ {
+ "agreement_duration": 6,
+ "country": "GB",
+ "deferral_period": 0,
+ "id": "F06895E17-EE96-926E-7137-37BCABB9DCF7",
+ "instalment_fee": 0,
+ "interest_rate": 0,
+ "max_deposit": 50,
+ "min_amount": 150,
+ "min_deposit": 0,
+ "setup_fee": 0,
+ "text": "6 Month 0% Interest Free"
+ },
+ {
+ "agreement_duration": 12,
+ "country": "GB",
+ "deferral_period": 0,
+ "id": "F284D5F1D-E8AF-D4B7-E1AF-A352F6087352",
+ "instalment_fee": 0,
+ "interest_rate": 0,
+ "max_deposit": 50,
+ "min_amount": 150,
+ "min_deposit": 0,
+ "setup_fee": 0,
+ "text": "12 Month 0% Interest Free"
+ }
+ ],
+ "status": "ok"
+}
+```
+
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`country` - The country code (*Optional, String*)
+
+```
+Example `GB`
+```
+
+
+
+Deal Calculator
+------------------
+
+The deal calculator calculates the payment terms for various terms and deposits.
+
+#### Example Request
+ `GET` https://secure.divido.com/v1/dealcalculator?merchant={MERCHANT}&amount={AMOUNT}&deposit={deposit}&country={country}&finance={FINANCE} `HTTP/1.1`
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "status": 'ok',
+ "purchase_price": 2000,
+ "deposit_amount": 200,
+ "credit_amount": 1800,
+ "monthly_payment_amount": 150,
+ "total_repayable_amount": 1800,
+ "agreement_duration": 12,
+ "interest_rate": 0.0,
+ "interest_type": "APR"
+ }
+```
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`amount`
+ - The total value of the order (*Required, Float*)
+
+```
+Example `2000.00`
+```
+
+ `deposit` - The value of the deposit. (*Required, Float*)
+
+```
+Example `200`
+```
+
+ `country` - The country code (*Required, String*)
+
+```
+Example `GB`
+```
+
+ `finance` - The finance code (*Required, String*)
+
+```
+Example `FA48EC74D-D95D-73A9-EC99-004FBE14A027`
+```
+
+
+
+Credit Request
+------------------
+
+The credit request creates a new proposal and return a URL to the Divido application form.
+
+#### Example Request
+ `POST` https://secure.divido.com/v1/creditrequest `HTTP/1.1`
+
+
+``` javascript
+curl https://secure.divido.com/v1/creditrequest \
+-d merchant=live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102 \
+-d deposit=100 \
+-d finance=F06895E17-EE96-926E-7137-37BCABB9DCF7 \
+-d directSign=true \
+-d country=GB \
+-d language=EN \
+-d currency=GBP \
+-d amount=1197.5 \
+-d reference=100019 \
+-d "customer[firstName]=John" \
+-d "customer[middleNames]=L" \
+-d "customer[lastName]=Doe" \
+-d "customer[country]=GB" \
+-d "customer[address][text]=115 High Street EC2A 4BX" \
+-d "customer[address][postcode]=EC2A 4BX" \
+-d "customer[address][street]=High street" \
+-d "customer[address][flat]=B" \
+-d "customer[address][buildingNumber]=115" \
+-d "customer[address][buildingName]=Amanda apartments" \
+-d "customer[address][town]=London" \
+-d "customer[address][monthsAtAddress]=60" \
+-d "customer[gender]=male" \
+-d "customer[shippingAddress][postcode]=EC2A 4BX" \
+-d "customer[shippingAddress][street]=High street" \
+-d "customer[shippingAddress][flat]=B" \
+-d "customer[shippingAddress][buildingNumber]=115" \
+-d "customer[shippingAddress][buildingName]=Amanda apartments" \
+-d "customer[shippingAddress][town]=London" \
+-d "customer[email]=john.doe@domain.com" \
+-d "customer[phoneNumber]=+44201234567" \
+-d "customer[dateOfBirthYear]=1967" \
+-d "customer[dateOfBirthMonth]=07" \
+-d "customer[dateOfBirthDay]=01" \
+-d "customer[bank][sortCode]=123456" \
+-d "customer[bank][accountNumber]=12345678" \
+-d "metadata[Invoice Number]=844001" \
+-d "metadata[Order Number]=100019" \
+-d "products[1][sku]=GIB100" \
+-d "products[1][name]=Gibson Les Paul Studio Raw Guitar" \
+-d "products[1][quantity]=1" \
+-d "products[1][price]=1153.00" \
+-d "products[1][vat]=20" \
+-d "products[1][unit]=pcs" \
+-d "products[1][image]=http://www.webshop.com/images/GIB100.png" \
+-d "products[2][sku]=H10" \
+-d "products[2][name]=Restring Upgrade" \
+-d "products[2][quantity]=0.5" \
+-d "products[2][price]=89" \
+-d "products[2][vat]=20" \
+-d "products[2][unit]=hour" \
+-d "products[2][attributes]=1" \
+-d "responseUrl=http://www.webshop.com/response.php" \
+-d "checkoutUrl=http://www.webshop.com/checkout" \
+-d "redirectUrl=http://www.webshop.com/success.html"
+```
+
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "id": "PD66DF728-5646-22E3-EF6F-CD3D2D094170",
+ "status": "ok",
+ "token": "bcaa33546495965c4c8b3dc41d8582a1",
+ "url": "https://secure.divido.com/token/bcaa33546495965c4c8b3dc41d8582a1"
+}
+```
+
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+ -
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`deposit` - The value of the deposit. (*Required, Float*)
+
+```
+Example `100`
+```
+
+`finance` - The finance code (*Required, String*)
+
+```
+Example `F23B150D4-9D00-724A-6DFA-A1E726F6761A`
+```
+
+`directSign` - Whether or not to immediately go to signing after approval (*Optional, Boolean*, Default is `true`)
+
+```
+Example `true`
+```
+
+
+`country` - The country code (*Required, String*)
+
+```
+Example `GB`
+```
+
+`language` - The country code (*Required, String*)
+
+```
+Example `EN`
+```
+
+`currency` - The currency code (*Required, String*)
+
+```
+Example `GBP`
+```
+
+`amount` - Order total in same currency as proposal. Used to validate the total from product line items. (*Optional, Float*)
+
+```
+Example `1197.5`
+```
+
+`reference` - Your intenral reference, will be returned in webhooks. (*Optional, Float*)
+
+```
+Example `100019`
+```
+
+`customer['firstName']` - Customer first name (*Optional, String*)
+
+```
+Example `Jane`
+```
+
+`customer['middleNames']` - Customer middle names (*Optional, String*)
+
+```
+Example `L`
+```
+
+`customer['lastName']` - Customer last name (*Optional, String*)
+
+```
+Example `Doe`
+```
+
+`customer['country']` - Customer country (*Optional, String*)
+
+```
+Example `GB`
+```
+
+`customer['address']['text']` - Customer address in one line. We will try to match the address and split it up in street, flat, buildingNumber, buildingName. (*Optional, String*
+
+```
+Example `115 High street EC2A 4BX`
+```
+
+
+`customer['address']['postcode']` - Customer postcode (*Optional, String*
+
+```
+Example `EC2A 4BX`
+```
+
+`customer['address']['street']` - Customer street (*Optional, String*)
+
+```
+Example `High street`
+```
+
+`customer['address']['flat']` - Customer flat (*Optional, String*)
+
+```
+Example `B`
+```
+
+`customer['address']['buildingNumber']` - Customer building number (*Optional, String*)
+
+```
+Example `115`
+```
+
+`customer['address']['buildingName']` - Customer building name (*Optional, String*)
+
+```
+Example `Amanda apartments`
+```
+
+`customer['address']['town']` - Customer town (*Optional, String*)
+
+```
+Example `London`
+```
+
+`customer['address']['monthsAtAddress']` - Customer months at address (*Optional, String*)
+
+```
+Example `60`
+```
+
+`customer['shippingAddress']['postcode']` - Customer postcode (*Optional, String*
+
+```
+Example `EC2A 4BX`
+```
+
+`customer['shippingAddress']['street']` - Customer street (*Optional, String*)
+
+```
+Example `High street`
+```
+
+`customer['shippingAddress']['flat']` - Customer flat (*Optional, String*)
+
+```
+Example `B`
+```
+
+`customer['shippingAddress']['buildingNumber']` - Customer building number (*Optional, String*)
+
+```
+Example `115`
+```
+
+`customer['shippingAddress']['buildingName']` - Customer building name (*Optional, String*)
+
+```
+Example `Amanda apartments`
+```
+
+`customer['shippingAddress']['town']` - Customer town (*Optional, String*)
+
+```
+Example `London`
+```
+
+`customer['gender']` - Customer gender (*Optional, String*)
+
+```
+Example `male`
+```
+
+`customer['email']` - Customer email (*Optional, String*)
+
+```
+Example `jane.doe@email.com`
+```
+
+`customer['phoneNumber']` - Customer phone number (*Optional, String*)
+
+```
+Example `0201234567`
+```
+
+`customer['dateOfBirthYear']` - Customer year of birth (*Optional, String*)
+
+```
+Example `1967`
+```
+
+`customer['dateOfBirthMonth']` - Customer month of birth (*Optional, String*)
+
+```
+Example `07`
+```
+
+`customer['dateOfBirthDay']` - Customer day of birth (*Optional, String*)
+
+```
+Example `01`
+```
+
+`customer['bank']['sortCode']` - Customer bank sort code (*Optional, String*)
+
+```
+Example `123456`
+```
+
+`customer['bank']['accountNumber']` - Customer bank account number (*Optional, String*)
+
+```
+Example `12345678`
+```
+
+`metadata['key']` - metadata key (*Optional, String*)
+
+```
+Example `Invoice Number`
+```
+
+`metadata['value']` - metadata value (*Optional, String*)
+
+```
+Example `844001`
+```
+
+`products['1']['sku']` - Product SKU (*Optional, String*)
+
+```
+Example `GIB100`
+```
+
+`products['1']['name']` - Product name/description (*Optional, String*)
+
+```
+Example `Gibson Les Paul Studio Raw Guitar`
+```
+
+`products['1']['quantity']` - Product quantity (*Optional, String*)
+
+```
+Example `1`
+```
+
+`products['1']['price']` - Product price in same currency as proposal (*Optional, String*)
+
+```
+Example `1153.00`
+```
+`products['1']['vat']` - Product VAT percentage (*Optional, String*)
+
+```
+Example `20`
+```
+
+`products['1']['unit']` - Product unit (*Optional, String*)
+```
+Example `pcs`
+```
+
+`products['1']['image']` - Product image (*Optional, String*)
+```
+Example `http://www.webshop.com/images/GIB100.png`
+```
+
+`products['1']['attributes']` - Product attributes (1=Service fee,2=Shipping fee,3=Payment fee,6=Discount, 10=Price is without VAT, 20=Line item with order VAT sum) (*Optional, String*)
+
+```
+Example `1,2`
+```
+
+`responseUrl` - The URL where we send notification about the payment (*Optional, String*)
+
+```
+Example `http://www.webshop.com/response.php`
+```
+
+`checkoutUrl` - A URL which Divido redirects the customer to if they get declined or wish to cancel their application (*Optional, String*)
+
+```
+Example `http://www.webshop.com/checkout`
+```
+
+`redirectUrl` - The URL the customer will get redirected to after a successful application (*Optional, String*)
+
+```
+Example `http://www.webshop.com/success.html`
+```
+
+Finalize Credit Request
+------------------
+
+Finalize an existing accepted credit application, will update the loan agreement and return an url to the contract signing. This only applies to Credit Requests created directSign = false.
+
+#### Example Request
+ `POST` https://secure.divido.com/v1/creditrequest/finalize `HTTP/1.1`
+
+
+``` javascript
+curl https://secure.divido.com/v1/creditrequest \
+-d merchant=live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102 \
+-d application=CAAC243AC-499A-84AF-DBBA-F58B9F7E798C \
+-d deposit=100 \
+-d finance=F06895E17-EE96-926E-7137-37BCABB9DCF7 \
+-d amount=1197.5 \
+-d "products[1][sku]=GIB100" \
+-d "products[1][name]=Gibson Les Paul Studio Raw Guitar" \
+-d "products[1][quantity]=1" \
+-d "products[1][price]=1153.00" \
+-d "products[1][vat]=20" \
+-d "products[1][unit]=pcs" \
+-d "products[1][image]=http://www.webshop.com/images/GIB100.png" \
+-d "products[2][sku]=H10" \
+-d "products[2][name]=Restring Upgrade" \
+-d "products[2][quantity]=0.5" \
+-d "products[2][price]=89" \
+-d "products[2][vat]=20" \
+-d "products[2][unit]=hour" \
+-d "products[2][attributes]=1" \
+-d "redirectUrl=http://www.webshop.com/success.html"
+```
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "id": "CAAC243AC-499A-84AF-DBBA-F58B9F7E798C",
+ "status": "ok",
+ "token": "bcaa33546495965c4c8b3dc41d8582a1",
+ "url": "https://secure.divido.com/token/bcaa33546495965c4c8b3dc41d8582a1"
+}
+```
+
+
+Activation
+------------------
+
+Activate whole or part of an application and initialise a payout from the underwriter. Activate part of the application by specifing the products that should be activated. If no product data is submitted, the whole application will be activated.
+
+#### Example Request
+ `POST` https://secure.divido.com/v1/activation `HTTP/1.1`
+
+
+``` javascript
+curl https://secure.divido.com/v1/activation \
+-d merchant="live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102" \
+-d application="CAAC243AC-499A-84AF-DBBA-F58B9F7E798C" \
+-d "products[1][sku]=GIB100" \
+-d "products[1][name]=Gibson Les Paul Studio Raw Guitar" \
+-d "products[1][quantity]=1" \
+-d "products[1][price]=1153.00" \
+-d "products[1][vat]=20" \
+-d "products[2][sku]=H10" \
+-d "products[2][name]=Restring Upgrade" \
+-d "products[2][quantity]=0.5" \
+-d "products[2][price]=89" \
+-d "products[2][vat]=20" \
+-d "products[2][attributes]=1" \
+-d amount=1197.5 \
+-d deliveryMethod="delivery" \
+-d trackingNumber="DHL291824419F" \
+-d reference="9482471" \
+-d comment="Order was delivered to the customer by DHL" \
+```
+
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "result": {
+ "creditAmount": 1097.5,
+ "depositAmount": 100,
+ "depositStatus": "PAID-BY-CARD",
+ "activatedAmount": 1197.5,
+ "activationStatus": "AWAITING-ACTIVATION",
+ "activations": [
+ {
+ "amount": 1197.5,
+ "comment": "Order was delivered to the customer by DHL",
+ "date": "2016-10-26 04:11",
+ "deliveryMethod": "delivery",
+ "reference": "9482471",
+ "status": "AWAITING-ACTIVATION",
+ "trackingNumber": "DHL291824419F"
+ }
+ ],
+ "cancellations": [],
+ "cancelledAmount": 0,
+ "id": "C8A05742F-3040-44EC-C252-050FD8869F79",
+ "lender": {
+ "app": "Demo",
+ "id": "L10F2BE8F-EF89-E403-E38F-8589ED2E51F5",
+ "name": "Demo"
+ },
+ "purchasePrice": 1197.5,
+ "refundedAmount": 0,
+ "refunds": [],
+ "status": "AWAITING-ACTIVATION"
+ },
+ "status": "ok"
+}
+```
+
+
+#### Parameters
+
+`merchant` - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102 `
+```
+
+`application` - The application or proposal identifier. (*Required, String*)
+
+```
+Example `CAAC243AC-499A-84AF-DBBA-F58B9F7E798C`
+```
+
+`products['1']['sku']` - Product SKU (*Optional, String*)
+
+```
+Example `GIB100`
+```
+
+`products['1']['name']` - Product name/description (*Optional, String*)
+
+```
+Example `Gibson Les Paul Studio Raw Guitar`
+```
+
+`products['1']['quantity']` - Product quantity (*Optional, String*)
+
+```
+Example `1`
+```
+
+`products['1']['price']` - Product price in same currency as proposal (*Optional, String*)
+
+```
+Example `1153.00`
+```
+`products['1']['vat']` - Product VAT percentage (*Optional, String*)
+
+```
+Example `20`
+```
+
+`amount` - Sum of the activated products (*Optional, String*)
+
+```
+Example `1197.5`
+```
+
+`deliveryMethod` - How the goods were delivered, can be either "store" or "delivery" (*Required, String*)
+
+```
+Example `delivery`
+```
+
+`trackingNumber` - If the deliveryMethod is delivery and you have a tracking number (*Optional, String*)
+
+```
+Example `DHL291824419F`
+```
+
+`reference` - Your reference to identify the activation (*Optional, String*)
+
+```
+Example `9482471 `
+```
+
+`comment` - Comment to the underwriter, can be order number or other information (*Optional, String*)
+
+```
+Example `Order was delivered to the customer by DHL`
+```
+
+Cancellation
+------------------
+
+Mark an application as cancelled and notify the underwriter, only possible if application is DRAFT, REFERRED, INFO-NEEDED, ACTION-CUSTOMER, ACTION-RETAILER, ACTION-LENDER, ACCEPTED, DEPOSIT-PAID, PARTIALLY-ACTIVATED, SIGNED.
+
+#### Example Request
+ `POST` https://secure.divido.com/v1/cancellation `HTTP/1.1`
+
+
+``` javascript
+curl https://secure.divido.com/v1/cancellation \
+-d merchant="live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102" \
+-d application="CAAC243AC-499A-84AF-DBBA-F58B9F7E798C" \
+-d "products[1][sku]=H10" \
+-d "products[1][name]=Restring Upgrade" \
+-d "products[1][quantity]=0.5" \
+-d "products[1][price]=89" \
+-d "products[1][vat]=20" \
+-d "products[1][attributes]=1" \
+-d amount=44.5 \
+-d reference="7321834" \
+-d comment="Customer requested to cancelled the order"
+```
+
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "result": {
+ "creditAmount": 1097.5,
+ "depositAmount": 100,
+ "depositStatus": "UNPAID",
+ "activatedAmount": 0,
+ "activationStatus": "AWAITING-ACTIVATION",
+ "activations": [],
+ "id": "CAAC243AC-499A-84AF-DBBA-F58B9F7E798C",
+ "lender": {
+ "app": "Demo",
+ "id": "L10F2BE8F-EF89-E403-E38F-8589ED2E51F5",
+ "name": "Demo"
+ },
+ "purchasePrice": 1197.5,
+ "refundedAmount": 0,
+ "refunds": [],
+ "cancelledAmount": 44.5,
+ "cancellations": [
+ {
+ "date": "2017-03-27 02:46",
+ "amount": 44.5,
+ "status": "PENDING",
+ "reference": "ref: 1490582812",
+ "comment": ""
+ }
+ ],
+ "status": "AWAITING-CANCELLATION"
+ },
+ "status": "ok"
+}
+```
+
+
+#### Parameters
+
+`merchant` - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102 `
+```
+
+`application` - The application or proposal identifier. (*Required, String*)
+
+```
+Example `CAAC243AC-499A-84AF-DBBA-F58B9F7E798C `
+```
+
+`products['1']['sku']` - Product SKU (*Optional, String*)
+
+```
+Example `H10`
+```
+
+`products['1']['name']` - Product name/description (*Optional, String*)
+
+```
+Example `Restring Upgrade`
+```
+
+`products['1']['quantity']` - Product quantity (*Optional, String*)
+
+```
+Example `1`
+```
+
+`products['1']['price']` - Product price in same currency as proposal (*Optional, String*)
+
+```
+Example `89`
+```
+`products['1']['vat']` - Product VAT percentage (*Optional, String*)
+
+```
+Example `20`
+```
+
+`products['1']['attributes']` - Product attributes (1=Service,2=Shipping fee,3=Payment fee, 10=Price is without VAT) (*Optional, String*)
+
+```
+Example `1,2`
+```
+
+`amount` - Sum of the refunded items (*Optional, String*)
+
+```
+Example `89`
+```
+
+`reference` - Your reference to identify the refund (*Optional, String*)
+
+```
+Example `7321834`
+```
+
+`comment` - Comment to the underwriter, can be order number or other information (*Optional, String*)
+
+```
+Example `Customer requested to cancelled the order`
+```
+
+Refund
+------------------
+
+Refund whole or part of an application, if the application is AWAITING-ACTIVATION, PARTIALLY-ACTIVATED, ACTIVATED or COMPLETED. For partial refund, specify the products that have been refunded. If no product data is submitted the whole application will be refunded.
+
+#### Example Request
+ `POST` https://secure.divido.com/v1/refund `HTTP/1.1`
+
+
+``` javascript
+curl https://secure.divido.com/v1/refund \
+-d merchant="live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102" \
+-d application="CAAC243AC-499A-84AF-DBBA-F58B9F7E798C" \
+-d "products[1][sku]=H10" \
+-d "products[1][name]=Restring Upgrade" \
+-d "products[1][quantity]=0.5" \
+-d "products[1][price]=89" \
+-d "products[1][vat]=20" \
+-d "products[1][attributes]=1" \
+-d amount=44.5 \
+-d reference="7321834" \
+-d comment="Customer returned part of order"
+```
+
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "result": {
+ "creditAmount": 1097.5,
+ "depositAmount": 100,
+ "depositStatus": "PAID-BY-CARD",
+ "activatedAmount": 1197.5,
+ "activationStatus": "AWAITING-ACTIVATION",
+ "activations": [
+ {
+ "amount": 1197.5,
+ "comment": "Order was delivered to the customer by DHL",
+ "date": "2016-10-26 04:11",
+ "deliveryMethod": "delivery",
+ "reference": "9482471",
+ "status": "AWAITING-ACTIVATION",
+ "trackingNumber": "DHL291824419F"
+ }
+ ],
+ "cancellations": [],
+ "cancelledAmount": 0,
+ "id": "C8A05742F-3040-44EC-C252-050FD8869F79",
+ "lender": {
+ "app": "Demo",
+ "id": "L10F2BE8F-EF89-E403-E38F-8589ED2E51F5",
+ "name": "Demo"
+ },
+ "purchasePrice": 1197.5,
+ "refundedAmount": 44.5,
+ "refunds": [
+ {
+ "amount": 44.5,
+ "comment": "Customer returned part of order",
+ "date": "2016-10-26 04:14",
+ "reference": "7321834",
+ "status": "PENDING"
+ }
+ ],
+ "status": "AWAITING-ACTIVATION"
+ },
+ "status": "ok"
+}
+```
+
+
+#### Parameters
+
+`merchant` - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102 `
+```
+
+`application` - The application or proposal identifier. (*Required, String*)
+
+```
+Example `CAAC243AC-499A-84AF-DBBA-F58B9F7E798C`
+```
+
+`products['1']['sku']` - Product SKU (*Optional, String*)
+
+```
+Example `H10`
+```
+
+`products['1']['name']` - Product name/description (*Optional, String*)
+
+```
+Example `Restring Upgrade`
+```
+
+`products['1']['quantity']` - Product quantity (*Optional, String*)
+
+```
+Example `0.5`
+```
+
+`products['1']['price']` - Product price in same currency as proposal (*Optional, String*)
+
+```
+Example `89`
+```
+`products['1']['vat']` - Product VAT percentage (*Optional, String*)
+
+```
+Example `20`
+```
+
+`products['1']['attributes']` - Product attributes (1=Service,2=Shipping fee,3=Payment fee, 10=Price is without VAT) (*Optional, String*)
+
+```
+Example `1,2`
+```
+
+`amount` - Sum of the refunded items (*Optional, String*)
+
+```
+Example `44.5`
+```
+
+`reference` - Your reference to identify the refund (*Optional, String*)
+
+```
+Example `7321834 `
+```
+
+`comment` - Comment to the underwriter, can be order number or other information (*Optional, String*)
+
+```
+Example `Customer returned part of order`
+```
+
+
+
+List all applications
+------------------
+
+Returns a list of your applications. The applications are returned sorted by creation date, with the most recently created applications appearing first.
+
+#### Example Request
+ `GET` https://secure.divido.com/v1/applications?merchant={MERCHANT}&proposal={PROPOSAL}&status={STATUS}&page={PAGE} `HTTP/1.1`
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "itemsPerPage": 30,
+ "page": 1,
+ "records": [
+ {
+ "_activatableAmount": "£ 0",
+ "_activatedAmount": "£ 1197.50",
+ "_cancelableAmount": "£ 0",
+ "_cancelledAmount": "£ 0",
+ "_creditAmount": "£ 1197.50",
+ "_currentCreditAmount": "£ 1197.50",
+ "_depositAmount": "£ 0",
+ "_monthlyPaymentAmount": "£ 199.58",
+ "_purchasePrice": "£ 1197.50",
+ "_refundableAmount": "£ 1197.50",
+ "_refundedAmount": "£ 0",
+ "_totalRepayableAmount": "£ 1197.48",
+ "activatableAmount": 740,
+ "activatedAmount": 1197.5,
+ "activations": [
+ {
+ "_amount": "£ 1197.50",
+ "amount": 1197.5,
+ "comment": "",
+ "date": "2016-10-26 04:20",
+ "deliveryMethod": "delivery",
+ "reference": "9482471",
+ "trackingNumber": ""
+ }
+ ],
+ "agreementDuration": 6,
+ "cancelableAmount": 0,
+ "cancellations": [],
+ "cancelledAmount": 0,
+ "channel": {
+ "id": "CDDB70595-BFE6-0B7D-EE5B-B09FFC89F98C",
+ "name": "Webshop.com",
+ "type": "webshop"
+ },
+ "country": "GB",
+ "createdDate": "2016-10-26 04:18",
+ "creditAmount": 1197.5,
+ "currentCreditAmount": 1197.5,
+ "currency": "GBP",
+ "deferralPeriod": 0,
+ "depositAmount": 0,
+ "depositReference": "",
+ "depositStatus": "NO-DEPOSIT",
+ "directSign": true,
+ "email": "john.doe@domain.com",
+ "finance": {
+ "id": "F06895E17-EE96-926E-7137-37BCABB9DCF7",
+ "maxDeposit": 50,
+ "minAmount": 150,
+ "minDeposit": 0,
+ "text": "6 Month 0% Interest Free"
+ },
+ "firstName": "John",
+ "history": [
+ {
+ "date": "2016-10-26 04:20",
+ "status": "AWAITING-ACTIVATION",
+ "text": "",
+ "type": "status",
+ "user": "James Weston"
+ },
+ {
+ "date": "2016-10-26 04:18",
+ "status": "SIGNED",
+ "text": "",
+ "type": "status",
+ "user": ""
+ },
+ {
+ "date": "2016-10-26 04:18",
+ "status": "ACCEPTED",
+ "text": "",
+ "type": "status",
+ "user": ""
+ },
+ {
+ "date": "2016-10-26 04:18",
+ "status": "",
+ "text": "Customer entered gateway from 10.11.12.1",
+ "type": "",
+ "user": ""
+ }
+ ],
+ "id": "C92F7C65B-5C2D-6544-BB13-3E54243B9875",
+ "identityVerified": false,
+ "interestRate": 0,
+ "interestType": "simple",
+ "lastName": "Doe",
+ "lender": "Demo",
+ "lenderLoanReference": "XY111111",
+ "lenderReference": "x22acc2e-2dc4-2ec2-3a7f-x4c5f02a0c3a",
+ "metadata": {
+ "Invoice Number": "844001",
+ "Order Number": "100019"
+ },
+ "modifiedDate": "2016-10-26 04:20",
+ "monthlyPaymentAmount": 199.58,
+ "products": [
+ {
+ "_price": "£ 1153",
+ "_sum": "£ 1153",
+ "image": "http://www.webshop.com/images/GIB100.png",
+ "name": "Gibson Les Paul Studio Raw Guitar",
+ "price": "1153.00",
+ "quantity": 1,
+ "sku": "GIB100",
+ "sum": "1153.00",
+ "unit": "pcs"
+ },
+ {
+ "_price": "£ 89",
+ "_sum": "£ 44.50",
+ "image": "",
+ "name": "Restring Upgrade",
+ "price": "89.00",
+ "quantity": 0.5,
+ "sku": "H10",
+ "sum": "44.50",
+ "unit": "hour"
+ }
+ ],
+ "proposal": "PD56030F0-845C-ECF1-6118-0B26EFDCB273",
+ "proposalCreator": null,
+ "purchasePrice": 1197.5,
+ "reference": "test reference",
+ "refundableAmount": 1197.50,
+ "refundedAmount": 0,
+ "refunds": [],
+ "status": "AWAITING-ACTIVATION",
+ "totalRepayableAmount": 1197.5,
+ "url": "https:\/\/secure.divido.com\/token\/0685cx87225604f0b75f53c6b6afe71x"
+ },
+ {
+ ...
+ },
+ {
+ ...
+ },
+ {
+ ...
+ }
+ ],
+ "status": "ok",
+ "totalItems": 4
+}
+```
+
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`country` - Filter by country code (*Optional, String*)
+
+```
+Example `GB`
+```
+
+`status` - Filter by status (*Optional, String*)
+
+```
+Example `SIGNED`
+```
+
+`proposal` - Filter by proposal (*Optional, String*)
+
+```
+Example `PAA717844-EE9D-78AF-D11C-EDCC1D180F87`
+```
+
+`page` - Show page, default 1 (*Optional, String*)
+
+```
+Example `2`
+```
+
+Retrieve an applications
+------------------
+
+Retrieves the details of an existing application. Supply the application ID and the API will return the corresponding application.
+
+#### Example Request
+ `GET` https://secure.divido.com/v1/applications?merchant={MERCHANT}&id={id} `HTTP/1.1`
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "record": {
+ "_activatableAmount": "£ 0",
+ "_activatedAmount": "£ 1197.50",
+ "_cancelableAmount": "£ 0",
+ "_cancelledAmount": "£ 0",
+ "_creditAmount": "£ 1197.50",
+ "_currentCreditAmount": "£ 1197.50",
+ "_depositAmount": "£ 0",
+ "_monthlyPaymentAmount": "£ 199.58",
+ "_purchasePrice": "£ 1197.50",
+ "_refundableAmount": "£ 1197.50",
+ "_refundedAmount": "£ 0",
+ "_totalRepayableAmount": "£ 1197.48",
+ "activatableAmount": 740,
+ "activatedAmount": 1197.5,
+ "activations": [
+ {
+ "_amount": "£ 1197.50",
+ "amount": 1197.5,
+ "comment": "",
+ "date": "2016-10-26 04:20",
+ "deliveryMethod": "delivery",
+ "reference": "9482471",
+ "trackingNumber": ""
+ }
+ ],
+ "agreementDuration": 6,
+ "cancelableAmount": 0,
+ "cancellations": [],
+ "cancelledAmount": 0,
+ "channel": {
+ "id": "CDDB70595-BFE6-0B7D-EE5B-B09FFC89F98C",
+ "name": "Webshop.com",
+ "type": "webshop"
+ },
+ "country": "GB",
+ "createdDate": "2016-10-26 04:18",
+ "creditAmount": 1197.5,
+ "currentCreditAmount": 1197.5,
+ "currency": "GBP",
+ "deferralPeriod": 0,
+ "depositAmount": 0,
+ "depositReference": "",
+ "depositStatus": "NO-DEPOSIT",
+ "directSign": true,
+ "email": "john.doe@domain.com",
+ "finance": {
+ "id": "F06895E17-EE96-926E-7137-37BCABB9DCF7",
+ "maxDeposit": 50,
+ "minAmount": 150,
+ "minDeposit": 0,
+ "text": "6 Month 0% Interest Free"
+ },
+ "firstName": "John",
+ "history": [
+ {
+ "date": "2016-10-26 04:20",
+ "status": "AWAITING-ACTIVATION",
+ "text": "",
+ "type": "status",
+ "user": "James Weston"
+ },
+ {
+ "date": "2016-10-26 04:18",
+ "status": "SIGNED",
+ "text": "",
+ "type": "status",
+ "user": ""
+ },
+ {
+ "date": "2016-10-26 04:18",
+ "status": "ACCEPTED",
+ "text": "",
+ "type": "status",
+ "user": ""
+ },
+ {
+ "date": "2016-10-26 04:18",
+ "status": "",
+ "text": "Customer entered gateway from 10.11.12.1",
+ "type": "",
+ "user": ""
+ }
+ ],
+ "id": "C92F7C65B-5C2D-6544-BB13-3E54243B9875",
+ "identityVerified": false,
+ "interestRate": 0,
+ "interestType": "simple",
+ "lastName": "Doe",
+ "lender": "Demo",
+ "lenderLoanReference": "XY111111",
+ "lenderReference": "",
+ "metadata": {
+ "Invoice Number": "844001",
+ "Order Number": "100019"
+ },
+ "modifiedDate": "2016-10-26 04:20",
+ "monthlyPaymentAmount": 199.58,
+ "products": [
+ {
+ "_price": "£ 1153",
+ "_sum": "£ 1153",
+ "image": "http://www.webshop.com/images/GIB100.png",
+ "name": "Gibson Les Paul Studio Raw Guitar",
+ "price": "1153.00",
+ "quantity": 1,
+ "sku": "GIB100",
+ "sum": "1153.00",
+ "unit": "pcs"
+ },
+ {
+ "_price": "£ 89",
+ "_sum": "£ 44.50",
+ "image": "",
+ "name": "Restring Upgrade",
+ "price": "89.00",
+ "quantity": 0.5,
+ "sku": "H10",
+ "sum": "44.50",
+ "unit": "hour"
+ }
+ ],
+ "proposal": "PD56030F0-845C-ECF1-6118-0B26EFDCB273",
+ "proposalCreator": null,
+ "purchasePrice": 1197.5,
+ "reference": "test reference",
+ "refundableAmount": 1197.50,
+ "refundedAmount": 0,
+ "refunds": [],
+ "status": "AWAITING-ACTIVATION",
+ "totalRepayableAmount": 1197.5,
+ "url": "https:\/\/secure.divido.com\/token\/0685cx87225604f0b75f53c6b6afe71x"
+ },
+ "status": "ok"
+}
+```
+
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`id` - Application id (*Required, String*)
+
+```
+Example `C84047A6D-89B2-FECF-D2B4-168444F5178C`
+```
+
+Reporting / List all payment batches
+------------------
+
+Retrieves all payment batches.
+
+#### Example Request
+ `GET` https://secure.divido.com/v1/payments?merchant={MERCHANT}&currency={CURRENCY}&lender={LENDER}&page={PAGE} `HTTP/1.1`
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "itemsPerPage": 30,
+ "page": 1,
+ "records": [
+ {
+ "currency": "GBP",
+ "date": "2016-04-14",
+ "id": "PB0506EBA-870B-FFC2-FCAB-250D1B1291BD",
+ "lender": {
+ "id": "L07F46CDF-5296-D190-1F2D-A1B5FD869B72",
+ "name": "Demo"
+ },
+ "merchant": {
+ "id": "M7470B82C-B1EE-158F-D965-CFFD3158992A",
+ "name": "Sofa & Table"
+ },
+ "records": 1,
+ "totalCreditAmount": 989,
+ "totalNetPayment": 1074.165,
+ "totalSubsidyAmount": 4.945
+ },
+ ...,
+ ...
+ ],
+ "status": "ok",
+ "totalItems": 3
+}
+```
+
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`currency` - Filter by currency code (*Optional, String*)
+
+```
+Example `GBP`
+```
+
+`lender` - Filter by lender ID (*Optional, String*)
+
+```
+Example `L07F46CDF-5296-D190-1F2D-A1B5FD869B72 `
+```
+
+`page` - Show page, default 1 (*Optional, String*)
+
+```
+Example `2`
+```
+
+Reporting / Retrieve records from a payment batch
+------------------
+
+Retrieves the content of a payment batch. Supply the batch ID and the API will return all records.
+
+#### Example Request
+ `GET` https://secure.divido.com/v1/payments?merchant={MERCHANT}&id={id} `HTTP/1.1`
+
+#### Example Response
+
+JSON example
+
+``` json
+{
+ "record": {
+ "currency": "GBP",
+ "date": "2016-04-14",
+ "id": "PB0506EBA-870B-FFC2-FCAB-250D1B1291BD",
+ "lender": {
+ "id": "L07F46CDF-5296-D190-1F2D-A1B5FD869B72",
+ "name": "Demo"
+ },
+ "totalCreditAmount": 989,
+ "totalNetPayment": 1074.165,
+ "totalSubsidyAmount": 4.945,
+ "transactions": [
+ {
+ "application": "CDD6CCE0C-8DC5-6EB4-9A08-45520484EB19",
+ "creditAmount": 989,
+ "customer": "HESELDEN, ANN",
+ "depositAmount": 100,
+ "finance": {
+ "id": "F927FA596-6C9C-8376-A99B-70AE9A020F6B",
+ "text": "0% 12 month - Demo Bank"
+ },
+ "netPaymentAmount": 1074.165,
+ "purchasePrice": 1089,
+ "reference": "267381",
+ "subsidyAmount": 4.945
+ }
+ ]
+ },
+ "status": "ok"
+}
+```
+
+
+#### Parameters
+
+`merchant`
+ - Your unique account identifier (*Required, String*)
+
+```
+Example `live_c31be25be.fb2ee4bc8a66e1ecd797c56f03621102`
+```
+
+`id` - Batch id (*Required, String*)
+
+```
+Example `PB0506EBA-870B-FFC2-FCAB-250D1B1291BD `
+```
diff --git a/public/system/storage/vendor/divido/divido-php/composer.json b/public/system/storage/vendor/divido/divido-php/composer.json
new file mode 100644
index 0000000..07e8ad1
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/composer.json
@@ -0,0 +1,30 @@
+{
+ "name": "divido/divido-php",
+ "description": "Divido PHP library",
+ "keywords": [
+ "divido",
+ "payment processing",
+ "instalments",
+ "finance",
+ "api"
+ ],
+ "homepage": "https://www.divido.com/",
+ "license": "MIT",
+ "type": "library",
+ "require": {
+ "php": ">=5.2.0",
+ "ext-curl": "*"
+ },
+ "autoload": {
+ "psr-0": {
+ "Divido":"lib"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "master":"2.0-dev",
+ "v1.1.1":"1.1.1-dev"
+ }
+ },
+ "minimum-stability": "dev"
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido.php b/public/system/storage/vendor/divido/divido-php/lib/Divido.php
new file mode 100644
index 0000000..2b533ce
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido.php
@@ -0,0 +1,45 @@
+<?php
+if (!function_exists('curl_init')) {
+ throw new Exception('Divido needs the CURL PHP extension.');
+}
+if (!function_exists('json_decode')) {
+ throw new Exception('Divido needs the JSON PHP extension.');
+}
+if (!function_exists('mb_detect_encoding')) {
+ throw new Exception('Divido needs the Multibyte String PHP extension.');
+}
+
+// Divido singleton
+require_once(dirname(__FILE__) . '/Divido/Divido.php');
+
+// Utilities
+require_once(dirname(__FILE__) . '/Divido/Util.php');
+require_once(dirname(__FILE__) . '/Divido/Util/Set.php');
+
+// Errors
+require_once(dirname(__FILE__) . '/Divido/Error.php');
+require_once(dirname(__FILE__) . '/Divido/ApiError.php');
+require_once(dirname(__FILE__) . '/Divido/ApiConnectionError.php');
+require_once(dirname(__FILE__) . '/Divido/AuthenticationError.php');
+require_once(dirname(__FILE__) . '/Divido/PaymentError.php');
+require_once(dirname(__FILE__) . '/Divido/InvalidRequestError.php');
+require_once(dirname(__FILE__) . '/Divido/RateLimitError.php');
+
+// Plumbing
+require_once(dirname(__FILE__) . '/Divido/Object.php');
+require_once(dirname(__FILE__) . '/Divido/ApiRequestor.php');
+require_once(dirname(__FILE__) . '/Divido/ApiResource.php');
+require_once(dirname(__FILE__) . '/Divido/SingletonApiResource.php');
+require_once(dirname(__FILE__) . '/Divido/AttachedObject.php');
+require_once(dirname(__FILE__) . '/Divido/List.php');
+
+// Divido API Resources
+require_once(dirname(__FILE__) . '/Divido/SendApplication.php');
+require_once(dirname(__FILE__) . '/Divido/CreditRequest.php');
+require_once(dirname(__FILE__) . '/Divido/DealCalculator.php');
+require_once(dirname(__FILE__) . '/Divido/Finances.php');
+require_once(dirname(__FILE__) . '/Divido/Comments.php');
+require_once(dirname(__FILE__) . '/Divido/Activation.php');
+require_once(dirname(__FILE__) . '/Divido/Refund.php');
+require_once(dirname(__FILE__) . '/Divido/Fulfillment.php');
+require_once(dirname(__FILE__) . '/Divido/Cancellation.php'); \ No newline at end of file
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Activation.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Activation.php
new file mode 100644
index 0000000..b75499c
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Activation.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_Activation extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Activation
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Activation.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Activate
+ */
+ public static function activate($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedActivateRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Activation The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiConnectionError.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiConnectionError.php
new file mode 100644
index 0000000..4e7b092
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiConnectionError.php
@@ -0,0 +1,5 @@
+<?php
+
+class Divido_ApiConnectionError extends Divido_Error
+{
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiError.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiError.php
new file mode 100644
index 0000000..fb1ea91
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiError.php
@@ -0,0 +1,5 @@
+<?php
+
+class Divido_ApiError extends Divido_Error
+{
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiRequestor.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiRequestor.php
new file mode 100644
index 0000000..350fc52
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiRequestor.php
@@ -0,0 +1,475 @@
+<?php
+
+class Divido_ApiRequestor
+{
+ /**
+ * @var string $apiKey The API key that's to be used to make requests.
+ */
+ public $apiKey;
+
+ private static $_preFlight;
+
+ private static function blacklistedCerts()
+ {
+ return array(
+ '05c0b3643694470a888c6e7feb5c9e24e823dc53',
+ '5b7dc7fbc98d78bf76d4d4fa6f597a0c901fad5c',
+ );
+ }
+
+ public function __construct($apiKey = null, $sharedSecret = null)
+ {
+ $this->_apiKey = $apiKey;
+ $this->_sharedSecret = $sharedSecret;
+ }
+
+ /**
+ * @param string $url The path to the API endpoint.
+ *
+ * @returns string The full path.
+ */
+ public static function apiUrl($url = '')
+ {
+ $apiBase = Divido::$apiBase;
+ return "$apiBase$url";
+ }
+
+ /**
+ * @param string|mixed $value A string to UTF8-encode.
+ *
+ * @returns string|mixed The UTF8-encoded string, or the object passed in if
+ * it wasn't a string.
+ */
+ public static function utf8($value)
+ {
+ if (is_string($value)
+ && mb_detect_encoding($value, "UTF-8", true) != "UTF-8") {
+ return utf8_encode($value);
+ } else {
+ return $value;
+ }
+ }
+
+ private static function _encodeObjects($d)
+ {
+ if ($d instanceof Divido_ApiResource) {
+ return self::utf8($d->id);
+ } else if ($d === true) {
+ return 'true';
+ } else if ($d === false) {
+ return 'false';
+ } else if (is_array($d)) {
+ $res = array();
+ foreach ($d as $k => $v) {
+ $res[$k] = self::_encodeObjects($v);
+ }
+
+ return $res;
+ } else {
+ return self::utf8($d);
+ }
+ }
+
+ /**
+ * @param array $arr An map of param keys to values.
+ * @param string|null $prefix (It doesn't look like we ever use $prefix...)
+ *
+ * @returns string A querystring, essentially.
+ */
+ public static function encode($arr, $prefix = null)
+ {
+ if (!is_array($arr)) {
+ return $arr;
+ }
+
+ $r = array();
+ foreach ($arr as $k => $v) {
+ if (is_null($v)) {
+ continue;
+ }
+
+ if ($prefix && $k && !is_int($k)) {
+ $k = $prefix . "[" . $k . "]";
+ } else if ($prefix) {
+ $k = $prefix . "[]";
+ }
+
+ if (is_array($v)) {
+ $r[] = self::encode($v, $k, true);
+ } else {
+ $r[] = urlencode($k) . "=" . urlencode($v);
+ }
+ }
+
+ return implode("&", $r);
+ }
+
+ /**
+ * @param string $method
+ * @param string $url
+ * @param array|null $params
+ *
+ * @return array An array whose first element is the response and second
+ * element is the API key used to make the request.
+ */
+ public function request($method, $url, $params = null)
+ {
+ if (!$params) {
+ $params = array();
+ }
+
+ list($rbody, $rcode, $myApiKey) = $this->_requestRaw($method, $url, $params);
+
+ $resp = $this->_interpretResponse($rbody, $rcode);
+ return array($resp, $myApiKey);
+ }
+
+ /**
+ * @param string $rbody A JSON string.
+ * @param int $rcode
+ * @param array $resp
+ *
+ * @throws Divido_InvalidRequestError if the error is caused by the user.
+ * @throws Divido_AuthenticationError if the error is caused by a lack of
+ * permissions.
+ * @throws Divido_PaymentError if the error is the error code is 402 (payment
+ * required)
+ * @throws Divido_ApiError otherwise.
+ */
+ public function handleApiError($rbody, $rcode, $resp)
+ {
+ if (!is_array($resp) || !isset($resp['error'])) {
+ $msg = "Invalid response object from API: $rbody "
+ . "(HTTP response code was $rcode)";
+ throw new Divido_ApiError($msg, $rcode, $rbody, $resp);
+ }
+
+ $error = $resp['error'];
+ $msg = isset($error['message']) ? $error['message'] : null;
+ $param = isset($error['param']) ? $error['param'] : null;
+ $code = isset($error['code']) ? $error['code'] : null;
+
+ switch ($rcode) {
+ case 400:
+ if ($code == 'rate_limit') {
+ throw new Divido_RateLimitError(
+ $msg, $param, $rcode, $rbody, $resp
+ );
+ }
+ case 404:
+ throw new Divido_InvalidRequestError(
+ $msg, $param, $rcode, $rbody, $resp
+ );
+ case 401:
+ throw new Divido_AuthenticationError($msg, $rcode, $rbody, $resp);
+ case 402:
+ throw new Divido_PaymentError($msg, $param, $code, $rcode, $rbody, $resp);
+ default:
+ throw new Divido_ApiError($msg, $rcode, $rbody, $resp);
+ }
+ }
+
+ private function _requestRaw($method, $url, $params)
+ {
+ $myApiKey = $this->_apiKey;
+ if (!$myApiKey) {
+ $myApiKey = Divido::$apiKey;
+ }
+
+ $sharedSecret = $this->_sharedSecret;
+ if (!$sharedSecret) {
+ $sharedSecret = Divido::$sharedSecret;
+ }
+
+ if (!$myApiKey) {
+ $msg = 'No API key provided. (HINT: set your API key using '
+ . '"Divido::setApiKey(<API-KEY>)". You can generate API keys from '
+ . 'the Divido web interface. See http://docs.divido.com/api for '
+ . 'details, or email support@divido.com if you have any questions.';
+ throw new Divido_AuthenticationError($msg);
+ }
+
+ $absUrl = $this->apiUrl($url);
+ $params = self::_encodeObjects($params);
+ $langVersion = phpversion();
+ $uname = php_uname();
+ $ua = array(
+ 'bindings_version' => Divido::VERSION,
+ 'lang' => 'php',
+ 'lang_version' => $langVersion,
+ 'publisher' => 'divido',
+ 'uname' => $uname,
+ );
+
+ $headers = array(
+ 'X-Divido-Client-User-Agent: ' . json_encode($ua),
+ 'User-Agent: Divido/v1 PhpBindings/' . Divido::VERSION,
+ 'Authorization: Bearer ' . $myApiKey,
+ 'Content-Type: application/x-www-form-urlencoded',
+ );
+
+ if (!empty($sharedSecret)) {
+ $queryString = http_build_query($params);
+ $string = (strlen($queryString)) ? $url . "?" . $queryString : $url;
+ $hmac = base64_encode(hash_hmac('sha256', $string, $sharedSecret, true));
+
+ $headers[] = 'X-DIVIDO-HMAC-SHA256: ' . $hmac;
+ }
+
+ if (Divido::$apiVersion) {
+ $headers[] = 'Divido-Version: ' . Divido::$apiVersion;
+ }
+ list($rbody, $rcode) = $this->_curlRequest(
+ $method,
+ $absUrl,
+ $headers,
+ $params
+ );
+ return array($rbody, $rcode, $myApiKey);
+ }
+
+ private function _interpretResponse($rbody, $rcode)
+ {
+ try {
+ $resp = json_decode($rbody, true);
+ } catch (Exception $e) {
+ $msg = "Invalid response body from API: $rbody "
+ . "(HTTP response code was $rcode)";
+ throw new Divido_ApiError($msg, $rcode, $rbody);
+ }
+
+ if ($rcode < 200 || $rcode >= 300) {
+ $this->handleApiError($rbody, $rcode, $resp);
+ }
+ return $resp;
+ }
+
+ private function _curlRequest($method, $absUrl, $headers, $params)
+ {
+
+ if (!self::$_preFlight) {
+ self::$_preFlight = $this->checkSslCert($this->apiUrl());
+ }
+
+ /*
+ $myApiKey = $this->_apiKey;
+ if (!$myApiKey)
+ $myApiKey = Divido::$apiKey;
+
+ if (!isset($params['merchant'])) {
+ $params['merchant'] = $myApiKey;
+ }
+ */
+
+ $curl = curl_init();
+ $method = strtolower($method);
+ $opts = array();
+
+ if ($method == 'get') {
+ $opts[CURLOPT_HTTPGET] = 1;
+ if (count($params) > 0) {
+ $encoded = self::encode($params);
+ $absUrl = "$absUrl?$encoded";
+ }
+ } else if ($method == 'post') {
+ $opts[CURLOPT_POST] = 1;
+ //$opts[CURLOPT_POSTFIELDS] = self::encode($params);
+ $opts[CURLOPT_POSTFIELDS] = http_build_query($params);
+ } else if ($method == 'delete') {
+ $opts[CURLOPT_CUSTOMREQUEST] = 'DELETE';
+ if (count($params) > 0) {
+ $encoded = self::encode($params);
+ $absUrl = "$absUrl?$encoded";
+ }
+ } else {
+ throw new Divido_ApiError("Unrecognized method $method");
+ }
+
+ $absUrl = self::utf8($absUrl);
+ // print "absUrl: ".$absUrl."<br />";
+ $opts[CURLOPT_URL] = $absUrl;
+
+ /*
+ if (isset($myApiKey)) {
+ // $opts[CURLOPT_USERPWD] = $params['merchant'].":";
+ curl_setopt($curl,CURLOPT_USERPWD,$myApiKey.":");
+ }
+ */
+ $opts[CURLOPT_RETURNTRANSFER] = true;
+ $opts[CURLOPT_CONNECTTIMEOUT] = 30;
+ $opts[CURLOPT_TIMEOUT] = 80;
+ $opts[CURLOPT_RETURNTRANSFER] = true;
+ $opts[CURLOPT_HTTPHEADER] = $headers;
+ if (!Divido::$verifySslCerts) {
+ $opts[CURLOPT_SSL_VERIFYPEER] = false;
+ }
+
+ curl_setopt_array($curl, $opts);
+ $rbody = curl_exec($curl);
+
+ // print_r($params);exit;
+ // print "url: ".$absUrl;Exit;
+ // print "rbody: " . $rbody;exit;
+
+ if (!defined('CURLE_SSL_CACERT_BADFILE')) {
+ define('CURLE_SSL_CACERT_BADFILE', 77); // constant not defined in PHP
+ }
+
+ $errno = curl_errno($curl);
+ if ($errno == CURLE_SSL_CACERT ||
+ $errno == CURLE_SSL_PEER_CERTIFICATE ||
+ $errno == CURLE_SSL_CACERT_BADFILE) {
+ array_push(
+ $headers,
+ 'X-Divido-Client-Info: {"ca":"using Divido-supplied CA bundle"}'
+ );
+ $cert = $this->caBundle();
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_CAINFO, $cert);
+ $rbody = curl_exec($curl);
+ }
+
+ if ($rbody === false) {
+ $errno = curl_errno($curl);
+ $message = curl_error($curl);
+ curl_close($curl);
+ $this->handleCurlError($errno, $message);
+ }
+
+ $rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ curl_close($curl);
+ return array($rbody, $rcode);
+ }
+
+ /**
+ * @param number $errno
+ * @param string $message
+ * @throws Divido_ApiConnectionError
+ */
+ public function handleCurlError($errno, $message)
+ {
+ $apiBase = Divido::$apiBase;
+ switch ($errno) {
+ case CURLE_COULDNT_CONNECT:
+ case CURLE_COULDNT_RESOLVE_HOST:
+ case CURLE_OPERATION_TIMEOUTED:
+ $msg = "Could not connect to Divido ($apiBase). Please check your "
+ . "internet connection and try again. If this problem persists, "
+ . "you should check Divido's service status at "
+ . "https://twitter.com/dividostatus, or";
+ break;
+ case CURLE_SSL_CACERT:
+ case CURLE_SSL_PEER_CERTIFICATE:
+ $msg = "Could not verify Divido's SSL certificate. Please make sure "
+ . "that your network is not intercepting certificates. "
+ . "(Try going to $apiBase in your browser.) "
+ . "If this problem persists,";
+ break;
+ default:
+ $msg = "Unexpected error communicating with Divido. "
+ . "If this problem persists,";
+ }
+ $msg .= " let us know at support@divido.com.";
+
+ $msg .= "\n\n(Network error [errno $errno]: $message)";
+ throw new Divido_ApiConnectionError($msg);
+ }
+
+ /**
+ * Preflight the SSL certificate presented by the backend. This isn't 100%
+ * bulletproof, in that we're not actually validating the transport used to
+ * communicate with Divido, merely that the first attempt to does not use a
+ * revoked certificate.
+ *
+ * Unfortunately the interface to OpenSSL doesn't make it easy to check the
+ * certificate before sending potentially sensitive data on the wire. This
+ * approach raises the bar for an attacker significantly.
+ */
+ private function checkSslCert($url)
+ {
+
+ return true;
+
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+ error_log(
+ 'Warning: This version of PHP is too old to check SSL certificates ' .
+ 'correctly. Divido cannot guarantee that the server has a ' .
+ 'certificate which is not blacklisted'
+ );
+ return true;
+ }
+
+ if (strpos(PHP_VERSION, 'hiphop') !== false) {
+ error_log(
+ 'Warning: HHVM does not support Divido\'s SSL certificate ' .
+ 'verification. (See http://docs.hhvm.com/manual/en/context.ssl.php) ' .
+ 'Divido cannot guarantee that the server has a certificate which is ' .
+ 'not blacklisted'
+ );
+ return true;
+ }
+
+ $url = parse_url($url);
+ $port = isset($url["port"]) ? $url["port"] : 443;
+ $url = "ssl://{$url["host"]}:{$port}";
+
+ $sslContext = stream_context_create(
+ array('ssl' => array(
+ 'capture_peer_cert' => true,
+ 'verify_peer' => true,
+ 'cafile' => $this->caBundle(),
+ ))
+ );
+ $result = stream_socket_client(
+ $url, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $sslContext
+ );
+ if ($errno !== 0) {
+ $apiBase = Divido::$apiBase;
+ throw new Divido_ApiConnectionError(
+ 'Could not connect to Divido (' . $apiBase . '). Please check your ' .
+ 'internet connection and try again. If this problem persists, ' .
+ 'you should check Divido\'s service status at ' .
+ 'https://twitter.com/dividostatus. Reason was: ' . $errstr
+ );
+ }
+
+ $params = stream_context_get_params($result);
+
+ $cert = $params['options']['ssl']['peer_certificate'];
+
+ openssl_x509_export($cert, $pemCert);
+
+ if (self::isBlackListed($pemCert)) {
+ throw new Divido_ApiConnectionError(
+ 'Invalid server certificate. You tried to connect to a server that ' .
+ 'has a revoked SSL certificate, which means we cannot securely send ' .
+ 'data to that server. Please email support@divido.com if you need ' .
+ 'help connecting to the correct API server.'
+ );
+ }
+
+ return true;
+ }
+
+ /* Checks if a valid PEM encoded certificate is blacklisted
+ * @return boolean
+ */
+ public static function isBlackListed($certificate)
+ {
+ $certificate = trim($certificate);
+ $lines = explode("\n", $certificate);
+
+ // Kludgily remove the PEM padding
+ array_shift($lines);
+ array_pop($lines);
+
+ $derCert = base64_decode(implode("", $lines));
+ $fingerprint = sha1($derCert);
+ return in_array($fingerprint, self::blacklistedCerts());
+ }
+
+ private function caBundle()
+ {
+ return dirname(__FILE__) . '/../data/ca-certificates.crt';
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiResource.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiResource.php
new file mode 100644
index 0000000..6241ac1
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/ApiResource.php
@@ -0,0 +1,218 @@
+<?php
+
+abstract class Divido_ApiResource extends Divido_Object
+{
+ protected static function _scopedRetrieve($class, $id, $apiKey=null)
+ {
+ $instance = new $class($id, $apiKey);
+ $instance->refresh();
+ return $instance;
+ }
+
+ /**
+ * @returns Divido_ApiResource The refreshed resource.
+ */
+ public function refresh()
+ {
+ $requestor = new Divido_ApiRequestor($this->_apiKey);
+ $url = $this->instanceUrl();
+
+ list($response, $apiKey) = $requestor->request(
+ 'get',
+ $url,
+ $this->_retrieveOptions
+ );
+ $this->refreshFrom($response, $apiKey);
+ return $this;
+ }
+
+ /**
+ * @param string $class
+ *
+ * @returns string The name of the class, with namespacing and underscores
+ * stripped.
+ */
+ public static function className($class)
+ {
+ // Useful for namespaces: Foo\Divido_Charge
+ if ($postfixNamespaces = strrchr($class, '\\')) {
+ $class = substr($postfixNamespaces, 1);
+ }
+ // Useful for underscored 'namespaces': Foo_Divido_Charge
+ if ($postfixFakeNamespaces = strrchr($class, 'Divido_')) {
+ $class = $postfixFakeNamespaces;
+ }
+ if (substr($class, 0, strlen('Divido')) == 'Divido') {
+ $class = substr($class, strlen('Divido'));
+ }
+ $class = str_replace('_', '', $class);
+ $name = urlencode($class);
+
+ $name = strtolower($name);
+ return $name;
+ }
+
+ /**
+ * @param string $class
+ *
+ * @returns string The endpoint URL for the given class.
+ */
+ public static function classUrl($class)
+ {
+ $base = self::_scopedLsb($class, 'className', $class);
+ return "/v1/${base}";
+ }
+
+ /**
+ * @returns string The full API URL for this API resource.
+ */
+ public function instanceUrl()
+ {
+ $id = $this['id'];
+ $class = get_class($this);
+ if ($id === null) {
+ $message = "Could not determine which URL to request: "
+ . "$class instance has invalid ID: $id";
+ throw new Divido_InvalidRequestError($message, null);
+ }
+ $id = Divido_ApiRequestor::utf8($id);
+ $base = $this->_lsb('classUrl', $class);
+ $extn = urlencode($id);
+ return "$base/$extn";
+ }
+
+ private static function _validateCall($method, $params=null, $apiKey=null)
+ {
+ if ($params && !is_array($params)) {
+ $message = "You must pass an array as the first argument to Divido API "
+ . "method calls. (HINT: an example call to create a charge "
+ . "would be: \"DividoCharge::create(array('amount' => 100, "
+ . "'currency' => 'usd', 'card' => array('number' => "
+ . "4242424242424242, 'exp_month' => 5, 'exp_year' => 2015)))\")";
+ throw new Divido_Error($message);
+ }
+
+ if ($apiKey && !is_string($apiKey)) {
+ $message = 'The second argument to Divido API method calls is an '
+ . 'optional per-request apiKey, which must be a string. '
+ . '(HINT: you can set a global apiKey by '
+ . '"Divido::setApiKey(<apiKey>)")';
+ throw new Divido_Error($message);
+ }
+ }
+
+ protected static function _scopedAll($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('all', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('get', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedSendApplicationRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('sendApplicationRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedCreditRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('creditRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedFinalizeRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('finalizeRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ $url = $url."/finalize";
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedFulfillRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('fulfillRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedActivateRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('activateRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedCancellationRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('cancelRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedRefundRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('refundRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedCommentRequest($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('commentRequest', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected static function _scopedCreate($class, $params=null, $apiKey=null)
+ {
+ self::_validateCall('create', $params, $apiKey);
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $url = self::_scopedLsb($class, 'classUrl', $class);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ protected function _scopedSave($class, $apiKey=null)
+ {
+ self::_validateCall('save');
+ $requestor = new Divido_ApiRequestor($apiKey);
+ $params = $this->serializeParameters();
+
+ if (count($params) > 0) {
+ $url = $this->instanceUrl();
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ $this->refreshFrom($response, $apiKey);
+ }
+ return $this;
+ }
+
+ protected function _scopedDelete($class, $params=null)
+ {
+ self::_validateCall('delete');
+ $requestor = new Divido_ApiRequestor($this->_apiKey);
+ $url = $this->instanceUrl();
+ list($response, $apiKey) = $requestor->request('delete', $url, $params);
+ $this->refreshFrom($response, $apiKey);
+ return $this;
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/AttachedObject.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/AttachedObject.php
new file mode 100644
index 0000000..c1f56fc
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/AttachedObject.php
@@ -0,0 +1,23 @@
+<?php
+
+// e.g. metadata on Divido objects.
+class Divido_AttachedObject extends Divido_Object
+{
+ /**
+ * Updates this object.
+ *
+ * @param array $properties A mapping of properties to update on this object.
+ */
+ public function replaceWith($properties)
+ {
+ $removed = array_diff(array_keys($this->_values), array_keys($properties));
+ // Don't unset, but rather set to null so we send up '' for deletion.
+ foreach ($removed as $k) {
+ $this->$k = null;
+ }
+
+ foreach ($properties as $k => $v) {
+ $this->$k = $v;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/AuthenticationError.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/AuthenticationError.php
new file mode 100644
index 0000000..0c2602d
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/AuthenticationError.php
@@ -0,0 +1,5 @@
+<?php
+
+class Divido_AuthenticationError extends Divido_Error
+{
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Cancellation.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Cancellation.php
new file mode 100644
index 0000000..7d54c6f
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Cancellation.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_Cancellation extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Cancellation
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Cancellation.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Charge The created charge.
+ */
+ public static function cancel($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedCancellationRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Cancellation The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Comments.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Comments.php
new file mode 100644
index 0000000..f9777f1
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Comments.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_Comments extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Fulfillment
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Fulfillment.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Comment The created charge.
+ */
+ public static function create($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedCommentRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Fulfillment The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/CreditRequest.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/CreditRequest.php
new file mode 100644
index 0000000..e84c22d
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/CreditRequest.php
@@ -0,0 +1,62 @@
+<?php
+
+class Divido_CreditRequest extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Charge
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Charges.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Charge The created credit request.
+ */
+ public static function create($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedCreditRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Finalize The created charge.
+ */
+ public static function finalize($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedFinalizeRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Charge The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/DealCalculator.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/DealCalculator.php
new file mode 100644
index 0000000..7050d42
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/DealCalculator.php
@@ -0,0 +1,49 @@
+<?php
+
+class Divido_DealCalculator extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_DealCalcuator
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Charges.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Charge The created charge.
+ */
+ public static function create($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedCreditRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Charge The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Divido.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Divido.php
new file mode 100644
index 0000000..154446a
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Divido.php
@@ -0,0 +1,185 @@
+<?php
+
+abstract class Divido
+{
+ /**
+ * @var string The Divido Mercahnt to be used for requests.
+ */
+ public static $merchant;
+
+ /**
+ * @var string The Divido API key to be used for requests.
+ */
+ public static $apiKey;
+
+ /**
+ * @var string The Divido shared secdret to be used for requests.
+ */
+ public static $sharedSecret;
+
+ /**
+ * @var string The Divido API key to be used for requests.
+ */
+ public static $sandboxMode;
+
+ /**
+ * @var string The base URL for the Divido API.
+ */
+ public static $apiBase = 'https://secure.divido.com';
+
+ /**
+ * @var string The base URL for the Divido API.
+ */
+ public static $devApiBase = 'https://platform.api.dev.divido.net';
+
+ /**
+ * @var string The base URL for the Divido API.
+ */
+ public static $sandboxApiBase = 'https://secure.sandbox.divido.com';
+
+ /**
+ * @var string The base URL for the Divido API.
+ */
+ public static $stagingApiBase = 'https://secure.staging.divido.com';
+
+ /**
+ * @var string The base URL for the Divido API.
+ */
+ public static $testingApiBase = 'https://secure.test.divido.com';
+
+ /**
+ * @var string The base URL for the Divido API.
+ */
+ public static $dockerApiBase = 'https://platform.api.dev.divido.net';
+
+ /**
+ * @var string|null The version of the Divido API to use for requests.
+ */
+ public static $apiVersion = null;
+ /**
+ * @var boolean Defaults to true.
+ */
+ public static $verifySslCerts = false;
+ const VERSION = '0.1';
+
+ /**
+ * @return string The API key used for requests.
+ */
+ public static function getMerchant()
+ {
+ return self::$apiKey;
+ }
+
+ /**
+ * Sets the API key to be used for requests.
+ *
+ * @param string $merchant
+ */
+ public static function setMerchant($merchant)
+ {
+ self::setApiKey($merchant);
+ }
+
+ /**
+ * @return string The shared secret used for requests.
+ */
+ public static function getSharedSecret()
+ {
+ return self::$sharedSecret;
+ }
+
+ /**
+ * Sets the shared secret to be used for requests.
+ *
+ * @param string $sharedSecret
+ */
+ public static function setSharedSecret($sharedSecret)
+ {
+ self::$sharedSecret = $sharedSecret;
+ }
+
+ /**
+ * @return string The sandbox mode used for requests.
+ */
+ public static function getSandboxMode()
+ {
+ return self::$sandboxMode;
+ }
+
+ /**
+ * Sets the sandbox mode to be used for requests.
+ *
+ * @param string $merchant
+ */
+ public static function setSandboxMode($sandboxMode)
+ {
+ self::$sandboxMode = $sandboxMode;
+
+ if ($sandboxMode) {
+ self::$apiBase = self::$sandboxApiBase;
+ }
+ }
+
+ /**
+ * @return string The API key used for requests.
+ */
+ public static function getApiKey()
+ {
+ return self::$apiKey;
+ }
+
+ /**
+ * Sets the API key to be used for requests.
+ *
+ * @param string $apiKey
+ */
+ public static function setApiKey($apiKey)
+ {
+ self::$apiKey = $apiKey;
+
+ if (substr($apiKey, 0, 7) == 'testing') {
+ self::$apiBase = self::$testingApiBase;
+ } else if (substr($apiKey, 0, 7) == 'staging') {
+ self::$apiBase = self::$sandboxApiBase;
+ } else if (substr($apiKey, 0, 3) == 'dev') {
+ self::$apiBase = self::$devApiBase;
+ } else if (substr($apiKey, 0, 7) == 'sandbox') {
+ self::$apiBase = self::$sandboxApiBase;
+ } else if (substr($apiKey, 0, 6) == 'docker') {
+ self::$apiBase = self::$dockerApiBase;
+ }
+ }
+
+ /**
+ * @return string The API version used for requests. null if we're using the
+ * latest version.
+ */
+ public static function getApiVersion()
+ {
+ return self::$apiVersion;
+ }
+
+ /**
+ * @param string $apiVersion The API version to use for requests.
+ */
+ public static function setApiVersion($apiVersion)
+ {
+ self::$apiVersion = $apiVersion;
+ }
+
+ /**
+ * @return boolean
+ */
+ public static function getVerifySslCerts()
+ {
+ return self::$verifySslCerts;
+ }
+
+ /**
+ * @param boolean $verify
+ */
+ public static function setVerifySslCerts($verify)
+ {
+ self::$verifySslCerts = $verify;
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Error.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Error.php
new file mode 100644
index 0000000..1d8fb7a
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Error.php
@@ -0,0 +1,29 @@
+<?php
+
+class Divido_Error extends Exception
+{
+ public function __construct($message, $httpStatus=null,
+ $httpBody=null, $jsonBody=null
+ )
+ {
+ parent::__construct($message);
+ $this->httpStatus = $httpStatus;
+ $this->httpBody = $httpBody;
+ $this->jsonBody = $jsonBody;
+ }
+
+ public function getHttpStatus()
+ {
+ return $this->httpStatus;
+ }
+
+ public function getHttpBody()
+ {
+ return $this->httpBody;
+ }
+
+ public function getJsonBody()
+ {
+ return $this->jsonBody;
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Finances.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Finances.php
new file mode 100644
index 0000000..3d58f8c
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Finances.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_Finances extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Finances
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Charges.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Finances The created charge.
+ */
+ public static function create($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedCreditRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Finances The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Fulfillment.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Fulfillment.php
new file mode 100644
index 0000000..ff0564c
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Fulfillment.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_Fulfillment extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Fulfillment
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Fulfillment.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Charge The created charge.
+ */
+ public static function fulfill($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedFulfillRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Fulfillment The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/InvalidRequestError.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/InvalidRequestError.php
new file mode 100644
index 0000000..aaa844d
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/InvalidRequestError.php
@@ -0,0 +1,12 @@
+<?php
+
+class Divido_InvalidRequestError extends Divido_Error
+{
+ public function __construct($message, $param, $httpStatus=null,
+ $httpBody=null, $jsonBody=null
+ )
+ {
+ parent::__construct($message, $httpStatus, $httpBody, $jsonBody);
+ $this->param = $param;
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/List.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/List.php
new file mode 100644
index 0000000..e707de6
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/List.php
@@ -0,0 +1,54 @@
+<?php
+
+class Divido_List extends Divido_Object
+{
+ public function all($params=null)
+ {
+ list($url, $params) = $this->extractPathAndUpdateParams($params);
+
+ $requestor = new Divido_ApiRequestor($this->_apiKey);
+ list($response, $apiKey) = $requestor->request('get', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ public function create($params=null)
+ {
+ list($url, $params) = $this->extractPathAndUpdateParams($params);
+
+ $requestor = new Divido_ApiRequestor($this->_apiKey);
+ list($response, $apiKey) = $requestor->request('post', $url, $params);
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ public function retrieve($id, $params=null)
+ {
+ list($url, $params) = $this->extractPathAndUpdateParams($params);
+
+ $requestor = new Divido_ApiRequestor($this->_apiKey);
+ $id = Divido_ApiRequestor::utf8($id);
+ $extn = urlencode($id);
+ list($response, $apiKey) = $requestor->request(
+ 'get', "$url/$extn", $params
+ );
+ return Divido_Util::convertToDividoObject($response, $apiKey);
+ }
+
+ private function extractPathAndUpdateParams($params)
+ {
+ $url = parse_url($this->url);
+ if (!isset($url['path'])) {
+ throw new Divido_APIError("Could not parse list url into parts: $url");
+ }
+
+ if (isset($url['query'])) {
+ // If the URL contains a query param, parse it out into $params so they
+ // don't interact weirdly with each other.
+ $query = array();
+ parse_str($url['query'], $query);
+ // PHP 5.2 doesn't support the ?: operator :(
+ $params = array_merge($params ? $params : array(), $query);
+ }
+
+ return array($url['path'], $params);
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Object.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Object.php
new file mode 100644
index 0000000..f784b0e
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Object.php
@@ -0,0 +1,265 @@
+<?php
+
+class Divido_Object implements ArrayAccess
+{
+ /**
+ * @var Divido_Util_Set Attributes that should not be sent to the API because
+ * they're not updatable (e.g. API key, ID).
+ */
+ public static $permanentAttributes;
+ /**
+ * @var Divido_Util_Set Attributes that are nested but still updatable from
+ * the parent class's URL (e.g. metadata).
+ */
+ public static $nestedUpdatableAttributes;
+
+ public static function init()
+ {
+ self::$permanentAttributes = new Divido_Util_Set(array('_apiKey', 'id'));
+ self::$nestedUpdatableAttributes = new Divido_Util_Set(array('metadata'));
+ }
+
+ protected $_apiKey;
+ protected $_values;
+ protected $_unsavedValues;
+ protected $_transientValues;
+ protected $_retrieveOptions;
+
+ public function __construct($id=null, $apiKey=null)
+ {
+ $this->_apiKey = $apiKey;
+ $this->_values = array();
+ $this->_unsavedValues = new Divido_Util_Set();
+ $this->_transientValues = new Divido_Util_Set();
+
+ $this->_retrieveOptions = array();
+ if (is_array($id)) {
+ foreach ($id as $key => $value) {
+ if ($key != 'id') {
+ $this->_retrieveOptions[$key] = $value;
+ }
+ }
+ $id = $id['id'];
+ }
+
+ if ($id !== null) {
+ $this->id = $id;
+ }
+ }
+
+ // Standard accessor magic methods
+ public function __set($k, $v)
+ {
+ if ($v === "") {
+ throw new InvalidArgumentException(
+ 'You cannot set \''.$k.'\'to an empty string. '
+ .'We interpret empty strings as NULL in requests. '
+ .'You may set obj->'.$k.' = NULL to delete the property'
+ );
+ }
+
+ if (self::$nestedUpdatableAttributes->includes($k)
+ && isset($this->$k) && is_array($v)) {
+ $this->$k->replaceWith($v);
+ } else {
+ // TODO: may want to clear from $_transientValues (Won't be user-visible).
+ $this->_values[$k] = $v;
+ }
+ if (!self::$permanentAttributes->includes($k))
+ $this->_unsavedValues->add($k);
+ }
+ public function __isset($k)
+ {
+ return isset($this->_values[$k]);
+ }
+ public function __unset($k)
+ {
+ unset($this->_values[$k]);
+ $this->_transientValues->add($k);
+ $this->_unsavedValues->discard($k);
+ }
+ public function __get($k)
+ {
+ if (array_key_exists($k, $this->_values)) {
+ return $this->_values[$k];
+ } else if ($this->_transientValues->includes($k)) {
+ $class = get_class($this);
+ $attrs = join(', ', array_keys($this->_values));
+ $message = "Divido Notice: Undefined property of $class instance: $k. "
+ . "HINT: The $k attribute was set in the past, however. "
+ . "It was then wiped when refreshing the object "
+ . "with the result returned by Divido's API, "
+ . "probably as a result of a save(). The attributes currently "
+ . "available on this object are: $attrs";
+ error_log($message);
+ return null;
+ } else {
+ $class = get_class($this);
+ error_log("Divido Notice: Undefined property of $class instance: $k");
+ return null;
+ }
+ }
+
+ // ArrayAccess methods
+ public function offsetSet($k, $v)
+ {
+ $this->$k = $v;
+ }
+
+ public function offsetExists($k)
+ {
+ return array_key_exists($k, $this->_values);
+ }
+
+ public function offsetUnset($k)
+ {
+ unset($this->$k);
+ }
+ public function offsetGet($k)
+ {
+ return array_key_exists($k, $this->_values) ? $this->_values[$k] : null;
+ }
+
+ public function keys()
+ {
+ return array_keys($this->_values);
+ }
+
+ /**
+ * This unfortunately needs to be public to be used in Util.php
+ *
+ * @param string $class
+ * @param array $values
+ * @param string|null $apiKey
+ *
+ * @return Divido_Object The object constructed from the given values.
+ */
+ public static function scopedConstructFrom($class, $values, $apiKey=null)
+ {
+ $obj = new $class(isset($values['id']) ? $values['id'] : null, $apiKey);
+ $obj->refreshFrom($values, $apiKey);
+ return $obj;
+ }
+
+ /**
+ * @param array $values
+ * @param string|null $apiKey
+ *
+ * @return Divido_Object The object of the same class as $this constructed
+ * from the given values.
+ */
+ public static function constructFrom($values, $apiKey=null)
+ {
+ return self::scopedConstructFrom(__CLASS__, $values, $apiKey);
+ }
+
+ /**
+ * Refreshes this object using the provided values.
+ *
+ * @param array $values
+ * @param string $apiKey
+ * @param boolean $partial Defaults to false.
+ */
+ public function refreshFrom($values, $apiKey, $partial=false)
+ {
+ $this->_apiKey = $apiKey;
+
+ // Wipe old state before setting new. This is useful for e.g. updating a
+ // customer, where there is no persistent card parameter. Mark those values
+ // which don't persist as transient
+ if ($partial) {
+ $removed = new Divido_Util_Set();
+ } else {
+ $removed = array_diff(array_keys($this->_values), array_keys($values));
+ }
+
+ foreach ($removed as $k) {
+ if (self::$permanentAttributes->includes($k))
+ continue;
+ unset($this->$k);
+ }
+
+ foreach ($values as $k => $v) {
+ if (self::$permanentAttributes->includes($k) && isset($this[$k]))
+ continue;
+
+ if (self::$nestedUpdatableAttributes->includes($k) && is_array($v)) {
+ $this->_values[$k] = Divido_Object::scopedConstructFrom(
+ 'Divido_AttachedObject', $v, $apiKey
+ );
+ } else {
+ $this->_values[$k] = Divido_Util::convertToDividoObject($v, $apiKey);
+ }
+
+ $this->_transientValues->discard($k);
+ $this->_unsavedValues->discard($k);
+ }
+ }
+
+ /**
+ * @return array A recursive mapping of attributes to values for this object,
+ * including the proper value for deleted attributes.
+ */
+ public function serializeParameters()
+ {
+ $params = array();
+ if ($this->_unsavedValues) {
+ foreach ($this->_unsavedValues->toArray() as $k) {
+ $v = $this->$k;
+ if ($v === NULL) {
+ $v = '';
+ }
+ $params[$k] = $v;
+ }
+ }
+
+ // Get nested updates.
+ foreach (self::$nestedUpdatableAttributes->toArray() as $property) {
+ if (isset($this->$property)
+ && $this->$property instanceOf Divido_Object) {
+ $params[$property] = $this->$property->serializeParameters();
+ }
+ }
+ return $params;
+ }
+
+ // Pretend to have late static bindings, even in PHP 5.2
+ protected function _lsb($method)
+ {
+ $class = get_class($this);
+ $args = array_slice(func_get_args(), 1);
+ return call_user_func_array(array($class, $method), $args);
+ }
+ protected static function _scopedLsb($class, $method)
+ {
+ $args = array_slice(func_get_args(), 2);
+ return call_user_func_array(array($class, $method), $args);
+ }
+
+ public function __toJSON()
+ {
+ if (defined('JSON_PRETTY_PRINT')) {
+ return json_encode($this->__toArray(true), JSON_PRETTY_PRINT);
+ } else {
+ return json_encode($this->__toArray(true));
+ }
+ }
+
+ public function __toString()
+ {
+ $class = get_class($this);
+ return $class . ' JSON: ' . $this->__toJSON();
+ }
+
+ public function __toArray($recursive=false)
+ {
+ if ($recursive) {
+ return Divido_Util::convertDividoObjectToArray($this->_values);
+ } else {
+ return $this->_values;
+ }
+ }
+}
+
+
+Divido_Object::init();
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/PaymentError.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/PaymentError.php
new file mode 100644
index 0000000..dddf94e
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/PaymentError.php
@@ -0,0 +1,13 @@
+<?php
+
+class Divido_PaymentError extends Divido_Error
+{
+ public function __construct($message, $param, $code, $httpStatus,
+ $httpBody, $jsonBody
+ )
+ {
+ parent::__construct($message, $httpStatus, $httpBody, $jsonBody);
+ $this->param = $param;
+ $this->code = $code;
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/RateLimitError.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/RateLimitError.php
new file mode 100644
index 0000000..e7baf61
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/RateLimitError.php
@@ -0,0 +1,11 @@
+<?php
+
+class Divido_RateLimitError extends Divido_InvalidRequestError
+{
+ public function __construct($message, $param, $httpStatus=null,
+ $httpBody=null, $jsonBody=null
+ )
+ {
+ parent::__construct($message, $httpStatus, $httpBody, $jsonBody);
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Refund.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Refund.php
new file mode 100644
index 0000000..0a9440e
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Refund.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_Refund extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_Fulfillment
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_Fulfillment.
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_Charge The created charge.
+ */
+ public static function refund($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedRefundRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_Fulfillment The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/SendApplication.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/SendApplication.php
new file mode 100644
index 0000000..cc3be41
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/SendApplication.php
@@ -0,0 +1,50 @@
+<?php
+
+class Divido_SendApplication extends Divido_ApiResource
+{
+ /**
+ * @param string $id The ID of the charge to retrieve.
+ * @param string|null $apiKey
+ *
+ * @return Divido_SendApplication
+ */
+ public static function retrieve($id, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedRetrieve($class, $id, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return array An array of Divido_SendApplication
+ */
+ public static function all($params=null, $apiKey=null)
+ {
+ $class = get_class();
+ return self::_scopedAll($class, $params, $apiKey);
+ }
+
+ /**
+ * @param array|null $params
+ * @param string|null $apiKey
+ *
+ * @return Divido_SendApplication
+ */
+ public static function send($params=null, $merchant=null)
+ {
+ $class = get_class();
+ return self::_scopedSendApplicationRequest($class, $params, $merchant);
+ }
+
+ /**
+ * @return Divido_SendApplication The saved charge.
+ */
+ public function save()
+ {
+ $class = get_class();
+ return self::_scopedSave($class);
+ }
+
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/SingletonApiResource.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/SingletonApiResource.php
new file mode 100644
index 0000000..7c36112
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/SingletonApiResource.php
@@ -0,0 +1,31 @@
+<?php
+
+abstract class Divido_SingletonApiResource extends Divido_ApiResource
+{
+ protected static function _scopedSingletonRetrieve($class, $apiKey=null)
+ {
+ $instance = new $class(null, $apiKey);
+ $instance->refresh();
+ return $instance;
+ }
+
+ /**
+ * @param Divido_SingletonApiResource $class
+ * @return string The endpoint associated with this singleton class.
+ */
+ public static function classUrl($class)
+ {
+ $base = self::className($class);
+ return "/v1/${base}";
+ }
+
+ /**
+ * @return string The endpoint associated with this singleton API resource.
+ */
+ public function instanceUrl()
+ {
+ $class = get_class($this);
+ $base = self::classUrl($class);
+ return "$base";
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Util.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Util.php
new file mode 100644
index 0000000..c7031da
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Util.php
@@ -0,0 +1,89 @@
+<?php
+
+abstract class Divido_Util
+{
+ /**
+ * Whether the provided array (or other) is a list rather than a dictionary.
+ *
+ * @param array|mixed $array
+ * @return boolean True if the given object is a list.
+ */
+ public static function isList($array)
+ {
+ if (!is_array($array))
+ return false;
+
+ // TODO: generally incorrect, but it's correct given Divido's response
+ foreach (array_keys($array) as $k) {
+ if (!is_numeric($k))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Recursively converts the PHP Divido object to an array.
+ *
+ * @param array $values The PHP Divido object to convert.
+ * @return array
+ */
+ public static function convertDividoObjectToArray($values)
+ {
+ $results = array();
+ foreach ($values as $k => $v) {
+ // FIXME: this is an encapsulation violation
+ if ($k[0] == '_') {
+ continue;
+ }
+ if ($v instanceof Divido_Object) {
+ $results[$k] = $v->__toArray(true);
+ } else if (is_array($v)) {
+ $results[$k] = self::convertDividoObjectToArray($v);
+ } else {
+ $results[$k] = $v;
+ }
+ }
+ return $results;
+ }
+
+ /**
+ * Converts a response from the Divido API to the corresponding PHP object.
+ *
+ * @param array $resp The response from the Divido API.
+ * @param string $apiKey
+ * @return Divido_Object|array
+ */
+ public static function convertToDividoObject($resp, $apiKey)
+ {
+ $types = array(
+ 'customer' => 'Divido_Customer',
+ 'list' => 'Divido_List',
+ 'invoice' => 'Divido_Invoice',
+ 'invoiceitem' => 'Divido_InvoiceItem',
+ 'event' => 'Divido_Event',
+ 'transfer' => 'Divido_Transfer',
+ 'plan' => 'Divido_Plan',
+ 'recipient' => 'Divido_Recipient',
+ 'refund' => 'Divido_Refund',
+ 'subscription' => 'Divido_Subscription',
+ 'fee_refund' => 'Divido_ApplicationFeeRefund'
+ );
+ if (self::isList($resp)) {
+ $mapped = array();
+ foreach ($resp as $i)
+ array_push($mapped, self::convertToDividoObject($i, $apiKey));
+ return $mapped;
+ } else if (is_array($resp)) {
+ if (isset($resp['object'])
+ && is_string($resp['object'])
+ && isset($types[$resp['object']])) {
+ $class = $types[$resp['object']];
+ } else {
+ $class = 'Divido_Object';
+ }
+ return Divido_Object::scopedConstructFrom($class, $resp, $apiKey);
+ } else {
+ return $resp;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/Divido/Util/Set.php b/public/system/storage/vendor/divido/divido-php/lib/Divido/Util/Set.php
new file mode 100644
index 0000000..af6cef9
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/Divido/Util/Set.php
@@ -0,0 +1,39 @@
+<?php
+
+class Divido_Util_Set implements IteratorAggregate
+{
+ private $_elts;
+
+ public function __construct($members = array())
+ {
+ $this->_elts = array();
+ foreach ($members as $item) {
+ $this->_elts[$item] = true;
+ }
+ }
+
+ public function includes($elt)
+ {
+ return isset($this->_elts[$elt]);
+ }
+
+ public function add($elt)
+ {
+ $this->_elts[$elt] = true;
+ }
+
+ public function discard($elt)
+ {
+ unset($this->_elts[$elt]);
+ }
+
+ public function toArray()
+ {
+ return array_keys($this->_elts);
+ }
+
+ public function getIterator()
+ {
+ return new ArrayIterator($this->toArray());
+ }
+}
diff --git a/public/system/storage/vendor/divido/divido-php/lib/data/ca-certificates.crt b/public/system/storage/vendor/divido/divido-php/lib/data/ca-certificates.crt
new file mode 100644
index 0000000..0e11f6d
--- /dev/null
+++ b/public/system/storage/vendor/divido/divido-php/lib/data/ca-certificates.crt
@@ -0,0 +1,5165 @@
+# Generated by https://gist.github.com/ab/9756531 on 2014-03-25
+# from Ubuntu ca-certificates 20130906.
+# See http://www.ubuntu.com/usn/usn-2154-1/ for version info.
+
+================================================================
+C: AT
+O: A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH
+OU: A-Trust-nQual-03
+CN: A-Trust-nQual-03
+-----BEGIN CERTIFICATE-----
+MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB
+VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp
+bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R
+dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw
+MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy
+dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52
+ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM
+EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj
+lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ
+znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH
+2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1
+k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs
+2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD
+VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
+AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG
+KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+
+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R
+FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS
+mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE
+DNuxUCAKGkq6ahq97BvIxYSazQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: BE
+O: GlobalSign nv-sa
+OU: Root CA
+CN: GlobalSign Root CA
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+================================================================
+C: BM
+O: QuoVadis Limited
+CN: QuoVadis Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+================================================================
+C: BM
+O: QuoVadis Limited
+CN: QuoVadis Root CA 3
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+================================================================
+C: BM
+O: QuoVadis Limited
+OU: Root Certification Authority
+CN: QuoVadis Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz
+MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw
+IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR
+dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp
+li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D
+rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ
+WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug
+F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU
+xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC
+Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv
+dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw
+ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl
+IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh
+c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy
+ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI
+KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T
+KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq
+y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p
+dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD
+VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk
+fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8
+7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R
+cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y
+mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW
+xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK
+SnQ2+Q==
+-----END CERTIFICATE-----
+
+================================================================
+C: CH
+O: SwissSign AG
+CN: SwissSign Gold CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+================================================================
+C: CH
+O: SwissSign AG
+CN: SwissSign Platinum CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
+BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu
+IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw
+WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD
+ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y
+IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn
+IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+
+6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob
+jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw
+izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl
++zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY
+zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP
+pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF
+KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW
+ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB
+AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0
+ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW
+IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA
+A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0
+uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+
+FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7
+jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/
+u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D
+YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1
+puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa
+icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG
+DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x
+kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z
+Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g==
+-----END CERTIFICATE-----
+
+================================================================
+C: CH
+O: SwissSign AG
+CN: SwissSign Silver CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
+BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
+IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
+RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
+U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
+Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
+YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
+nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
+6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
+eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
+c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
+MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
+HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
+jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
+5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
+rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
+wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
+AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
+WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
+xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
+2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
+IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
+aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
+em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
+dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
+OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
+tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+================================================================
+C: CH
+O: WISeKey
+OU: Copyright (c) 2005
+OU: OISTE Foundation Endorsed
+CN: OISTE WISeKey Global Root GA CA
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB
+ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly
+aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
+ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w
+NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G
+A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD
+VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX
+SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR
+VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2
+w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF
+mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg
+4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9
+4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw
+EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx
+SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2
+ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8
+vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi
+Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ
+/L7fCg0=
+-----END CERTIFICATE-----
+
+================================================================
+C: CN
+O: CNNIC
+CN: CNNIC ROOT
+-----BEGIN CERTIFICATE-----
+MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD
+TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2
+MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF
+Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh
+IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6
+dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO
+V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC
+GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN
+v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB
+AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB
+Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO
+76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK
+OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH
+ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi
+yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL
+buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj
+2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE=
+-----END CERTIFICATE-----
+
+================================================================
+C: CN
+O: China Internet Network Information Center
+CN: China Internet Network Information Center EV Certificates Root
+-----BEGIN CERTIFICATE-----
+MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
+Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g
+Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0
+aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa
+Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg
+SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo
+aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp
+ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z
+7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//
+DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx
+zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8
+hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs
+4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u
+gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY
+NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
+FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3
+j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG
+52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB
+echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
+ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI
+zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy
+wy39FCqQmbkHzJ8=
+-----END CERTIFICATE-----
+
+================================================================
+C: CO
+O: Sociedad Cameral de Certificación Digital - Certicámara S.A.
+CN: AC Raíz Certicámara S.A.
+-----BEGIN CERTIFICATE-----
+MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx
+CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp
+ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa
+QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw
+NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft
+ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu
+QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG
+qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL
+fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ
+Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4
+Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ
+54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b
+MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j
+ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej
+YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt
+A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF
+rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ
+pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB
+lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy
+YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50
+7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs
+YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6
+xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc
+unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/
+Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp
+ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42
+gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0
+jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+
+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD
+W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/
+RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r
+MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk
+BYn8eNZcLCZDqQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: D-Trust GmbH
+CN: D-TRUST Root Class 3 CA 2 2009
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: D-Trust GmbH
+CN: D-TRUST Root Class 3 CA 2 EV 2009
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: Deutsche Telekom AG
+OU: T-TeleSec Trust Center
+CN: Deutsche Telekom Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
+MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
+IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
+IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
+RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
+U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
+IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
+ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
+QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
+rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
+NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
+QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
+txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
+BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
+AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
+tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
+IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
+6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: T-Systems Enterprise Services GmbH
+OU: T-Systems Trust Center
+CN: T-TeleSec GlobalRoot Class 3
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: TC TrustCenter GmbH
+OU: TC TrustCenter Class 2 CA
+CN: TC TrustCenter Class 2 CA II
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
+BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
+Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1
+OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
+SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc
+VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf
+tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg
+uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J
+XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK
+8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99
+5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3
+kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
+dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6
+Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
+JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
+Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS
+GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt
+ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8
+au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV
+hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI
+dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: TC TrustCenter GmbH
+OU: TC TrustCenter Class 3 CA
+CN: TC TrustCenter Class 3 CA II
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
+BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
+Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1
+OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
+SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc
+VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW
+Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q
+Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2
+1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq
+ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1
+Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX
+XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
+dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6
+Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
+JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
+Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN
+irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8
+TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6
+g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB
+95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj
+S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A==
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+O: TC TrustCenter GmbH
+OU: TC TrustCenter Universal CA
+CN: TC TrustCenter Universal CA I
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL
+MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
+BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1
+c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx
+MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg
+R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD
+VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR
+JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T
+fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu
+jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z
+wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ
+fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD
+VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G
+CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1
+7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn
+8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs
+ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
+ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/
+2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
+-----END CERTIFICATE-----
+
+================================================================
+C: DE
+ST: Baden-Wuerttemberg (BW)
+L: Stuttgart
+O: Deutscher Sparkassen Verlag GmbH
+CN: S-TRUST Authentication and Encryption Root CA 2005:PN
+-----BEGIN CERTIFICATE-----
+MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCB
+rjELMAkGA1UEBhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcp
+MRIwEAYDVQQHEwlTdHV0dGdhcnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fz
+c2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVTLVRSVVNUIEF1dGhlbnRpY2F0aW9u
+IGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0wNTA2MjIwMDAwMDBa
+Fw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFkZW4t
+V3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMg
+RGV1dHNjaGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJV
+U1QgQXV0aGVudGljYXRpb24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBO
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1
+toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob4QSwI7+Vio5bG0F/WsPo
+TUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXLg3KSwlOy
+ggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1
+XgqfeN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteF
+hy+S8dF2g08LOlk3KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm
+7QIDAQABo4GSMIGPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEG
+MCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJvbmxpbmUxLTIwNDgtNTAdBgNV
+HQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAUD8oeXHngovMp
+ttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD
+pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFo
+LtU96G7m1R08P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersF
+iXOMy6ZNwPv2AtawB6MDwidAnwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0y
+h9WUUpY6RsZxlj33mA6ykaqP2vROJAA5VeitF7nTNCtKqUDMFypVZUF0Qn71wK/I
+k63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8bHz2eBIPdltkdOpQ=
+-----END CERTIFICATE-----
+
+================================================================
+C: DK
+O: TDC
+CN: TDC OCES CA
+-----BEGIN CERTIFICATE-----
+MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE
+SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw
+ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU
+REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr
+2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s
+2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU
+GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj
+dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r
+TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB
+AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv
+c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl
+ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu
+MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg
+T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud
+HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD
+VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny
+bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy
+MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ
+J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG
+SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom
+JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO
+inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y
+caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB
+mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ
+YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9
+BKNDLdr8C2LqL19iUw==
+-----END CERTIFICATE-----
+
+================================================================
+C: DK
+O: TDC Internet
+OU: TDC Internet Root CA
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE
+SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg
+Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV
+BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl
+cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA
+vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu
+Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a
+0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1
+4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN
+eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD
+R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG
+A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu
+dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME
+Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3
+WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw
+HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ
+KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO
+Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX
+wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+
+2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89
+9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0
+jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38
+aQNiuJkFBT1reBK9sG9l
+-----END CERTIFICATE-----
+
+================================================================
+C: EE
+O: AS Sertifitseerimiskeskus
+CN: EE Certification Centre Root CA
+emailAddress: pki@sk.ee
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1
+MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
+czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG
+CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy
+MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl
+ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS
+b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy
+euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO
+bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw
+WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d
+MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE
+1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/
+zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB
+BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF
+BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV
+v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG
+E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW
+iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v
+GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0=
+-----END CERTIFICATE-----
+
+================================================================
+C: ES
+CN: Autoridad de Certificacion Firmaprofesional CIF A62634068
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy
+MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD
+VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv
+ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl
+AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF
+661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9
+am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1
+ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481
+PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS
+3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k
+SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF
+3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM
+ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g
+StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz
+Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB
+jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+================================================================
+C: ES
+L: C/ Muntaner 244 Barcelona
+CN: Autoridad de Certificacion Firmaprofesional CIF A62634068
+emailAddress: ca@firmaprofesional.com
+-----BEGIN CERTIFICATE-----
+MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx
+IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1
+dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w
+HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx
+IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1
+dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u
+Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY
+rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z
+hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay
+BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL
+iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb
+AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv
+bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0
+MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
+FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n
+VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq
+u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m
+hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl
+ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp
+QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5
+quGnM/b9Sh/22WA=
+-----END CERTIFICATE-----
+
+================================================================
+C: ES
+O: Agencia Catalana de Certificacio (NIF Q-0801176-I)
+OU: Serveis Publics de Certificacio
+OU: Vegeu https://www.catcert.net/verarrel (c)03
+OU: Jerarquia Entitats de Certificacio Catalanes
+CN: EC-ACC
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB
+8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy
+dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1
+YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3
+dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh
+IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD
+LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG
+EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g
+KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD
+ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu
+bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg
+ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R
+85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm
+4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV
+HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd
+QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t
+lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB
+o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4
+opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo
+dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW
+ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN
+AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y
+/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k
+SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy
+Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS
+Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl
+nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI=
+-----END CERTIFICATE-----
+
+================================================================
+C: ES
+O: Generalitat Valenciana
+OU: PKIGVA
+CN: Root CA Generalitat Valenciana
+-----BEGIN CERTIFICATE-----
+MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJF
+UzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJ
+R1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcN
+MDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0G
+A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScw
+JQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+
+WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKj
+SgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl
+u6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOy
+A8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxk
+Hl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7
+MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBr
+aS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIIC
+IwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8A
+cgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIA
+YQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQAIABWAGEA
+bABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA
+bgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA
+aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMA
+aQBvAG4AYQBtAGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQA
+ZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA
+YwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBuAHQAcgBhACAAZQBuACAAbABhACAA
+ZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAAOgAvAC8AdwB3AHcA
+LgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0dHA6
+Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+y
+eAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw
+CQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0G
+A1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVu
+Y2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3Fbcrn
+lD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLt
+b8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg
+9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XF
+ducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmC
+IoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM=
+-----END CERTIFICATE-----
+
+================================================================
+C: ES
+O: IZENPE S.A.
+CN: Izenpe.com
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+================================================================
+C: EU
+L: Madrid (see current address at www.camerfirma.com/address)
+serialNumber: A82743287
+O: AC Camerfirma S.A.
+CN: Chambers of Commerce Root - 2008
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
+VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
+IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
+MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz
+IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz
+MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj
+dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw
+EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp
+MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9
+28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq
+VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q
+DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR
+5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL
+ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a
+Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl
+UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s
++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5
+Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx
+hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV
+HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1
++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN
+YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t
+L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy
+ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt
+IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV
+HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w
+DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW
+PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF
+5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1
+glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH
+FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2
+pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD
+xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG
+tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq
+jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De
+fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ
+d0jQ
+-----END CERTIFICATE-----
+
+================================================================
+C: EU
+L: Madrid (see current address at www.camerfirma.com/address)
+serialNumber: A82743287
+O: AC Camerfirma S.A.
+CN: Global Chambersign Root - 2008
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
+VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
+IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
+MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx
+MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
+cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
+A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
+BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed
+KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7
+G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2
+zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4
+ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG
+HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2
+Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V
+yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e
+beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r
+6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog
+zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW
+BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr
+ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp
+ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk
+cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt
+YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC
+CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow
+KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI
+hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ
+UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz
+X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x
+fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz
+a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd
+Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd
+SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O
+AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso
+M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge
+v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+================================================================
+C: EU
+O: AC Camerfirma SA CIF A82743287
+OU: http://www.chambersign.org
+CN: Chambers of Commerce Root
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn
+MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
+ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg
+b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa
+MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB
+ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw
+IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B
+AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb
+unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d
+BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq
+7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3
+0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX
+roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG
+A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j
+aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p
+26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA
+BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud
+EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN
+BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
+aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB
+AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd
+p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi
+1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc
+XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0
+eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu
+tGWaIZDgqtCYvDi1czyL+Nw=
+-----END CERTIFICATE-----
+
+================================================================
+C: EU
+O: AC Camerfirma SA CIF A82743287
+OU: http://www.chambersign.org
+CN: Global Chambersign Root
+-----BEGIN CERTIFICATE-----
+MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn
+MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
+ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo
+YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9
+MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy
+NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G
+A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA
+A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0
+Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s
+QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV
+eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795
+B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh
+z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T
+AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i
+ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w
+TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH
+MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD
+VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE
+VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
+bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B
+AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM
+bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi
+ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG
+VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c
+ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/
+AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
+-----END CERTIFICATE-----
+
+================================================================
+C: FI
+O: Sonera
+CN: Sonera Class1 CA
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
+MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx
+MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV
+BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG
+29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk
+oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk
+3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL
+qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN
+nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw
+DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG
+MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX
+ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H
+DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO
+TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv
+kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w
+zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa
+-----END CERTIFICATE-----
+
+================================================================
+C: FI
+O: Sonera
+CN: Sonera Class2 CA
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
+MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx
+MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV
+BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o
+Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt
+5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s
+3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej
+vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu
+8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw
+DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG
+MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil
+zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/
+3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD
+FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6
+Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2
+ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M
+-----END CERTIFICATE-----
+
+================================================================
+C: FR
+O: Certinomis
+OU: 0002 433998903
+CN: Certinomis - Autorité Racine
+-----BEGIN CERTIFICATE-----
+MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET
+MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk
+BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4
+Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl
+cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0
+aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY
+F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N
+8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe
+rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K
+/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu
+7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC
+28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6
+lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E
+nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB
+0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09
+5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj
+WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN
+jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
+KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s
+ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM
+OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q
+619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn
+2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj
+o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v
+nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG
+5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq
+pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb
+dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0
+BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5
+-----END CERTIFICATE-----
+
+================================================================
+C: FR
+O: Certplus
+CN: Class 2 Primary CA
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw
+PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz
+cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9
+MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz
+IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ
+ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR
+VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL
+kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd
+EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas
+H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0
+HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud
+DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4
+QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu
+Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/
+AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8
+yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR
+FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA
+ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB
+kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+================================================================
+C: FR
+O: Dhimyotis
+CN: Certigna
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+================================================================
+C: FR
+ST: France
+L: Paris
+O: PM/SGDN
+OU: DCSSI
+CN: IGC/A
+emailAddress: igca@sgdn.pm.gouv.fr
+-----BEGIN CERTIFICATE-----
+MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT
+AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ
+TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG
+9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw
+MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM
+BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO
+MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2
+LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI
+s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2
+xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4
+u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b
+F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx
+Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd
+PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV
+HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx
+NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF
+AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ
+L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY
+YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
+Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a
+NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R
+0982gaEbeC9xs/FZTEYYKKuF0mBWWg==
+-----END CERTIFICATE-----
+
+================================================================
+C: GB
+O: Trustis Limited
+OU: Trustis FPS Root CA
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL
+ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx
+MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc
+MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+
+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH
+iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj
+vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA
+0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB
+OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/
+BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E
+FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01
+GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW
+zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4
+1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE
+f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F
+jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN
+ZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+
+================================================================
+C: GB
+ST: Greater Manchester
+L: Salford
+O: Comodo CA Limited
+CN: AAA Certificate Services
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+================================================================
+C: GB
+ST: Greater Manchester
+L: Salford
+O: Comodo CA Limited
+CN: Secure Certificate Services
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp
+ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow
+fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV
+BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM
+cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S
+HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996
+CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk
+3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz
+6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV
+HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
+EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv
+Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw
+Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
+DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0
+5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
+Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI
+gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ
+aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl
+izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk=
+-----END CERTIFICATE-----
+
+================================================================
+C: GB
+ST: Greater Manchester
+L: Salford
+O: Comodo CA Limited
+CN: Trusted Certificate Services
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
+aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
+MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
+BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
+VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
+fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
+TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
+fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
+1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
+kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
+A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
+ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
+dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
+Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
+HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
+pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
+jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
+xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
+dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
+-----END CERTIFICATE-----
+
+================================================================
+C: GB
+ST: Greater Manchester
+L: Salford
+O: COMODO CA Limited
+CN: COMODO Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: GB
+ST: Greater Manchester
+L: Salford
+O: COMODO CA Limited
+CN: COMODO ECC Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+================================================================
+C: GR
+O: Hellenic Academic and Research Institutions Cert. Authority
+CN: Hellenic Academic and Research Institutions RootCA 2011
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix
+RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p
+YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw
+NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK
+EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl
+cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz
+dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ
+fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns
+bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD
+75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP
+FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV
+HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp
+5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu
+b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA
+A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p
+6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7
+dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys
+Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI
+l7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+
+================================================================
+C: HK
+O: Hongkong Post
+CN: Hongkong Post Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx
+FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg
+Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG
+A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr
+b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ
+jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn
+PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh
+ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9
+nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h
+q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED
+MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC
+mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3
+7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB
+oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs
+EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
+fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
+AmvZWg==
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+L: Budapest
+O: Microsec Ltd.
+CN: Microsec e-Szigno Root CA 2009
+emailAddress: info@e-szigno.hu
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+L: Budapest
+O: NetLock Kft.
+OU: Tanúsítványkiadók (Certification Services)
+CN: NetLock Arany (Class Gold) Főtanúsítvány
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+L: Budapest
+O: Microsec Ltd.
+OU: e-Szigno CA
+CN: Microsec e-Szigno Root CA
+-----BEGIN CERTIFICATE-----
+MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw
+cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy
+b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z
+ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4
+NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN
+TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p
+Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u
+uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+
+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA
+vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770
+Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx
+62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB
+AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw
+LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP
+BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB
+AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov
+MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5
+ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
+AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT
+AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh
+ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo
+AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa
+AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln
+bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p
+Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP
+PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv
+Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB
+EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu
+w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj
+cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV
+HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI
+VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS
+BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS
+b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS
+8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds
+ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl
+7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
+86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR
+hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/
+MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+L: Budapest
+O: NetLock Halozatbiztonsagi Kft.
+OU: Tanusitvanykiadok
+CN: NetLock Expressz (Class C) Tanusitvanykiado
+-----BEGIN CERTIFICATE-----
+MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx
+ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0
+b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD
+EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X
+DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw
+DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u
+c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr
+TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA
+OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC
+2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW
+RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P
+AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW
+ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0
+YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz
+b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO
+ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB
+IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs
+b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs
+ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s
+YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg
+a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g
+SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0
+aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg
+YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg
+Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY
+ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g
+pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4
+Fp1hBWeAyNDYpQcCNJgEjTME1A==
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+L: Budapest
+O: NetLock Halozatbiztonsagi Kft.
+OU: Tanusitvanykiadok
+CN: NetLock Minositett Kozjegyzoi (Class QA) Tanusitvanykiado
+emailAddress: info@netlock.hu
+-----BEGIN CERTIFICATE-----
+MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx
+ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0
+b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD
+EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz
+aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w
+MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G
+A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh
+Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l
+dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh
+bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq
+eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe
+r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5
+3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd
+vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l
+mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC
+wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg
+hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0
+TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh
+biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg
+ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg
+dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6
+b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl
+c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0
+ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3
+dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu
+ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh
+bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo
+ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3
+Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u
+ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA
+A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ
+MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+
+NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR
+VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY
+83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3
+macqaJVmlaut74nLYKkGEsaUR+ko
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+L: Budapest
+O: NetLock Halozatbiztonsagi Kft.
+OU: Tanusitvanykiadok
+CN: NetLock Uzleti (Class B) Tanusitvanykiado
+-----BEGIN CERTIFICATE-----
+MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx
+ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0
+b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD
+EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05
+OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G
+A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh
+Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l
+dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK
+gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX
+iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc
+Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E
+BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G
+SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu
+b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh
+bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv
+Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln
+aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0
+IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh
+c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph
+biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo
+ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP
+UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj
+YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo
+dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA
+bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06
+sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa
+n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS
+NitjrFgBazMpUIaD8QFI
+-----END CERTIFICATE-----
+
+================================================================
+C: HU
+ST: Hungary
+L: Budapest
+O: NetLock Halozatbiztonsagi Kft.
+OU: Tanusitvanykiadok
+CN: NetLock Kozjegyzoi (Class A) Tanusitvanykiado
+-----BEGIN CERTIFICATE-----
+MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV
+MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe
+TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0
+dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB
+KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0
+N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC
+dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu
+MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL
+b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD
+zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi
+3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8
+WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY
+Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi
+NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC
+ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4
+QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0
+YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz
+aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu
+IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm
+ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg
+ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs
+amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv
+IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3
+Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6
+ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1
+YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg
+dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs
+b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G
+CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO
+xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP
+0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ
+QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk
+f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK
+8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI
+-----END CERTIFICATE-----
+
+================================================================
+C: IE
+O: Baltimore
+OU: CyberTrust
+CN: Baltimore CyberTrust Root
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+================================================================
+C: IL
+O: StartCom Ltd.
+CN: StartCom Certification Authority G2
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1
+OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG
+A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ
+JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD
+vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo
+D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/
+Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW
+RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK
+HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN
+nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM
+0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i
+UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9
+Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg
+TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL
+BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
+2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX
+UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl
+6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK
+9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ
+HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI
+wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY
+XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l
+IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo
+hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr
+so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI
+-----END CERTIFICATE-----
+
+================================================================
+C: IL
+O: StartCom Ltd.
+OU: Secure Digital Certificate Signing
+CN: StartCom Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
+-----END CERTIFICATE-----
+
+================================================================
+C: IL
+O: StartCom Ltd.
+OU: Secure Digital Certificate Signing
+CN: StartCom Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
+ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
+ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
+aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
+YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
+c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
+d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
+CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
+wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
+Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
+0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
+pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
+CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
+P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
+1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
+KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
+8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
+fyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----
+
+================================================================
+C: IT
+L: Milan
+O: Actalis S.p.A./03358520967
+CN: Actalis Authentication Root CA
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+================================================================
+C: JP
+O: Japan Certification Services, Inc.
+CN: SecureSign RootCA11
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr
+MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG
+A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0
+MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp
+Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD
+QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz
+i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8
+h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV
+MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9
+UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni
+8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC
+h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm
+KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ
+X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr
+QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5
+pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN
+QSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+================================================================
+C: JP
+O: Japanese Government
+OU: ApplicationCA
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc
+MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp
+b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT
+AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs
+aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H
+j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K
+f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55
+IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw
+FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht
+QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm
+/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ
+k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ
+MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC
+seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ
+hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+
+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U
+DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj
+B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
+rosot4LKGAfmt1t06SAZf7IbiVQ=
+-----END CERTIFICATE-----
+
+================================================================
+C: JP
+O: SECOM Trust Systems CO.,LTD.
+OU: Security Communication EV RootCA1
+-----BEGIN CERTIFICATE-----
+MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz
+MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N
+IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11
+bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE
+RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO
+zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5
+bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF
+MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1
+VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC
+OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G
+CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW
+tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ
+q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb
+EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+
+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O
+VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
+-----END CERTIFICATE-----
+
+================================================================
+C: JP
+O: SECOM Trust Systems CO.,LTD.
+OU: Security Communication RootCA2
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+================================================================
+C: JP
+O: SECOM Trust.net
+OU: Security Communication RootCA1
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
+MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
+dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
+WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
+VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
+9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
+DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
+Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
+QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
+xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
+A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
+kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
+Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
+Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
+JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
+RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
+-----END CERTIFICATE-----
+
+================================================================
+C: NL
+O: Staat der Nederlanden
+CN: Staat der Nederlanden Root CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX
+DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
+ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
+b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291
+qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp
+uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU
+Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE
+pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp
+5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M
+UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN
+GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy
+5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv
+6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK
+eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6
+B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/
+BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov
+L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG
+SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS
+CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen
+5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897
+IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK
+gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL
++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL
+vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm
+bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk
+N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC
+Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z
+ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: NL
+O: Staat der Nederlanden
+CN: Staat der Nederlanden Root CA
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO
+TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy
+MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk
+ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn
+ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71
+9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO
+hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U
+tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o
+BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh
+SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww
+OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv
+cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA
+7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k
+/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm
+eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6
+u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy
+7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR
+iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==
+-----END CERTIFICATE-----
+
+================================================================
+C: NO
+O: Buypass AS-983163327
+CN: Buypass Class 2 CA 1
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg
+Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL
+MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD
+VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0
+ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX
+l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB
+HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B
+5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3
+WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD
+AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP
+gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+
+DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu
+BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs
+h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk
+LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
+-----END CERTIFICATE-----
+
+================================================================
+C: NO
+O: Buypass AS-983163327
+CN: Buypass Class 2 Root CA
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
+
+================================================================
+C: NO
+O: Buypass AS-983163327
+CN: Buypass Class 3 CA 1
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg
+Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL
+MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD
+VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg
+isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z
+NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI
++MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R
+hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+
+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD
+AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP
+Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s
+EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2
+mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC
+e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow
+dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915
+-----END CERTIFICATE-----
+
+================================================================
+C: NO
+O: Buypass AS-983163327
+CN: Buypass Class 3 Root CA
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
+
+================================================================
+C: PL
+O: Unizeto Sp. z o.o.
+CN: Certum CA
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM
+MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD
+QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM
+MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD
+QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E
+jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo
+ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI
+ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu
+Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg
+AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7
+HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA
+uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa
+TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg
+xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q
+CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x
+O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs
+6GAqm4VKQPNriiTsBhYscw==
+-----END CERTIFICATE-----
+
+================================================================
+C: PL
+O: Unizeto Technologies S.A.
+OU: Certum Certification Authority
+CN: Certum Trusted Network CA
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+================================================================
+C: RO
+O: certSIGN
+OU: certSIGN ROOT CA
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+================================================================
+C: SE
+O: AddTrust AB
+OU: AddTrust External TTP Network
+CN: AddTrust External CA Root
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+================================================================
+C: SE
+O: AddTrust AB
+OU: AddTrust TTP Network
+CN: AddTrust Class 1 CA Root
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
+MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
+VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
+CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
+tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
+dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
+PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
+BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
+MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
+ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
+7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
+43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
+eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
+pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
+WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
+-----END CERTIFICATE-----
+
+================================================================
+C: SE
+O: AddTrust AB
+OU: AddTrust TTP Network
+CN: AddTrust Public CA Root
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx
+MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB
+ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV
+BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV
+6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX
+GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP
+dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH
+1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF
+62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW
+BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL
+MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU
+cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv
+b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6
+IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/
+iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
+GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh
+4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm
+XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
+-----END CERTIFICATE-----
+
+================================================================
+C: SE
+O: AddTrust AB
+OU: AddTrust TTP Network
+CN: AddTrust Qualified CA Root
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1
+MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK
+EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh
+BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq
+xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G
+87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i
+2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U
+WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1
+0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G
+A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr
+pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL
+ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm
+aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv
+hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm
+hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
+dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3
+P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y
+iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no
+xqE=
+-----END CERTIFICATE-----
+
+================================================================
+C: SK
+L: Bratislava
+O: Disig a.s.
+CN: CA Disig
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET
+MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE
+AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw
+CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg
+YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE
+Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX
+mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD
+XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW
+S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp
+FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD
+AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu
+ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z
+ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv
+Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw
+DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6
+yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq
+EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/
+CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB
+EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN
+PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag=
+-----END CERTIFICATE-----
+
+================================================================
+C: SK
+L: Bratislava
+O: Disig a.s.
+CN: CA Disig Root R1
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy
+MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk
+D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o
+OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A
+fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe
+IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n
+oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK
+/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj
+rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD
+3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE
+7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC
+yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd
+qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI
+hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
+xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA
+SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo
+HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB
+emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC
+AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb
+7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x
+DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk
+F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF
+a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT
+Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL
+-----END CERTIFICATE-----
+
+================================================================
+C: SK
+L: Bratislava
+O: Disig a.s.
+CN: CA Disig Root R2
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+================================================================
+C: TR
+L: Gebze - Kocaeli
+O: Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBİTAK
+OU: Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE
+OU: Kamu Sertifikasyon Merkezi
+CN: TÜBİTAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3
+-----BEGIN CERTIFICATE-----
+MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS
+MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp
+bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw
+VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy
+YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy
+dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2
+ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe
+Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls
+aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU
+QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh
+xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0
+aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr
+IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h
+gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK
+O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO
+fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw
+lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
+hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID
+AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP
+NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t
+wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM
+7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh
+gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n
+oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs
+yZyQ2uypQjyttgI=
+-----END CERTIFICATE-----
+
+================================================================
+C: TR
+O: Elektronik Bilgi Guvenligi A.S.
+CN: e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1
+MQswCQYDVQQGEwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxp
+Z2kgQS5TLjE8MDoGA1UEAxMzZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZp
+a2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3MDEwNDExMzI0OFoXDTE3MDEwNDEx
+MzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0cm9uaWsgQmlsZ2kg
+R3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9uaWsg
+U2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdU
+MZTe1RK6UxYC6lhj71vY8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlT
+L/jDj/6z/P2douNffb7tC+Bg62nsM+3YjfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H
+5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAIJjjcJRFHLfO6IxClv7wC
+90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk9Ok0oSy1
+c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoE
+VtstxNulMA0GCSqGSIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLP
+qk/CaOv/gKlR6D1id4k9CnU58W5dF4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S
+/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwqD2fK/A+JYZ1lpTzlvBNbCNvj
+/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4Vwpm+Vganf2X
+KWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
+fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
+-----END CERTIFICATE-----
+
+================================================================
+C: TW
+O: Chunghwa Telecom Co., Ltd.
+OU: ePKI Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+================================================================
+C: TW
+O: Government Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/
+MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow
+PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR
+IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q
+gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy
+yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts
+F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2
+jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx
+ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC
+VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK
+YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH
+EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN
+Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud
+DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE
+MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK
+UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf
+qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK
+ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE
+JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7
+hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1
+EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm
+nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX
+udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz
+ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe
+LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl
+pYYsfPQS
+-----END CERTIFICATE-----
+
+================================================================
+C: TW
+O: TAIWAN-CA
+OU: Root CA
+CN: TWCA Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: AffirmTrust
+CN: AffirmTrust Commercial
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: AffirmTrust
+CN: AffirmTrust Networking
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: AffirmTrust
+CN: AffirmTrust Premium
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: AffirmTrust
+CN: AffirmTrust Premium ECC
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: America Online Inc.
+CN: America Online Root Certification Authority 1
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
+bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2
+MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
+ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk
+hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym
+1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW
+OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb
+2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko
+O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU
+AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF
+Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb
+LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir
+oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C
+MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
+sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: America Online Inc.
+CN: America Online Root Certification Authority 2
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
+bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2
+MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
+ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC
+206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci
+KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2
+JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9
+BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e
+Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B
+PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67
+Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq
+Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ
+o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3
++L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj
+YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj
+FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn
+xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2
+LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc
+obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8
+CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe
+IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA
+DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F
+AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX
+Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb
+AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl
+Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw
+RY8mkaKO/qk=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: DigiCert Inc
+OU: www.digicert.com
+CN: DigiCert Assured ID Root CA
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: DigiCert Inc
+OU: www.digicert.com
+CN: DigiCert Global Root CA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: DigiCert Inc
+OU: www.digicert.com
+CN: DigiCert High Assurance EV Root CA
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Digital Signature Trust
+OU: DST ACES
+CN: DST ACES CA X6
+-----BEGIN CERTIFICATE-----
+MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx
+ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w
+MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD
+VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx
+FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu
+ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7
+gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH
+fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a
+ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT
+ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF
+MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk
+c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto
+dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt
+aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI
+hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk
+QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/
+h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
+nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR
+rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2
+9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Digital Signature Trust Co.
+OU: DSTCA E1
+-----BEGIN CERTIFICATE-----
+MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
+UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
+EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ
+BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
+ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg
+bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ
+j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV
+Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG
+SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
+JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
+RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw
+MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5
+fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i
++DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
+SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN
+QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+
+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Digital Signature Trust Co.
+OU: DSTCA E2
+-----BEGIN CERTIFICATE-----
+MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
+UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
+EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ
+BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
+ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/
+k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso
+LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o
+TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG
+SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
+JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
+RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3
+MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C
+TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5
+WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
+SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR
+xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL
+B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Entrust, Inc.
+OU: www.entrust.net/CPS is incorporated by reference
+OU: (c) 2006 Entrust, Inc.
+CN: Entrust Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Entrust.net
+OU: www.entrust.net/CPS incorp. by ref. (limits liab.)
+OU: (c) 1999 Entrust.net Limited
+CN: Entrust.net Secure Server Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
+ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
+KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
+ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
+MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
+ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
+b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
+bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
+U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
+A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
+I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
+wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
+AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
+oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
+BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
+dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
+MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
+b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
+dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
+MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
+E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
+MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
+hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
+95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
+2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Equifax
+OU: Equifax Secure Certificate Authority
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
+UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
+dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
+MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
+dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
+BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
+cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
+AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
+aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
+ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
+IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
+MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
+A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
+7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
+1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Equifax Secure Inc.
+CN: Equifax Secure Global eBusiness CA-1
+-----BEGIN CERTIFICATE-----
+MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
+ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
+MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
+dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
+c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
+UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
+58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
+o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
+aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
+A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
+Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
+8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Equifax Secure Inc.
+CN: Equifax Secure eBusiness CA-1
+-----BEGIN CERTIFICATE-----
+MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT
+ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw
+MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j
+LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo
+RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu
+WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw
+Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD
+AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK
+eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM
+zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+
+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN
+/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GTE Corporation
+OU: GTE CyberTrust Solutions, Inc.
+CN: GTE CyberTrust Global Root
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
+VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
+bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
+b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
+iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
+r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
+04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
+GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
+3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
+lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+CN: GeoTrust Global CA
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+CN: GeoTrust Global CA 2
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
+IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
+R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
+PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
+Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
+TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
+5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
+S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
+2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
+EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
+EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
+/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
+A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
+abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
+I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
+4iIprn2DQKi6bA==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+CN: GeoTrust Primary Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
+R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
+MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
+AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
+ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
+7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
+kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
+mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
+KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
+6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
+4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
+oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
+UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
+AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+CN: GeoTrust Universal CA
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
+IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
+VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
+cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
+QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
+F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
+c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
+mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
+VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
+teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
+f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
+Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
+nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
+MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
+9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
+IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
+ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
+uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
+Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
+QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
+koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
+ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
+DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
+bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+CN: GeoTrust Universal CA 2
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
+VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
+c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
+WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
+FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
+XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
+se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
+KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
+IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
+y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
+hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
+QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
+Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
+HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
+KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
+L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
+Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
+ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
+T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
+GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
+1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
+OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
+6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
+QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+OU: (c) 2007 GeoTrust Inc. - For authorized use only
+CN: GeoTrust Primary Certification Authority - G2
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
+KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
+MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
+NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
+BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
+MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
+So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
+tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
+CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
+qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
+rD6ogRLQy7rQkgu2npaqBA+K
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: GeoTrust Inc.
+OU: (c) 2008 GeoTrust Inc. - For authorized use only
+CN: GeoTrust Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
+mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
+MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
+BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
+BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
+hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
+5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
+JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
+DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
+huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
+AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
+zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
+kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
+SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
+spki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Network Solutions L.L.C.
+CN: Network Solutions Certificate Authority
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
+MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
+UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
+ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
+c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
+OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
+mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
+BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
+qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
+gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
+bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
+dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
+6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
+h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
+/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
+pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: SecureTrust Corporation
+CN: Secure Global CA
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: SecureTrust Corporation
+CN: SecureTrust CA
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Starfield Technologies, Inc.
+OU: Starfield Class 2 Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: The Go Daddy Group, Inc.
+OU: Go Daddy Class 2 Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VISA
+OU: Visa International Service Association
+CN: Visa eCommerce Root
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr
+MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl
+cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw
+CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h
+dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l
+cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h
+2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E
+lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV
+ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq
+299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t
+vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL
+dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF
+AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR
+zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3
+LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd
+7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw
+++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: Class 1 Public Primary Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f
+zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi
+TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G
+CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW
+NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV
+Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: Class 1 Public Primary Certification Authority - G2
+OU: (c) 1998 VeriSign, Inc. - For authorized use only
+OU: VeriSign Trust Network
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
+c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
+MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
+emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
+DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
+FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg
+UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
+YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
+MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK
+VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm
+Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID
+AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J
+h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul
+uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68
+DzFc6PLZ
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: Class 2 Public Primary Certification Authority - G2
+OU: (c) 1998 VeriSign, Inc. - For authorized use only
+OU: VeriSign Trust Network
+-----BEGIN CERTIFICATE-----
+MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns
+YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
+MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y
+aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe
+Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj
+IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx
+KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM
+HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw
+DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC
+AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji
+nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX
+rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn
+jBJ7xUS0rg==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: Class 3 Public Primary Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
+lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
+AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: Class 3 Public Primary Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
+2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
+2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: Class 3 Public Primary Certification Authority - G2
+OU: (c) 1998 VeriSign, Inc. - For authorized use only
+OU: VeriSign Trust Network
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
+c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
+MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
+emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
+DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
+FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
+UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
+YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
+MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
+pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
+13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
+AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
+U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
+F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
+oJ2daZH9
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 1999 VeriSign, Inc. - For authorized use only
+CN: VeriSign Class 1 Public Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4
+nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO
+8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV
+ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb
+PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2
+6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr
+n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a
+qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4
+wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3
+ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs
+pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4
+E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 1999 VeriSign, Inc. - For authorized use only
+CN: VeriSign Class 2 Public Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy
+aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s
+IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp
+Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV
+BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp
+Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu
+Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g
+Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
+IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU
+J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO
+JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY
+wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o
+koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN
+qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E
+Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe
+xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u
+7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU
+sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI
+sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP
+cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 1999 VeriSign, Inc. - For authorized use only
+CN: VeriSign Class 3 Public Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
+N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
+KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
+kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
+CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
+Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
+imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
+2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
+DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
+F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
+TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 1999 VeriSign, Inc. - For authorized use only
+CN: VeriSign Class 4 Public Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
+GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
+U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
+NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
+ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
+ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
+CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
+g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
+fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
+2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
+bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 2006 VeriSign, Inc. - For authorized use only
+CN: VeriSign Class 3 Public Primary Certification Authority - G5
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 2007 VeriSign, Inc. - For authorized use only
+CN: VeriSign Class 3 Public Primary Certification Authority - G4
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
+SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
+biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
+GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
+fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
+aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
+aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
+4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
+FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: VeriSign, Inc.
+OU: VeriSign Trust Network
+OU: (c) 2008 VeriSign, Inc. - For authorized use only
+CN: VeriSign Universal Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
+IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
+IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
+bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
+9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
+H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
+LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
+/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
+rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
+WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
+exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
+sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
+seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
+4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
+lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
+7M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Wells Fargo
+OU: Wells Fargo Certification Authority
+CN: Wells Fargo Root Certificate Authority
+-----BEGIN CERTIFICATE-----
+MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v
+dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0
+MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww
+KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G
+A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13
+5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE
+SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O
+JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu
+ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE
+AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB
+AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB
+CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw
+b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo
+7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/
+0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7
+nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx
+x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ
+33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: Wells Fargo WellsSecure
+OU: Wells Fargo Bank NA
+CN: WellsSecure Public Root Certificate Authority
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx
+IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs
+cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v
+dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0
+MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl
+bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD
+DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r
+WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU
+Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs
+HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj
+z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf
+SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl
+AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG
+KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P
+AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j
+BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC
+VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX
+ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB
+ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd
+/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB
+A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn
+k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9
+iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv
+2G0xffX8oRAHh84vWdw+WNs=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: thawte, Inc.
+OU: (c) 2007 thawte, Inc. - For authorized use only
+CN: thawte Primary Root CA - G2
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
+MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
+YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
+dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
+BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
+papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
+DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
+KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
+XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: thawte, Inc.
+OU: Certification Services Division
+OU: (c) 2006 thawte, Inc. - For authorized use only
+CN: thawte Primary Root CA
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
+qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
+BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
+NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
+LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
+A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
+W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
+3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
+6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
+Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
+NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
+r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
+DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
+YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
+/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
+LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
+jVaMaA==
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+O: thawte, Inc.
+OU: Certification Services Division
+OU: (c) 2008 thawte, Inc. - For authorized use only
+CN: thawte Primary Root CA - G3
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB
+rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
+BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa
+Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl
+LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u
+MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl
+ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm
+gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
+YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
+b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
+9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
+zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
+OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA
+2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW
+oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c
+KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM
+m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu
+MdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+OU: www.xrampsecurity.com
+O: XRamp Security Services Inc
+CN: XRamp Global Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: Arizona
+L: Scottsdale
+O: GoDaddy.com, Inc.
+CN: Go Daddy Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: Arizona
+L: Scottsdale
+O: Starfield Technologies, Inc.
+CN: Starfield Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: Arizona
+L: Scottsdale
+O: Starfield Technologies, Inc.
+CN: Starfield Services Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: Indiana
+L: Indianapolis
+O: Software in the Public Interest
+OU: hostmaster
+CN: Certificate Authority
+emailAddress: hostmaster@spi-inc.org
+-----BEGIN CERTIFICATE-----
+MIIIDjCCBfagAwIBAgIJAOiOtsn4KhQoMA0GCSqGSIb3DQEBBQUAMIG8MQswCQYD
+VQQGEwJVUzEQMA4GA1UECBMHSW5kaWFuYTEVMBMGA1UEBxMMSW5kaWFuYXBvbGlz
+MSgwJgYDVQQKEx9Tb2Z0d2FyZSBpbiB0aGUgUHVibGljIEludGVyZXN0MRMwEQYD
+VQQLEwpob3N0bWFzdGVyMR4wHAYDVQQDExVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkx
+JTAjBgkqhkiG9w0BCQEWFmhvc3RtYXN0ZXJAc3BpLWluYy5vcmcwHhcNMDgwNTEz
+MDgwNzU2WhcNMTgwNTExMDgwNzU2WjCBvDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMfU29mdHdh
+cmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1hc3RlcjEe
+MBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcNAQkBFhZo
+b3N0bWFzdGVyQHNwaS1pbmMub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEA3DbmR0LCxFF1KYdAw9iOIQbSGE7r7yC9kDyFEBOMKVuUY/b0LfEGQpG5
+GcRCaQi/izZF6igFM0lIoCdDkzWKQdh4s/Dvs24t3dHLfer0dSbTPpA67tfnLAS1
+fOH1fMVO73e9XKKTM5LOfYFIz2u1IiwIg/3T1c87Lf21SZBb9q1NE8re06adU1Fx
+Y0b4ShZcmO4tbZoWoXaQ4mBDmdaJ1mwuepiyCwMs43pPx93jzONKao15Uvr0wa8u
+jyoIyxspgpJyQ7zOiKmqp4pRQ1WFmjcDeJPI8L20QcgHQprLNZd6ioFl3h1UCAHx
+ZFy3FxpRvB7DWYd2GBaY7r/2Z4GLBjXFS21ZGcfSxki+bhQog0oQnBv1b7ypjvVp
+/rLBVcznFMn5WxRTUQfqzj3kTygfPGEJ1zPSbqdu1McTCW9rXRTunYkbpWry9vjQ
+co7qch8vNGopCsUK7BxAhRL3pqXTT63AhYxMfHMgzFMY8bJYTAH1v+pk1Vw5xc5s
+zFNaVrpBDyXfa1C2x4qgvQLCxTtVpbJkIoRRKFauMe5e+wsWTUYFkYBE7axt8Feo
++uthSKDLG7Mfjs3FIXcDhB78rKNDCGOM7fkn77SwXWfWT+3Qiz5dW8mRvZYChD3F
+TbxCP3T9PF2sXEg2XocxLxhsxGjuoYvJWdAY4wCAs1QnLpnwFVMCAwEAAaOCAg8w
+ggILMB0GA1UdDgQWBBQ0cdE41xU2g0dr1zdkQjuOjVKdqzCB8QYDVR0jBIHpMIHm
+gBQ0cdE41xU2g0dr1zdkQjuOjVKdq6GBwqSBvzCBvDELMAkGA1UEBhMCVVMxEDAO
+BgNVBAgTB0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMf
+U29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1h
+c3RlcjEeMBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcN
+AQkBFhZob3N0bWFzdGVyQHNwaS1pbmMub3JnggkA6I62yfgqFCgwDwYDVR0TAQH/
+BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAAcwCQYDVR0SBAIwADAuBglghkgBhvhC
+AQ0EIRYfU29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDAwBglghkgBhvhC
+AQQEIxYhaHR0cHM6Ly9jYS5zcGktaW5jLm9yZy9jYS1jcmwucGVtMDIGCWCGSAGG
++EIBAwQlFiNodHRwczovL2NhLnNwaS1pbmMub3JnL2NlcnQtY3JsLnBlbTAhBgNV
+HREEGjAYgRZob3N0bWFzdGVyQHNwaS1pbmMub3JnMA4GA1UdDwEB/wQEAwIBBjAN
+BgkqhkiG9w0BAQUFAAOCAgEAtM294LnqsgMrfjLp3nI/yUuCXp3ir1UJogxU6M8Y
+PCggHam7AwIvUjki+RfPrWeQswN/2BXja367m1YBrzXU2rnHZxeb1NUON7MgQS4M
+AcRb+WU+wmHo0vBqlXDDxm/VNaSsWXLhid+hoJ0kvSl56WEq2dMeyUakCHhBknIP
+qxR17QnwovBc78MKYiC3wihmrkwvLo9FYyaW8O4x5otVm6o6+YI5HYg84gd1GuEP
+sTC8cTLSOv76oYnzQyzWcsR5pxVIBcDYLXIC48s9Fmq6ybgREOJJhcyWR2AFJS7v
+dVkz9UcZFu/abF8HyKZQth3LZjQl/GaD68W2MEH4RkRiqMEMVObqTFoo5q7Gt/5/
+O5aoLu7HaD7dAD0prypjq1/uSSotxdz70cbT0ZdWUoa2lOvUYFG3/B6bzAKb1B+P
++UqPti4oOxfMxaYF49LTtcYDyeFIQpvLP+QX4P4NAZUJurgNceQJcHdC2E3hQqlg
+g9cXiUPS1N2nGLar1CQlh7XU4vwuImm9rWgs/3K1mKoGnOcqarihk3bOsPN/nOHg
+T7jYhkalMwIsJWE3KpLIrIF0aGOHM3a9BX9e1dUCbb2v/ypaqknsmHlHU5H2DjRa
+yaXG67Ljxay2oHA1u8hRadDytaIybrw/oDc5fHE2pgXfDBLkFqfF1stjo5VwP+YE
+o2A=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: UT
+L: Salt Lake City
+O: The USERTRUST Network
+OU: http://www.usertrust.com
+CN: UTN - DATACorp SGC
+-----BEGIN CERTIFICATE-----
+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB
+kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw
+IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG
+EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD
+VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu
+dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6
+E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ
+D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK
+4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq
+lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW
+bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB
+o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT
+MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js
+LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr
+BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB
+AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj
+j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH
+KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv
+2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3
+mfnGV/TJVTl4uix5yaaIK/QI
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: UT
+L: Salt Lake City
+O: The USERTRUST Network
+OU: http://www.usertrust.com
+CN: UTN-USERFirst-Client Authentication and Email
+-----BEGIN CERTIFICATE-----
+MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB
+rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt
+Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa
+Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV
+BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l
+dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE
+AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B
+YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9
+hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l
+L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm
+SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM
+1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws
+6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw
+Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50
+aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
+AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u
+7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0
+xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ
+rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim
+eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk
+USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ=
+-----END CERTIFICATE-----
+
+================================================================
+C: US
+ST: UT
+L: Salt Lake City
+O: The USERTRUST Network
+OU: http://www.usertrust.com
+CN: UTN-USERFirst-Hardware
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
+A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
+MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
+d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
+cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
+0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
+M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
+MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
+oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
+DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
+oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
+dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
+bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
+BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
+//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
+CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
+CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
+3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
+KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
+-----END CERTIFICATE-----
+
+================================================================
+C: ZA
+ST: Western Cape
+L: Cape Town
+O: Thawte Consulting cc
+OU: Certification Services Division
+CN: Thawte Premium Server CA
+emailAddress: premium-server@thawte.com
+-----BEGIN CERTIFICATE-----
+MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
+FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
+VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
+dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
+MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
+MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
+A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
+b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
+cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
+bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
+VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
+ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
+uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
+9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
+hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
+pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
+-----END CERTIFICATE-----
+
+================================================================
+C: ZA
+ST: Western Cape
+L: Cape Town
+O: Thawte Consulting cc
+OU: Certification Services Division
+CN: Thawte Server CA
+emailAddress: server-certs@thawte.com
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx
+FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
+VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm
+MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx
+MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3
+dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl
+cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3
+DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91
+yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX
+L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj
+EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG
+7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e
+QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ
+qdq5snUb9kLy78fyGPmJvKP/iiMucEc=
+-----END CERTIFICATE-----
+
+================================================================
+C: ch
+O: Swisscom
+OU: Digital Certificate Services
+CN: Swisscom Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk
+MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0
+YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg
+Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT
+AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp
+Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9
+m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih
+FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/
+TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F
+EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco
+kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu
+HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF
+vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo
+19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC
+L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW
+bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX
+JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw
+FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
+BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc
+K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf
+ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik
+Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB
+sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e
+3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR
+ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip
+mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH
+b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf
+rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms
+hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y
+zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6
+MBr1mmz0DlP5OlvRHA==
+-----END CERTIFICATE-----
+
+================================================================
+C: ch
+O: Swisscom
+OU: Digital Certificate Services
+CN: Swisscom Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk
+MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0
+YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg
+Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT
+AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp
+Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr
+jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r
+0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f
+2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP
+ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF
+y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA
+tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL
+6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0
+uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL
+acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh
+k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q
+VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw
+FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O
+BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh
+b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R
+fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv
+/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI
+REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx
+srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv
+aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT
+woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n
+Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W
+t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N
+8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2
+9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5
+wSsSnqaeG8XmDtkx2Q==
+-----END CERTIFICATE-----
+
+================================================================
+C: ch
+O: Swisscom
+OU: Digital Certificate Services
+CN: Swisscom Root EV CA 2
+-----BEGIN CERTIFICATE-----
+MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw
+ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp
+dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290
+IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD
+VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy
+dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg
+MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx
+UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD
+1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH
+oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR
+HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/
+5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv
+idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL
+OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC
+NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f
+46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB
+UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth
+7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G
+A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
+MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB
+bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x
+XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T
+PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0
+Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70
+WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL
+Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm
+7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S
+nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN
+vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB
+WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI
+fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb
+I+2ksx0WckNLIOFZfsLorSa/ovc=
+-----END CERTIFICATE-----
+
+================================================================
+CN: ACEDICOM Root
+OU: PKI
+O: EDICOM
+C: ES
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE
+AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x
+CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW
+MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF
+RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
+AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7
+09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7
+XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P
+Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK
+t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb
+X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28
+MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU
+fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI
+2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH
+K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae
+ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP
+BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ
+MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw
+RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
+bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm
+fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3
+gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe
+I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i
+5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi
+ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn
+MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ
+o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6
+zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN
+GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt
+r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK
+Z05phkOTOPu220+DkdRgfks+KzgHVZhepA==
+-----END CERTIFICATE-----
+
+================================================================
+CN: ComSign CA
+O: ComSign
+C: IL
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0
+MRMwEQYDVQQDEwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQG
+EwJJTDAeFw0wNDAzMjQxMTMyMThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMT
+CkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNpZ24xCzAJBgNVBAYTAklMMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49qROR+WCf4C9DklBKK
+8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTyP2Q2
+98CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb
+2CEJKHxNGGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxC
+ejVb7Us6eva1jsz/D3zkYDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7Kpi
+Xd3DTKaCQeQzC6zJMw9kglcq/QytNuEMrkvF7zuZ2SOzW120V+x0cAwqTwIDAQAB
+o4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Zl
+ZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0PAQH/BAQD
+AgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRL
+AZs+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWd
+foPPbrxHbvUanlR2QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0M
+cXS6hMTXcpuEfDhOZAYnKuGntewImbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq
+8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb/627HOkthIDYIb6FUtnUdLlp
+hbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VGzT2ouvDzuFYk
+Res3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U
+AGegcQCCSA==
+-----END CERTIFICATE-----
+
+================================================================
+CN: ComSign Secured CA
+O: ComSign
+C: IL
+-----BEGIN CERTIFICATE-----
+MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw
+PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu
+MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx
+GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL
+MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf
+HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh
+gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW
+v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue
+Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr
+9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt
+6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7
+MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl
+Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58
+ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq
+hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p
+iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC
+dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL
+kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL
+hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz
+OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==
+-----END CERTIFICATE-----
+
+================================================================
+CN: EBG Elektronik Sertifika Hizmet Sağlayıcısı
+O: EBG Bilişim Teknolojileri ve Hizmetleri A.Ş.
+C: TR
+-----BEGIN CERTIFICATE-----
+MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV
+BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
+c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt
+ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4
+MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg
+SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl
+a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h
+4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk
+tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s
+tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL
+dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4
+c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um
+TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z
++kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O
+Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW
+OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW
+fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2
+l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw
+FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+
+8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI
+6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO
+TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME
+wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY
+Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn
+xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q
+DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q
+Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t
+hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4
+7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7
+QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT
+-----END CERTIFICATE-----
+
+================================================================
+CN: TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
+C: TR
+L: ANKARA
+O: (c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
+-----BEGIN CERTIFICATE-----
+MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc
+UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
+c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg
+MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8
+dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz
+MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy
+dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD
+VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg
+xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu
+xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7
+XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k
+heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J
+YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C
+urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1
+JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51
+b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV
+9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7
+kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh
+fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy
+B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA
+aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS
+RGQDJereW26fyfJOrN3H
+-----END CERTIFICATE-----
+
+================================================================
+CN: TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
+C: TR
+L: Ankara
+O: TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007
+-----BEGIN CERTIFICATE-----
+MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc
+UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
+c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS
+S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg
+SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx
+OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry
+b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC
+VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE
+sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F
+ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY
+KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG
++7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG
+HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P
+IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M
+733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk
+Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G
+CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW
+AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
+aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5
+mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa
+XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ
+qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9
+-----END CERTIFICATE-----
+
+================================================================
+CN: TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
+C: TR
+L: Ankara
+O: TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005
+-----BEGIN CERTIFICATE-----
+MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc
+UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
+c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS
+S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg
+SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3
+WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv
+bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU
+UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw
+bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe
+LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef
+J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh
+R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ
+Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX
+JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p
+zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S
+Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq
+ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4
+Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz
+gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH
+uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS
+y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI=
+-----END CERTIFICATE-----
+
+================================================================
+L: ValiCert Validation Network
+O: ValiCert, Inc.
+OU: ValiCert Class 1 Policy Validation Authority
+CN: http://www.valicert.com/
+emailAddress: info@valicert.com
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy
+NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y
+LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+
+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y
+TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0
+LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW
+I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw
+nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI
+-----END CERTIFICATE-----
+
+================================================================
+L: ValiCert Validation Network
+O: ValiCert, Inc.
+OU: ValiCert Class 2 Policy Validation Authority
+CN: http://www.valicert.com/
+emailAddress: info@valicert.com
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
+NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
+dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
+WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
+v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
+UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
+IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
+W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
+-----END CERTIFICATE-----
+
+================================================================
+L: ValiCert Validation Network
+O: ValiCert, Inc.
+OU: ValiCert Class 3 Policy Validation Authority
+CN: http://www.valicert.com/
+emailAddress: info@valicert.com
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy
+NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD
+cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs
+2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY
+JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE
+Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ
+n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A
+PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu
+-----END CERTIFICATE-----
+
+================================================================
+O: Cybertrust, Inc
+CN: Cybertrust Global Root
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+================================================================
+O: Digital Signature Trust Co.
+CN: DST Root CA X3
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+================================================================
+O: Entrust.net
+OU: www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)
+OU: (c) 1999 Entrust.net Limited
+CN: Entrust.net Certification Authority (2048)
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+================================================================
+O: RSA Security Inc
+OU: RSA Security 2048 V3
+-----BEGIN CERTIFICATE-----
+MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6
+MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp
+dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX
+BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy
+MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp
+eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg
+/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl
+wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh
+AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2
+PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu
+AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR
+MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc
+HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/
+Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+
+f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO
+rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch
+6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3
+7CAFYd4=
+-----END CERTIFICATE-----
+
+================================================================
+OU: GlobalSign Root CA - R2
+O: GlobalSign
+CN: GlobalSign
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+================================================================
+OU: GlobalSign Root CA - R3
+O: GlobalSign
+CN: GlobalSign
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+================================================================
+emailAddress: contacto@procert.net.ve
+L: Chacao
+ST: Miranda
+OU: Proveedor de Certificados PROCERT
+O: Sistema Nacional de Certificacion Electronica
+C: VE
+CN: PSCProcert
+-----BEGIN CERTIFICATE-----
+MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1
+dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s
+YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz
+dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0
+aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh
+IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ
+KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEw
+MFoXDTIwMTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHBy
+b2NlcnQubmV0LnZlMQ8wDQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGEx
+KjAoBgNVBAsTIVByb3ZlZWRvciBkZSBDZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQG
+A1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9u
+aWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo9
+7BVCwfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74
+BCXfgI8Qhd19L3uA3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38G
+ieU89RLAu9MLmV+QfI4tL3czkkohRqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9
+JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmOEO8GqQKJ/+MMbpfg353bIdD0
+PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG20qCZyFSTXai2
+0b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
+0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/
+6mnbVSKVUyqUtd+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1m
+v6JpIzi4mWCZDlZTOpx+FIywBm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7
+K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvpr2uKGcfLFFb14dq12fy/czja+eev
+bqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/AgEBMDcGA1UdEgQw
+MC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0w
+MB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFD
+gBStuyIdxuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0
+b3JpZGFkIGRlIENlcnRpZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xh
+bm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0
+cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRp
+ZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEg
+ZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkq
+hkiG9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQD
+AgEGME0GA1UdEQRGMESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0w
+MDAwMDKgGwYFYIZeAgKgEgwQUklGLUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEag
+RKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9sY3IvQ0VSVElGSUNBRE8t
+UkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNyYWl6LnN1c2Nl
+cnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
+Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsG
+AQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcN
+AQELBQADggIBACtZ6yKZu4SqT96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS
+1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmNg7+mvTV+LFwxNG9s2/NkAZiqlCxB
+3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4quxtxj7mkoP3Yldmv
+Wb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1n8Gh
+HVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHm
+pHmJWhSnFFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXz
+sOfIt+FTvZLm8wyWuevo5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bE
+qCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq3TNWOByyrYDT13K9mmyZY+gAu0F2Bbdb
+mRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5poLWccret9W6aAjtmcz9
+opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3YeMLEYC/H
+YvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
+-----END CERTIFICATE-----
+
+================================================================
+emailAddress: pki@sk.ee
+C: EE
+O: AS Sertifitseerimiskeskus
+CN: Juur-SK
+-----BEGIN CERTIFICATE-----
+MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN
+AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp
+dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw
+MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw
+CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ
+MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB
+SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz
+ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH
+LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP
+PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL
+2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w
+ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC
+MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk
+AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0
+AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz
+AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz
+AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f
+BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE
+FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY
+P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi
+CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g
+kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95
+HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS
+na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q
+qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z
+TbvGRNs2yyqcjg==
+-----END CERTIFICATE-----
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/.travis.yml b/public/system/storage/vendor/guzzlehttp/guzzle/.travis.yml
new file mode 100644
index 0000000..607b00a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/.travis.yml
@@ -0,0 +1,52 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+ - 7.2
+ - hhvm
+ - nightly
+
+env:
+ global:
+ - TEST_COMMAND="composer test"
+
+before_script:
+ - curl --version
+ - pear config-set php_ini ~/.phpenv/versions/`php -r 'echo phpversion();'`/etc/php.ini || echo 'Error modifying PEAR'
+ - pecl install uri_template || echo 'Error installing uri_template'
+ # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
+ - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
+ - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
+ - ~/.nvm/nvm.sh install v0.6.14
+ - ~/.nvm/nvm.sh run v0.6.14
+
+script: $TEST_COMMAND
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ - php: nightly
+ fast_finish: true
+ include:
+ - php: 5.4
+ env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci"
+
+before_deploy:
+ - make package
+
+deploy:
+ provider: releases
+ api_key:
+ secure: UpypqlYgsU68QT/x40YzhHXvzWjFwCNo9d+G8KAdm7U9+blFfcWhV1aMdzugvPMl6woXgvJj7qHq5tAL4v6oswCORhpSBfLgOQVFaica5LiHsvWlAedOhxGmnJqMTwuepjBCxXhs3+I8Kof1n4oUL9gKytXjOVCX/f7XU1HiinU=
+ file:
+ - build/artifacts/guzzle.phar
+ - build/artifacts/guzzle.zip
+ on:
+ repo: guzzle/guzzle
+ tags: true
+ all_branches: true
+ php: 5.4
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/CHANGELOG.md b/public/system/storage/vendor/guzzlehttp/guzzle/CHANGELOG.md
new file mode 100644
index 0000000..56ec2b7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/CHANGELOG.md
@@ -0,0 +1,1071 @@
+# CHANGELOG
+
+## 5.3.3 - 2018-07-31
+
+* Fix bug parsing 0 epoch expiry times
+* Fix PHP 7.3 compatibility
+
+## 5.3.2 - 2018-01-15
+
+* Improve tests
+* Fix react promise dependency
+* Fix PHP 7 compatibility
+
+## 5.3.1 - 2016-07-18
+
+* Address HTTP_PROXY security vulnerability, CVE-2016-5385:
+ https://httpoxy.org/
+* Event name fix: https://github.com/guzzle/guzzle/commit/fcae91ff31de41e312fe113ec3acbcda31b2622e
+* Response header case sensitivity fix: https://github.com/guzzle/guzzle/commit/043eeadf20ee40ddc6712faee4d3957a91f2b041
+
+## 5.3.0 - 2015-05-19
+
+* Mock now supports `save_to`
+* Marked `AbstractRequestEvent::getTransaction()` as public.
+* Fixed a bug in which multiple headers using different casing would overwrite
+ previous headers in the associative array.
+* Added `Utils::getDefaultHandler()`
+* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
+* URL scheme is now always lowercased.
+
+## 5.2.0 - 2015-01-27
+
+* Added `AppliesHeadersInterface` to make applying headers to a request based
+ on the body more generic and not specific to `PostBodyInterface`.
+* Reduced the number of stack frames needed to send requests.
+* Nested futures are now resolved in the client rather than the RequestFsm
+* Finishing state transitions is now handled in the RequestFsm rather than the
+ RingBridge.
+* Added a guard in the Pool class to not use recursion for request retries.
+
+## 5.1.0 - 2014-12-19
+
+* Pool class no longer uses recursion when a request is intercepted.
+* The size of a Pool can now be dynamically adjusted using a callback.
+ See https://github.com/guzzle/guzzle/pull/943.
+* Setting a request option to `null` when creating a request with a client will
+ ensure that the option is not set. This allows you to overwrite default
+ request options on a per-request basis.
+ See https://github.com/guzzle/guzzle/pull/937.
+* Added the ability to limit which protocols are allowed for redirects by
+ specifying a `protocols` array in the `allow_redirects` request option.
+* Nested futures due to retries are now resolved when waiting for synchronous
+ responses. See https://github.com/guzzle/guzzle/pull/947.
+* `"0"` is now an allowed URI path. See
+ https://github.com/guzzle/guzzle/pull/935.
+* `Query` no longer typehints on the `$query` argument in the constructor,
+ allowing for strings and arrays.
+* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
+ specific exceptions if necessary.
+
+## 5.0.3 - 2014-11-03
+
+This change updates query strings so that they are treated as un-encoded values
+by default where the value represents an un-encoded value to send over the
+wire. A Query object then encodes the value before sending over the wire. This
+means that even value query string values (e.g., ":") are url encoded. This
+makes the Query class match PHP's http_build_query function. However, if you
+want to send requests over the wire using valid query string characters that do
+not need to be encoded, then you can provide a string to Url::setQuery() and
+pass true as the second argument to specify that the query string is a raw
+string that should not be parsed or encoded (unless a call to getQuery() is
+subsequently made, forcing the query-string to be converted into a Query
+object).
+
+## 5.0.2 - 2014-10-30
+
+* Added a trailing `\r\n` to multipart/form-data payloads. See
+ https://github.com/guzzle/guzzle/pull/871
+* Added a `GuzzleHttp\Pool::send()` convenience method to match the docs.
+* Status codes are now returned as integers. See
+ https://github.com/guzzle/guzzle/issues/881
+* No longer overwriting an existing `application/x-www-form-urlencoded` header
+ when sending POST requests, allowing for customized headers. See
+ https://github.com/guzzle/guzzle/issues/877
+* Improved path URL serialization.
+
+ * No longer double percent-encoding characters in the path or query string if
+ they are already encoded.
+ * Now properly encoding the supplied path to a URL object, instead of only
+ encoding ' ' and '?'.
+ * Note: This has been changed in 5.0.3 to now encode query string values by
+ default unless the `rawString` argument is provided when setting the query
+ string on a URL: Now allowing many more characters to be present in the
+ query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A
+
+## 5.0.1 - 2014-10-16
+
+Bugfix release.
+
+* Fixed an issue where connection errors still returned response object in
+ error and end events event though the response is unusable. This has been
+ corrected so that a response is not returned in the `getResponse` method of
+ these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867
+* Fixed an issue where transfer statistics were not being populated in the
+ RingBridge. https://github.com/guzzle/guzzle/issues/866
+
+## 5.0.0 - 2014-10-12
+
+Adding support for non-blocking responses and some minor API cleanup.
+
+### New Features
+
+* Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.
+* Added a public API for creating a default HTTP adapter.
+* Updated the redirect plugin to be non-blocking so that redirects are sent
+ concurrently. Other plugins like this can now be updated to be non-blocking.
+* Added a "progress" event so that you can get upload and download progress
+ events.
+* Added `GuzzleHttp\Pool` which implements FutureInterface and transfers
+ requests concurrently using a capped pool size as efficiently as possible.
+* Added `hasListeners()` to EmitterInterface.
+* Removed `GuzzleHttp\ClientInterface::sendAll` and marked
+ `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the
+ recommended way).
+
+### Breaking changes
+
+The breaking changes in this release are relatively minor. The biggest thing to
+look out for is that request and response objects no longer implement fluent
+interfaces.
+
+* Removed the fluent interfaces (i.e., `return $this`) from requests,
+ responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`,
+ `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and
+ `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of
+ why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/.
+ This also makes the Guzzle message interfaces compatible with the current
+ PSR-7 message proposal.
+* Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except
+ for the HTTP request functions from function.php, these functions are now
+ implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode`
+ moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to
+ `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to
+ `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be
+ `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php
+ caused problems for many users: they aren't PSR-4 compliant, require an
+ explicit include, and needed an if-guard to ensure that the functions are not
+ declared multiple times.
+* Rewrote adapter layer.
+ * Removing all classes from `GuzzleHttp\Adapter`, these are now
+ implemented as callables that are stored in `GuzzleHttp\Ring\Client`.
+ * Removed the concept of "parallel adapters". Sending requests serially or
+ concurrently is now handled using a single adapter.
+ * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The
+ Transaction object now exposes the request, response, and client as public
+ properties. The getters and setters have been removed.
+* Removed the "headers" event. This event was only useful for changing the
+ body a response once the headers of the response were known. You can implement
+ a similar behavior in a number of ways. One example might be to use a
+ FnStream that has access to the transaction being sent. For example, when the
+ first byte is written, you could check if the response headers match your
+ expectations, and if so, change the actual stream body that is being
+ written to.
+* Removed the `asArray` parameter from
+ `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+ value as an array, then use the newly added `getHeaderAsArray()` method of
+ `MessageInterface`. This change makes the Guzzle interfaces compatible with
+ the PSR-7 interfaces.
+* `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add
+ custom request options using double-dispatch (this was an implementation
+ detail). Instead, you should now provide an associative array to the
+ constructor which is a mapping of the request option name mapping to a
+ function that applies the option value to a request.
+* Removed the concept of "throwImmediately" from exceptions and error events.
+ This control mechanism was used to stop a transfer of concurrent requests
+ from completing. This can now be handled by throwing the exception or by
+ cancelling a pool of requests or each outstanding future request individually.
+* Updated to "GuzzleHttp\Streams" 3.0.
+ * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a
+ `maxLen` parameter. This update makes the Guzzle streams project
+ compatible with the current PSR-7 proposal.
+ * `GuzzleHttp\Stream\Stream::__construct`,
+ `GuzzleHttp\Stream\Stream::factory`, and
+ `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second
+ argument. They now accept an associative array of options, including the
+ "size" key and "metadata" key which can be used to provide custom metadata.
+
+## 4.2.2 - 2014-09-08
+
+* Fixed a memory leak in the CurlAdapter when reusing cURL handles.
+* No longer using `request_fulluri` in stream adapter proxies.
+* Relative redirects are now based on the last response, not the first response.
+
+## 4.2.1 - 2014-08-19
+
+* Ensuring that the StreamAdapter does not always add a Content-Type header
+* Adding automated github releases with a phar and zip
+
+## 4.2.0 - 2014-08-17
+
+* Now merging in default options using a case-insensitive comparison.
+ Closes https://github.com/guzzle/guzzle/issues/767
+* Added the ability to automatically decode `Content-Encoding` response bodies
+ using the `decode_content` request option. This is set to `true` by default
+ to decode the response body if it comes over the wire with a
+ `Content-Encoding`. Set this value to `false` to disable decoding the
+ response content, and pass a string to provide a request `Accept-Encoding`
+ header and turn on automatic response decoding. This feature now allows you
+ to pass an `Accept-Encoding` header in the headers of a request but still
+ disable automatic response decoding.
+ Closes https://github.com/guzzle/guzzle/issues/764
+* Added the ability to throw an exception immediately when transferring
+ requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760
+* Updating guzzlehttp/streams dependency to ~2.1
+* No longer utilizing the now deprecated namespaced methods from the stream
+ package.
+
+## 4.1.8 - 2014-08-14
+
+* Fixed an issue in the CurlFactory that caused setting the `stream=false`
+ request option to throw an exception.
+ See: https://github.com/guzzle/guzzle/issues/769
+* TransactionIterator now calls rewind on the inner iterator.
+ See: https://github.com/guzzle/guzzle/pull/765
+* You can now set the `Content-Type` header to `multipart/form-data`
+ when creating POST requests to force multipart bodies.
+ See https://github.com/guzzle/guzzle/issues/768
+
+## 4.1.7 - 2014-08-07
+
+* Fixed an error in the HistoryPlugin that caused the same request and response
+ to be logged multiple times when an HTTP protocol error occurs.
+* Ensuring that cURL does not add a default Content-Type when no Content-Type
+ has been supplied by the user. This prevents the adapter layer from modifying
+ the request that is sent over the wire after any listeners may have already
+ put the request in a desired state (e.g., signed the request).
+* Throwing an exception when you attempt to send requests that have the
+ "stream" set to true in parallel using the MultiAdapter.
+* Only calling curl_multi_select when there are active cURL handles. This was
+ previously changed and caused performance problems on some systems due to PHP
+ always selecting until the maximum select timeout.
+* Fixed a bug where multipart/form-data POST fields were not correctly
+ aggregated (e.g., values with "&").
+
+## 4.1.6 - 2014-08-03
+
+* Added helper methods to make it easier to represent messages as strings,
+ including getting the start line and getting headers as a string.
+
+## 4.1.5 - 2014-08-02
+
+* Automatically retrying cURL "Connection died, retrying a fresh connect"
+ errors when possible.
+* cURL implementation cleanup
+* Allowing multiple event subscriber listeners to be registered per event by
+ passing an array of arrays of listener configuration.
+
+## 4.1.4 - 2014-07-22
+
+* Fixed a bug that caused multi-part POST requests with more than one field to
+ serialize incorrectly.
+* Paths can now be set to "0"
+* `ResponseInterface::xml` now accepts a `libxml_options` option and added a
+ missing default argument that was required when parsing XML response bodies.
+* A `save_to` stream is now created lazily, which means that files are not
+ created on disk unless a request succeeds.
+
+## 4.1.3 - 2014-07-15
+
+* Various fixes to multipart/form-data POST uploads
+* Wrapping function.php in an if-statement to ensure Guzzle can be used
+ globally and in a Composer install
+* Fixed an issue with generating and merging in events to an event array
+* POST headers are only applied before sending a request to allow you to change
+ the query aggregator used before uploading
+* Added much more robust query string parsing
+* Fixed various parsing and normalization issues with URLs
+* Fixing an issue where multi-valued headers were not being utilized correctly
+ in the StreamAdapter
+
+## 4.1.2 - 2014-06-18
+
+* Added support for sending payloads with GET requests
+
+## 4.1.1 - 2014-06-08
+
+* Fixed an issue related to using custom message factory options in subclasses
+* Fixed an issue with nested form fields in a multi-part POST
+* Fixed an issue with using the `json` request option for POST requests
+* Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar`
+
+## 4.1.0 - 2014-05-27
+
+* Added a `json` request option to easily serialize JSON payloads.
+* Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON.
+* Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`.
+* Added the ability to provide an emitter to a client in the client constructor.
+* Added the ability to persist a cookie session using $_SESSION.
+* Added a trait that can be used to add event listeners to an iterator.
+* Removed request method constants from RequestInterface.
+* Fixed warning when invalid request start-lines are received.
+* Updated MessageFactory to work with custom request option methods.
+* Updated cacert bundle to latest build.
+
+4.0.2 (2014-04-16)
+------------------
+
+* Proxy requests using the StreamAdapter now properly use request_fulluri (#632)
+* Added the ability to set scalars as POST fields (#628)
+
+## 4.0.1 - 2014-04-04
+
+* The HTTP status code of a response is now set as the exception code of
+ RequestException objects.
+* 303 redirects will now correctly switch from POST to GET requests.
+* The default parallel adapter of a client now correctly uses the MultiAdapter.
+* HasDataTrait now initializes the internal data array as an empty array so
+ that the toArray() method always returns an array.
+
+## 4.0.0 - 2014-03-29
+
+* For more information on the 4.0 transition, see:
+ http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/
+* For information on changes and upgrading, see:
+ https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+* Added `GuzzleHttp\batch()` as a convenience function for sending requests in
+ parallel without needing to write asynchronous code.
+* Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`.
+ You can now pass a callable or an array of associative arrays where each
+ associative array contains the "fn", "priority", and "once" keys.
+
+## 4.0.0.rc-2 - 2014-03-25
+
+* Removed `getConfig()` and `setConfig()` from clients to avoid confusion
+ around whether things like base_url, message_factory, etc. should be able to
+ be retrieved or modified.
+* Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface
+* functions.php functions were renamed using snake_case to match PHP idioms
+* Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and
+ `GUZZLE_CURL_SELECT_TIMEOUT` environment variables
+* Added the ability to specify custom `sendAll()` event priorities
+* Added the ability to specify custom stream context options to the stream
+ adapter.
+* Added a functions.php function for `get_path()` and `set_path()`
+* CurlAdapter and MultiAdapter now use a callable to generate curl resources
+* MockAdapter now properly reads a body and emits a `headers` event
+* Updated Url class to check if a scheme and host are set before adding ":"
+ and "//". This allows empty Url (e.g., "") to be serialized as "".
+* Parsing invalid XML no longer emits warnings
+* Curl classes now properly throw AdapterExceptions
+* Various performance optimizations
+* Streams are created with the faster `Stream\create()` function
+* Marked deprecation_proxy() as internal
+* Test server is now a collection of static methods on a class
+
+## 4.0.0-rc.1 - 2014-03-15
+
+* See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+
+## 3.8.1 - 2014-01-28
+
+* Bug: Always using GET requests when redirecting from a 303 response
+* Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in
+ `Guzzle\Http\ClientInterface::setSslVerification()`
+* Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL
+* Bug: The body of a request can now be set to `"0"`
+* Sending PHP stream requests no longer forces `HTTP/1.0`
+* Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of
+ each sub-exception
+* Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than
+ clobbering everything).
+* Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)
+* Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.
+ For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.
+* Now properly escaping the regular expression delimiter when matching Cookie domains.
+* Network access is now disabled when loading XML documents
+
+## 3.8.0 - 2013-12-05
+
+* Added the ability to define a POST name for a file
+* JSON response parsing now properly walks additionalProperties
+* cURL error code 18 is now retried automatically in the BackoffPlugin
+* Fixed a cURL error when URLs contain fragments
+* Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were
+ CurlExceptions
+* CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)
+* Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`
+* Fixed a bug that was encountered when parsing empty header parameters
+* UriTemplate now has a `setRegex()` method to match the docs
+* The `debug` request parameter now checks if it is truthy rather than if it exists
+* Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin
+* Added the ability to combine URLs using strict RFC 3986 compliance
+* Command objects can now return the validation errors encountered by the command
+* Various fixes to cache revalidation (#437 and 29797e5)
+* Various fixes to the AsyncPlugin
+* Cleaned up build scripts
+
+## 3.7.4 - 2013-10-02
+
+* Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)
+* Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp
+ (see https://github.com/aws/aws-sdk-php/issues/147)
+* Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots
+* Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)
+* Updated the bundled cacert.pem (#419)
+* OauthPlugin now supports adding authentication to headers or query string (#425)
+
+## 3.7.3 - 2013-09-08
+
+* Added the ability to get the exception associated with a request/command when using `MultiTransferException` and
+ `CommandTransferException`.
+* Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description
+* Schemas are only injected into response models when explicitly configured.
+* No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of
+ an EntityBody.
+* Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator.
+* Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`.
+* Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()
+* Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin
+* Bug fix: Visiting XML attributes first before visiting XML children when serializing requests
+* Bug fix: Properly parsing headers that contain commas contained in quotes
+* Bug fix: mimetype guessing based on a filename is now case-insensitive
+
+## 3.7.2 - 2013-08-02
+
+* Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander
+ See https://github.com/guzzle/guzzle/issues/371
+* Bug fix: Cookie domains are now matched correctly according to RFC 6265
+ See https://github.com/guzzle/guzzle/issues/377
+* Bug fix: GET parameters are now used when calculating an OAuth signature
+* Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted
+* `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched
+* `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.
+ See https://github.com/guzzle/guzzle/issues/379
+* Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See
+ https://github.com/guzzle/guzzle/pull/380
+* cURL multi cleanup and optimizations
+
+## 3.7.1 - 2013-07-05
+
+* Bug fix: Setting default options on a client now works
+* Bug fix: Setting options on HEAD requests now works. See #352
+* Bug fix: Moving stream factory before send event to before building the stream. See #353
+* Bug fix: Cookies no longer match on IP addresses per RFC 6265
+* Bug fix: Correctly parsing header parameters that are in `<>` and quotes
+* Added `cert` and `ssl_key` as request options
+* `Host` header can now diverge from the host part of a URL if the header is set manually
+* `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter
+* OAuth parameters are only added via the plugin if they aren't already set
+* Exceptions are now thrown when a URL cannot be parsed
+* Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails
+* Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin
+
+## 3.7.0 - 2013-06-10
+
+* See UPGRADING.md for more information on how to upgrade.
+* Requests now support the ability to specify an array of $options when creating a request to more easily modify a
+ request. You can pass a 'request.options' configuration setting to a client to apply default request options to
+ every request created by a client (e.g. default query string variables, headers, curl options, etc.).
+* Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
+ See `Guzzle\Http\StaticClient::mount`.
+* Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
+ created by a command (e.g. custom headers, query string variables, timeout settings, etc.).
+* Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
+ headers of a response
+* Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
+ (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
+* ServiceBuilders now support storing and retrieving arbitrary data
+* CachePlugin can now purge all resources for a given URI
+* CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
+* CachePlugin now uses the Vary header to determine if a resource is a cache hit
+* `Guzzle\Http\Message\Response` now implements `\Serializable`
+* Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
+* `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
+* Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
+* Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size
+* `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message
+* Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older
+ Symfony users can still use the old version of Monolog.
+* Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`.
+ Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.
+* Several performance improvements to `Guzzle\Common\Collection`
+* Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+ createRequest, head, delete, put, patch, post, options, prepareRequest
+* Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+* Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+* Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+* Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+ default `array()`
+* Added `Guzzle\Stream\StreamInterface::isRepeatable`
+* Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+ $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+ $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.
+* Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
+* Removed `Guzzle\Http\ClientInterface::expandTemplate()`
+* Removed `Guzzle\Http\ClientInterface::setRequestFactory()`
+* Removed `Guzzle\Http\ClientInterface::getCurlMulti()`
+* Removed `Guzzle\Http\Message\RequestInterface::canCache`
+* Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`
+* Removed `Guzzle\Http\Message\RequestInterface::isRedirect`
+* Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
+* You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting
+ `Guzzle\Common\Version::$emitWarnings` to true.
+* Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use
+ `$request->getResponseBody()->isRepeatable()` instead.
+* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+* Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
+* Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
+* Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
+* Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.
+ These will work through Guzzle 4.0
+* Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params].
+* Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+* Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.
+* Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.
+* Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
+* Marked `Guzzle\Common\Collection::inject()` as deprecated.
+* Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');`
+* CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
+* Always setting X-cache headers on cached responses
+* Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
+* `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
+ $request, Response $response);`
+* `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
+* `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
+* Added `CacheStorageInterface::purge($url)`
+* `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
+ CanCacheStrategyInterface $canCache = null)`
+* Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
+
+## 3.6.0 - 2013-05-29
+
+* ServiceDescription now implements ToArrayInterface
+* Added command.hidden_params to blacklist certain headers from being treated as additionalParameters
+* Guzzle can now correctly parse incomplete URLs
+* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
+* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
+* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
+* Specific header implementations can be created for complex headers. When a message creates a header, it uses a
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
+ CacheControl header implementation.
+* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
+* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
+* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
+ Guzzle\Http\Curl\RequestMediator
+* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
+* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
+* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
+* Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
+* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
+* All response header helper functions return a string rather than mixing Header objects and strings inconsistently
+* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
+ directly via interfaces
+* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
+ but are a no-op until removed.
+* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
+ `Guzzle\Service\Command\ArrayCommandInterface`.
+* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
+ on a request while the request is still being transferred
+* The ability to case-insensitively search for header values
+* Guzzle\Http\Message\Header::hasExactHeader
+* Guzzle\Http\Message\Header::raw. Use getAll()
+* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
+ instead.
+* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
+* Added the ability to cast Model objects to a string to view debug information.
+
+## 3.5.0 - 2013-05-13
+
+* Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times
+* Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove
+ itself from the EventDispatcher)
+* Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values
+* Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too
+* Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a
+ non-existent key
+* Bug: All __call() method arguments are now required (helps with mocking frameworks)
+* Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference
+ to help with refcount based garbage collection of resources created by sending a request
+* Deprecating ZF1 cache and log adapters. These will be removed in the next major version.
+* Deprecating `Response::getPreviousResponse()` (method signature still exists, but it'sdeprecated). Use the
+ HistoryPlugin for a history.
+* Added a `responseBody` alias for the `response_body` location
+* Refactored internals to no longer rely on Response::getRequest()
+* HistoryPlugin can now be cast to a string
+* HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests
+ and responses that are sent over the wire
+* Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects
+
+## 3.4.3 - 2013-04-30
+
+* Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response
+* Added a check to re-extract the temp cacert bundle from the phar before sending each request
+
+## 3.4.2 - 2013-04-29
+
+* Bug fix: Stream objects now work correctly with "a" and "a+" modes
+* Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present
+* Bug fix: AsyncPlugin no longer forces HEAD requests
+* Bug fix: DateTime timezones are now properly handled when using the service description schema formatter
+* Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails
+* Setting a response on a request will write to the custom request body from the response body if one is specified
+* LogPlugin now writes to php://output when STDERR is undefined
+* Added the ability to set multiple POST files for the same key in a single call
+* application/x-www-form-urlencoded POSTs now use the utf-8 charset by default
+* Added the ability to queue CurlExceptions to the MockPlugin
+* Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send)
+* Configuration loading now allows remote files
+
+## 3.4.1 - 2013-04-16
+
+* Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti
+ handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost.
+* Exceptions are now properly grouped when sending requests in parallel
+* Redirects are now properly aggregated when a multi transaction fails
+* Redirects now set the response on the original object even in the event of a failure
+* Bug fix: Model names are now properly set even when using $refs
+* Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax
+* Added support for oauth_callback in OAuth signatures
+* Added support for oauth_verifier in OAuth signatures
+* Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection
+
+## 3.4.0 - 2013-04-11
+
+* Bug fix: URLs are now resolved correctly based on http://tools.ietf.org/html/rfc3986#section-5.2. #289
+* Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289
+* Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263
+* Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.
+* Bug fix: Added `number` type to service descriptions.
+* Bug fix: empty parameters are removed from an OAuth signature
+* Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header
+* Bug fix: Fixed "array to string" error when validating a union of types in a service description
+* Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream
+* Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin.
+* Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs.
+* The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections.
+* Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if
+ the Content-Type can be determined based on the entity body or the path of the request.
+* Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder.
+* Added support for a PSR-3 LogAdapter.
+* Added a `command.after_prepare` event
+* Added `oauth_callback` parameter to the OauthPlugin
+* Added the ability to create a custom stream class when using a stream factory
+* Added a CachingEntityBody decorator
+* Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized.
+* The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar.
+* You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies
+* POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This
+ means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use
+ POST fields or files (the latter is only used when emulating a form POST in the browser).
+* Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest
+
+## 3.3.1 - 2013-03-10
+
+* Added the ability to create PHP streaming responses from HTTP requests
+* Bug fix: Running any filters when parsing response headers with service descriptions
+* Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing
+* Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across
+ response location visitors.
+* Bug fix: Removed the possibility of creating configuration files with circular dependencies
+* RequestFactory::create() now uses the key of a POST file when setting the POST file name
+* Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set
+
+## 3.3.0 - 2013-03-03
+
+* A large number of performance optimizations have been made
+* Bug fix: Added 'wb' as a valid write mode for streams
+* Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned
+* Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()`
+* BC: Removed `Guzzle\Http\Utils` class
+* BC: Setting a service description on a client will no longer modify the client's command factories.
+* BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using
+ the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
+* BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to
+ lowercase
+* Operation parameter objects are now lazy loaded internally
+* Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses
+* Added support for instantiating responseType=class responseClass classes. Classes must implement
+ `Guzzle\Service\Command\ResponseClassInterface`
+* Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These
+ additional properties also support locations and can be used to parse JSON responses where the outermost part of the
+ JSON is an array
+* Added support for nested renaming of JSON models (rename sentAs to name)
+* CachePlugin
+ * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error
+ * Debug headers can now added to cached response in the CachePlugin
+
+## 3.2.0 - 2013-02-14
+
+* CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients.
+* URLs with no path no longer contain a "/" by default
+* Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url.
+* BadResponseException no longer includes the full request and response message
+* Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface
+* Adding getResponseBody() to Guzzle\Http\Message\RequestInterface
+* Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription
+* Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list
+* xmlEncoding can now be customized for the XML declaration of a XML service description operation
+* Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value
+ aggregation and no longer uses callbacks
+* The URL encoding implementation of Guzzle\Http\QueryString can now be customized
+* Bug fix: Filters were not always invoked for array service description parameters
+* Bug fix: Redirects now use a target response body rather than a temporary response body
+* Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded
+* Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives
+
+## 3.1.2 - 2013-01-27
+
+* Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the
+ response body. For example, the XmlVisitor now parses the XML response into an array in the before() method.
+* Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent
+* CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444)
+* Fixed a bug where redirect responses were not chained correctly using getPreviousResponse()
+* Setting default headers on a client after setting the user-agent will not erase the user-agent setting
+
+## 3.1.1 - 2013-01-20
+
+* Adding wildcard support to Guzzle\Common\Collection::getPath()
+* Adding alias support to ServiceBuilder configs
+* Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface
+
+## 3.1.0 - 2013-01-12
+
+* BC: CurlException now extends from RequestException rather than BadResponseException
+* BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse()
+* Added getData to ServiceDescriptionInterface
+* Added context array to RequestInterface::setState()
+* Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http
+* Bug: Adding required content-type when JSON request visitor adds JSON to a command
+* Bug: Fixing the serialization of a service description with custom data
+* Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing
+ an array of successful and failed responses
+* Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection
+* Added Guzzle\Http\IoEmittingEntityBody
+* Moved command filtration from validators to location visitors
+* Added `extends` attributes to service description parameters
+* Added getModels to ServiceDescriptionInterface
+
+## 3.0.7 - 2012-12-19
+
+* Fixing phar detection when forcing a cacert to system if null or true
+* Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()`
+* Cleaning up `Guzzle\Common\Collection::inject` method
+* Adding a response_body location to service descriptions
+
+## 3.0.6 - 2012-12-09
+
+* CurlMulti performance improvements
+* Adding setErrorResponses() to Operation
+* composer.json tweaks
+
+## 3.0.5 - 2012-11-18
+
+* Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin
+* Bug: Response body can now be a string containing "0"
+* Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert
+* Bug: QueryString::fromString now properly parses query string parameters that contain equal signs
+* Added support for XML attributes in service description responses
+* DefaultRequestSerializer now supports array URI parameter values for URI template expansion
+* Added better mimetype guessing to requests and post files
+
+## 3.0.4 - 2012-11-11
+
+* Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value
+* Bug: Cookies can now be added that have a name, domain, or value set to "0"
+* Bug: Using the system cacert bundle when using the Phar
+* Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures
+* Enhanced cookie jar de-duplication
+* Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added
+* Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies
+* Added the ability to create any sort of hash for a stream rather than just an MD5 hash
+
+## 3.0.3 - 2012-11-04
+
+* Implementing redirects in PHP rather than cURL
+* Added PECL URI template extension and using as default parser if available
+* Bug: Fixed Content-Length parsing of Response factory
+* Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams.
+* Adding ToArrayInterface throughout library
+* Fixing OauthPlugin to create unique nonce values per request
+
+## 3.0.2 - 2012-10-25
+
+* Magic methods are enabled by default on clients
+* Magic methods return the result of a command
+* Service clients no longer require a base_url option in the factory
+* Bug: Fixed an issue with URI templates where null template variables were being expanded
+
+## 3.0.1 - 2012-10-22
+
+* Models can now be used like regular collection objects by calling filter, map, etc.
+* Models no longer require a Parameter structure or initial data in the constructor
+* Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator`
+
+## 3.0.0 - 2012-10-15
+
+* Rewrote service description format to be based on Swagger
+ * Now based on JSON schema
+ * Added nested input structures and nested response models
+ * Support for JSON and XML input and output models
+ * Renamed `commands` to `operations`
+ * Removed dot class notation
+ * Removed custom types
+* Broke the project into smaller top-level namespaces to be more component friendly
+* Removed support for XML configs and descriptions. Use arrays or JSON files.
+* Removed the Validation component and Inspector
+* Moved all cookie code to Guzzle\Plugin\Cookie
+* Magic methods on a Guzzle\Service\Client now return the command un-executed.
+* Calling getResult() or getResponse() on a command will lazily execute the command if needed.
+* Now shipping with cURL's CA certs and using it by default
+* Added previousResponse() method to response objects
+* No longer sending Accept and Accept-Encoding headers on every request
+* Only sending an Expect header by default when a payload is greater than 1MB
+* Added/moved client options:
+ * curl.blacklist to curl.option.blacklist
+ * Added ssl.certificate_authority
+* Added a Guzzle\Iterator component
+* Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin
+* Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin)
+* Added a more robust caching plugin
+* Added setBody to response objects
+* Updating LogPlugin to use a more flexible MessageFormatter
+* Added a completely revamped build process
+* Cleaning up Collection class and removing default values from the get method
+* Fixed ZF2 cache adapters
+
+## 2.8.8 - 2012-10-15
+
+* Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did
+
+## 2.8.7 - 2012-09-30
+
+* Bug: Fixed config file aliases for JSON includes
+* Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests
+* Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload
+* Bug: Hardening request and response parsing to account for missing parts
+* Bug: Fixed PEAR packaging
+* Bug: Fixed Request::getInfo
+* Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail
+* Adding the ability for the namespace Iterator factory to look in multiple directories
+* Added more getters/setters/removers from service descriptions
+* Added the ability to remove POST fields from OAuth signatures
+* OAuth plugin now supports 2-legged OAuth
+
+## 2.8.6 - 2012-09-05
+
+* Added the ability to modify and build service descriptions
+* Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command
+* Added a `json` parameter location
+* Now allowing dot notation for classes in the CacheAdapterFactory
+* Using the union of two arrays rather than an array_merge when extending service builder services and service params
+* Ensuring that a service is a string before doing strpos() checks on it when substituting services for references
+ in service builder config files.
+* Services defined in two different config files that include one another will by default replace the previously
+ defined service, but you can now create services that extend themselves and merge their settings over the previous
+* The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like
+ '_default' with a default JSON configuration file.
+
+## 2.8.5 - 2012-08-29
+
+* Bug: Suppressed empty arrays from URI templates
+* Bug: Added the missing $options argument from ServiceDescription::factory to enable caching
+* Added support for HTTP responses that do not contain a reason phrase in the start-line
+* AbstractCommand commands are now invokable
+* Added a way to get the data used when signing an Oauth request before a request is sent
+
+## 2.8.4 - 2012-08-15
+
+* Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin
+* Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable.
+* Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream
+* Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream
+* Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5())
+* Added additional response status codes
+* Removed SSL information from the default User-Agent header
+* DELETE requests can now send an entity body
+* Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries
+* Added the ability of the MockPlugin to consume mocked request bodies
+* LogPlugin now exposes request and response objects in the extras array
+
+## 2.8.3 - 2012-07-30
+
+* Bug: Fixed a case where empty POST requests were sent as GET requests
+* Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body
+* Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new
+* Added multiple inheritance to service description commands
+* Added an ApiCommandInterface and added `getParamNames()` and `hasParam()`
+* Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything
+* Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles
+
+## 2.8.2 - 2012-07-24
+
+* Bug: Query string values set to 0 are no longer dropped from the query string
+* Bug: A Collection object is no longer created each time a call is made to `Guzzle\Service\Command\AbstractCommand::getRequestHeaders()`
+* Bug: `+` is now treated as an encoded space when parsing query strings
+* QueryString and Collection performance improvements
+* Allowing dot notation for class paths in filters attribute of a service descriptions
+
+## 2.8.1 - 2012-07-16
+
+* Loosening Event Dispatcher dependency
+* POST redirects can now be customized using CURLOPT_POSTREDIR
+
+## 2.8.0 - 2012-07-15
+
+* BC: Guzzle\Http\Query
+ * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl)
+ * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding()
+ * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool)
+ * Changed the aggregation functions of QueryString to be static methods
+ * Can now use fromString() with querystrings that have a leading ?
+* cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters
+* Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body
+* Cookies are no longer URL decoded by default
+* Bug: URI template variables set to null are no longer expanded
+
+## 2.7.2 - 2012-07-02
+
+* BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser.
+* BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty()
+* CachePlugin now allows for a custom request parameter function to check if a request can be cached
+* Bug fix: CachePlugin now only caches GET and HEAD requests by default
+* Bug fix: Using header glue when transferring headers over the wire
+* Allowing deeply nested arrays for composite variables in URI templates
+* Batch divisors can now return iterators or arrays
+
+## 2.7.1 - 2012-06-26
+
+* Minor patch to update version number in UA string
+* Updating build process
+
+## 2.7.0 - 2012-06-25
+
+* BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes.
+* BC: Removed magic setX methods from commands
+* BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method
+* Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable.
+* Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity)
+* Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace
+* Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin
+* Added the ability to set POST fields and files in a service description
+* Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method
+* Adding a command.before_prepare event to clients
+* Added BatchClosureTransfer and BatchClosureDivisor
+* BatchTransferException now includes references to the batch divisor and transfer strategies
+* Fixed some tests so that they pass more reliably
+* Added Guzzle\Common\Log\ArrayLogAdapter
+
+## 2.6.6 - 2012-06-10
+
+* BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin
+* BC: Removing Guzzle\Service\Command\CommandSet
+* Adding generic batching system (replaces the batch queue plugin and command set)
+* Updating ZF cache and log adapters and now using ZF's composer repository
+* Bug: Setting the name of each ApiParam when creating through an ApiCommand
+* Adding result_type, result_doc, deprecated, and doc_url to service descriptions
+* Bug: Changed the default cookie header casing back to 'Cookie'
+
+## 2.6.5 - 2012-06-03
+
+* BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource()
+* BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from
+* BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data
+* BC: Renaming methods in the CookieJarInterface
+* Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations
+* Making the default glue for HTTP headers ';' instead of ','
+* Adding a removeValue to Guzzle\Http\Message\Header
+* Adding getCookies() to request interface.
+* Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber()
+
+## 2.6.4 - 2012-05-30
+
+* BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.
+* BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand
+* Bug: Fixing magic method command calls on clients
+* Bug: Email constraint only validates strings
+* Bug: Aggregate POST fields when POST files are present in curl handle
+* Bug: Fixing default User-Agent header
+* Bug: Only appending or prepending parameters in commands if they are specified
+* Bug: Not requiring response reason phrases or status codes to match a predefined list of codes
+* Allowing the use of dot notation for class namespaces when using instance_of constraint
+* Added any_match validation constraint
+* Added an AsyncPlugin
+* Passing request object to the calculateWait method of the ExponentialBackoffPlugin
+* Allowing the result of a command object to be changed
+* Parsing location and type sub values when instantiating a service description rather than over and over at runtime
+
+## 2.6.3 - 2012-05-23
+
+* [BC] Guzzle\Common\FromConfigInterface no longer requires any config options.
+* [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.
+* You can now use an array of data when creating PUT request bodies in the request factory.
+* Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.
+* [Http] Adding support for Content-Type in multipart POST uploads per upload
+* [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])
+* Adding more POST data operations for easier manipulation of POST data.
+* You can now set empty POST fields.
+* The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.
+* Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.
+* CS updates
+
+## 2.6.2 - 2012-05-19
+
+* [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method.
+
+## 2.6.1 - 2012-05-19
+
+* [BC] Removing 'path' support in service descriptions. Use 'uri'.
+* [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.
+* [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it.
+* [BC] Removing Guzzle\Common\XmlElement.
+* All commands, both dynamic and concrete, have ApiCommand objects.
+* Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.
+* Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.
+* Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible.
+
+## 2.6.0 - 2012-05-15
+
+* [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder
+* [BC] Executing a Command returns the result of the command rather than the command
+* [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed.
+* [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args.
+* [BC] Moving ResourceIterator* to Guzzle\Service\Resource
+* [BC] Completely refactored ResourceIterators to iterate over a cloned command object
+* [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate
+* [BC] Guzzle\Guzzle is now deprecated
+* Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject
+* Adding Guzzle\Version class to give version information about Guzzle
+* Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate()
+* Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data
+* ServiceDescription and ServiceBuilder are now cacheable using similar configs
+* Changing the format of XML and JSON service builder configs. Backwards compatible.
+* Cleaned up Cookie parsing
+* Trimming the default Guzzle User-Agent header
+* Adding a setOnComplete() method to Commands that is called when a command completes
+* Keeping track of requests that were mocked in the MockPlugin
+* Fixed a caching bug in the CacheAdapterFactory
+* Inspector objects can be injected into a Command object
+* Refactoring a lot of code and tests to be case insensitive when dealing with headers
+* Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL
+* Adding the ability to set global option overrides to service builder configs
+* Adding the ability to include other service builder config files from within XML and JSON files
+* Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.
+
+## 2.5.0 - 2012-05-08
+
+* Major performance improvements
+* [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated.
+* [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.
+* [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}"
+* Added the ability to passed parameters to all requests created by a client
+* Added callback functionality to the ExponentialBackoffPlugin
+* Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies.
+* Rewinding request stream bodies when retrying requests
+* Exception is thrown when JSON response body cannot be decoded
+* Added configurable magic method calls to clients and commands. This is off by default.
+* Fixed a defect that added a hash to every parsed URL part
+* Fixed duplicate none generation for OauthPlugin.
+* Emitting an event each time a client is generated by a ServiceBuilder
+* Using an ApiParams object instead of a Collection for parameters of an ApiCommand
+* cache.* request parameters should be renamed to params.cache.*
+* Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle.
+* Added the ability to disable type validation of service descriptions
+* ServiceDescriptions and ServiceBuilders are now Serializable
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/LICENSE b/public/system/storage/vendor/guzzlehttp/guzzle/LICENSE
new file mode 100644
index 0000000..9af9fba
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011-2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/README.md b/public/system/storage/vendor/guzzlehttp/guzzle/README.md
new file mode 100644
index 0000000..d41e7e7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/README.md
@@ -0,0 +1,70 @@
+Guzzle, PHP HTTP client and webservice framework
+================================================
+
+[![Build Status](https://secure.travis-ci.org/guzzle/guzzle.svg?branch=master)](http://travis-ci.org/guzzle/guzzle)
+
+Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
+trivial to integrate with web services.
+
+- Manages things like persistent connections, represents query strings as
+ collections, simplifies sending streaming POST requests with fields and
+ files, and abstracts away the underlying HTTP transport layer.
+- Can send both synchronous and asynchronous requests using the same interface
+ without requiring a dependency on a specific event loop.
+- Pluggable HTTP adapters allows Guzzle to integrate with any method you choose
+ for sending HTTP requests over the wire (e.g., cURL, sockets, PHP's stream
+ wrapper, non-blocking event loops like ReactPHP.
+- Guzzle makes it so that you no longer need to fool around with cURL options,
+ stream contexts, or sockets.
+
+```php
+$client = new GuzzleHttp\Client();
+$response = $client->get('http://guzzlephp.org');
+$res = $client->get('https://api.github.com/user', ['auth' => ['user', 'pass']]);
+echo $res->getStatusCode();
+// "200"
+echo $res->getHeader('content-type');
+// 'application/json; charset=utf8'
+echo $res->getBody();
+// {"type":"User"...'
+var_export($res->json());
+// Outputs the JSON decoded data
+
+// Send an asynchronous request.
+$req = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
+$client->send($req)->then(function ($response) {
+ echo 'I completed! ' . $response;
+});
+```
+
+Get more information and answers with the
+[Documentation](http://guzzlephp.org/),
+[Forums](https://groups.google.com/forum/?hl=en#!forum/guzzle),
+and [Gitter](https://gitter.im/guzzle/guzzle).
+
+### Installing via Composer
+
+The recommended way to install Guzzle is through
+[Composer](http://getcomposer.org).
+
+```bash
+# Install Composer
+curl -sS https://getcomposer.org/installer | php
+```
+
+Next, run the Composer command to install the latest stable version of Guzzle:
+
+```bash
+composer.phar require guzzlehttp/guzzle
+```
+
+After installing, you need to require Composer's autoloader:
+
+```php
+require 'vendor/autoload.php';
+```
+
+### Documentation
+
+More information can be found in the online documentation at
+http://guzzlephp.org/.
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/UPGRADING.md b/public/system/storage/vendor/guzzlehttp/guzzle/UPGRADING.md
new file mode 100644
index 0000000..2b3877f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/UPGRADING.md
@@ -0,0 +1,1050 @@
+Guzzle Upgrade Guide
+====================
+
+4.x to 5.0
+----------
+
+## Rewritten Adapter Layer
+
+Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send
+HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor
+is still supported, but it has now been renamed to `handler`. Instead of
+passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
+`callable` that follows the RingPHP specification.
+
+## Removed Fluent Interfaces
+
+[Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil)
+from the following classes:
+
+- `GuzzleHttp\Collection`
+- `GuzzleHttp\Url`
+- `GuzzleHttp\Query`
+- `GuzzleHttp\Post\PostBody`
+- `GuzzleHttp\Cookie\SetCookie`
+
+## Removed functions.php
+
+Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following
+functions can be used as replacements.
+
+- `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode`
+- `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath`
+- `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path`
+- `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however,
+ deprecated in favor of using `GuzzleHttp\Pool::batch()`.
+
+The "procedural" global client has been removed with no replacement (e.g.,
+`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client`
+object as a replacement.
+
+## `throwImmediately` has been removed
+
+The concept of "throwImmediately" has been removed from exceptions and error
+events. This control mechanism was used to stop a transfer of concurrent
+requests from completing. This can now be handled by throwing the exception or
+by cancelling a pool of requests or each outstanding future request
+individually.
+
+## headers event has been removed
+
+Removed the "headers" event. This event was only useful for changing the
+body a response once the headers of the response were known. You can implement
+a similar behavior in a number of ways. One example might be to use a
+FnStream that has access to the transaction being sent. For example, when the
+first byte is written, you could check if the response headers match your
+expectations, and if so, change the actual stream body that is being
+written to.
+
+## Updates to HTTP Messages
+
+Removed the `asArray` parameter from
+`GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+value as an array, then use the newly added `getHeaderAsArray()` method of
+`MessageInterface`. This change makes the Guzzle interfaces compatible with
+the PSR-7 interfaces.
+
+3.x to 4.0
+----------
+
+## Overarching changes:
+
+- Now requires PHP 5.4 or greater.
+- No longer requires cURL to send requests.
+- Guzzle no longer wraps every exception it throws. Only exceptions that are
+ recoverable are now wrapped by Guzzle.
+- Various namespaces have been removed or renamed.
+- No longer requiring the Symfony EventDispatcher. A custom event dispatcher
+ based on the Symfony EventDispatcher is
+ now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant
+ speed and functionality improvements).
+
+Changes per Guzzle 3.x namespace are described below.
+
+## Batch
+
+The `Guzzle\Batch` namespace has been removed. This is best left to
+third-parties to implement on top of Guzzle's core HTTP library.
+
+## Cache
+
+The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement
+has been implemented yet, but hoping to utilize a PSR cache interface).
+
+## Common
+
+- Removed all of the wrapped exceptions. It's better to use the standard PHP
+ library for unrecoverable exceptions.
+- `FromConfigInterface` has been removed.
+- `Guzzle\Common\Version` has been removed. The VERSION constant can be found
+ at `GuzzleHttp\ClientInterface::VERSION`.
+
+### Collection
+
+- `getAll` has been removed. Use `toArray` to convert a collection to an array.
+- `inject` has been removed.
+- `keySearch` has been removed.
+- `getPath` no longer supports wildcard expressions. Use something better like
+ JMESPath for this.
+- `setPath` now supports appending to an existing array via the `[]` notation.
+
+### Events
+
+Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses
+`GuzzleHttp\Event\Emitter`.
+
+- `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by
+ `GuzzleHttp\Event\EmitterInterface`.
+- `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by
+ `GuzzleHttp\Event\Emitter`.
+- `Symfony\Component\EventDispatcher\Event` is replaced by
+ `GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in
+ `GuzzleHttp\Event\EventInterface`.
+- `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and
+ `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the
+ event emitter of a request, client, etc. now uses the `getEmitter` method
+ rather than the `getDispatcher` method.
+
+#### Emitter
+
+- Use the `once()` method to add a listener that automatically removes itself
+ the first time it is invoked.
+- Use the `listeners()` method to retrieve a list of event listeners rather than
+ the `getListeners()` method.
+- Use `emit()` instead of `dispatch()` to emit an event from an emitter.
+- Use `attach()` instead of `addSubscriber()` and `detach()` instead of
+ `removeSubscriber()`.
+
+```php
+$mock = new Mock();
+// 3.x
+$request->getEventDispatcher()->addSubscriber($mock);
+$request->getEventDispatcher()->removeSubscriber($mock);
+// 4.x
+$request->getEmitter()->attach($mock);
+$request->getEmitter()->detach($mock);
+```
+
+Use the `on()` method to add a listener rather than the `addListener()` method.
+
+```php
+// 3.x
+$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } );
+// 4.x
+$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } );
+```
+
+## Http
+
+### General changes
+
+- The cacert.pem certificate has been moved to `src/cacert.pem`.
+- Added the concept of adapters that are used to transfer requests over the
+ wire.
+- Simplified the event system.
+- Sending requests in parallel is still possible, but batching is no longer a
+ concept of the HTTP layer. Instead, you must use the `complete` and `error`
+ events to asynchronously manage parallel request transfers.
+- `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`.
+- `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`.
+- QueryAggregators have been rewritten so that they are simply callable
+ functions.
+- `GuzzleHttp\StaticClient` has been removed. Use the functions provided in
+ `functions.php` for an easy to use static client instance.
+- Exceptions in `GuzzleHttp\Exception` have been updated to all extend from
+ `GuzzleHttp\Exception\TransferException`.
+
+### Client
+
+Calling methods like `get()`, `post()`, `head()`, etc. no longer create and
+return a request, but rather creates a request, sends the request, and returns
+the response.
+
+```php
+// 3.0
+$request = $client->get('/');
+$response = $request->send();
+
+// 4.0
+$response = $client->get('/');
+
+// or, to mirror the previous behavior
+$request = $client->createRequest('GET', '/');
+$response = $client->send($request);
+```
+
+`GuzzleHttp\ClientInterface` has changed.
+
+- The `send` method no longer accepts more than one request. Use `sendAll` to
+ send multiple requests in parallel.
+- `setUserAgent()` has been removed. Use a default request option instead. You
+ could, for example, do something like:
+ `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`.
+- `setSslVerification()` has been removed. Use default request options instead,
+ like `$client->setConfig('defaults/verify', true)`.
+
+`GuzzleHttp\Client` has changed.
+
+- The constructor now accepts only an associative array. You can include a
+ `base_url` string or array to use a URI template as the base URL of a client.
+ You can also specify a `defaults` key that is an associative array of default
+ request options. You can pass an `adapter` to use a custom adapter,
+ `batch_adapter` to use a custom adapter for sending requests in parallel, or
+ a `message_factory` to change the factory used to create HTTP requests and
+ responses.
+- The client no longer emits a `client.create_request` event.
+- Creating requests with a client no longer automatically utilize a URI
+ template. You must pass an array into a creational method (e.g.,
+ `createRequest`, `get`, `put`, etc.) in order to expand a URI template.
+
+### Messages
+
+Messages no longer have references to their counterparts (i.e., a request no
+longer has a reference to it's response, and a response no loger has a
+reference to its request). This association is now managed through a
+`GuzzleHttp\Adapter\TransactionInterface` object. You can get references to
+these transaction objects using request events that are emitted over the
+lifecycle of a request.
+
+#### Requests with a body
+
+- `GuzzleHttp\Message\EntityEnclosingRequest` and
+ `GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The
+ separation between requests that contain a body and requests that do not
+ contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface`
+ handles both use cases.
+- Any method that previously accepts a `GuzzleHttp\Response` object now accept a
+ `GuzzleHttp\Message\ResponseInterface`.
+- `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to
+ `GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create
+ both requests and responses and is implemented in
+ `GuzzleHttp\Message\MessageFactory`.
+- POST field and file methods have been removed from the request object. You
+ must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface`
+ to control the format of a POST body. Requests that are created using a
+ standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use
+ a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if
+ the method is POST and no body is provided.
+
+```php
+$request = $client->createRequest('POST', '/');
+$request->getBody()->setField('foo', 'bar');
+$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r')));
+```
+
+#### Headers
+
+- `GuzzleHttp\Message\Header` has been removed. Header values are now simply
+ represented by an array of values or as a string. Header values are returned
+ as a string by default when retrieving a header value from a message. You can
+ pass an optional argument of `true` to retrieve a header value as an array
+ of strings instead of a single concatenated string.
+- `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to
+ `GuzzleHttp\Post`. This interface has been simplified and now allows the
+ addition of arbitrary headers.
+- Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most
+ of the custom headers are now handled separately in specific
+ subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has
+ been updated to properly handle headers that contain parameters (like the
+ `Link` header).
+
+#### Responses
+
+- `GuzzleHttp\Message\Response::getInfo()` and
+ `GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event
+ system to retrieve this type of information.
+- `GuzzleHttp\Message\Response::getRawHeaders()` has been removed.
+- `GuzzleHttp\Message\Response::getMessage()` has been removed.
+- `GuzzleHttp\Message\Response::calculateAge()` and other cache specific
+ methods have moved to the CacheSubscriber.
+- Header specific helper functions like `getContentMd5()` have been removed.
+ Just use `getHeader('Content-MD5')` instead.
+- `GuzzleHttp\Message\Response::setRequest()` and
+ `GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event
+ system to work with request and response objects as a transaction.
+- `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the
+ Redirect subscriber instead.
+- `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have
+ been removed. Use `getStatusCode()` instead.
+
+#### Streaming responses
+
+Streaming requests can now be created by a client directly, returning a
+`GuzzleHttp\Message\ResponseInterface` object that contains a body stream
+referencing an open PHP HTTP stream.
+
+```php
+// 3.0
+use Guzzle\Stream\PhpStreamRequestFactory;
+$request = $client->get('/');
+$factory = new PhpStreamRequestFactory();
+$stream = $factory->fromRequest($request);
+$data = $stream->read(1024);
+
+// 4.0
+$response = $client->get('/', ['stream' => true]);
+// Read some data off of the stream in the response body
+$data = $response->getBody()->read(1024);
+```
+
+#### Redirects
+
+The `configureRedirects()` method has been removed in favor of a
+`allow_redirects` request option.
+
+```php
+// Standard redirects with a default of a max of 5 redirects
+$request = $client->createRequest('GET', '/', ['allow_redirects' => true]);
+
+// Strict redirects with a custom number of redirects
+$request = $client->createRequest('GET', '/', [
+ 'allow_redirects' => ['max' => 5, 'strict' => true]
+]);
+```
+
+#### EntityBody
+
+EntityBody interfaces and classes have been removed or moved to
+`GuzzleHttp\Stream`. All classes and interfaces that once required
+`GuzzleHttp\EntityBodyInterface` now require
+`GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no
+longer uses `GuzzleHttp\EntityBody::factory` but now uses
+`GuzzleHttp\Stream\Stream::factory` or even better:
+`GuzzleHttp\Stream\create()`.
+
+- `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface`
+- `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream`
+- `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream`
+- `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream`
+- `Guzzle\Http\IoEmittyinEntityBody` has been removed.
+
+#### Request lifecycle events
+
+Requests previously submitted a large number of requests. The number of events
+emitted over the lifecycle of a request has been significantly reduced to make
+it easier to understand how to extend the behavior of a request. All events
+emitted during the lifecycle of a request now emit a custom
+`GuzzleHttp\Event\EventInterface` object that contains context providing
+methods and a way in which to modify the transaction at that specific point in
+time (e.g., intercept the request and set a response on the transaction).
+
+- `request.before_send` has been renamed to `before` and now emits a
+ `GuzzleHttp\Event\BeforeEvent`
+- `request.complete` has been renamed to `complete` and now emits a
+ `GuzzleHttp\Event\CompleteEvent`.
+- `request.sent` has been removed. Use `complete`.
+- `request.success` has been removed. Use `complete`.
+- `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`.
+- `request.exception` has been removed. Use `error`.
+- `request.receive.status_line` has been removed.
+- `curl.callback.progress` has been removed. Use a custom `StreamInterface` to
+ maintain a status update.
+- `curl.callback.write` has been removed. Use a custom `StreamInterface` to
+ intercept writes.
+- `curl.callback.read` has been removed. Use a custom `StreamInterface` to
+ intercept reads.
+
+`headers` is a new event that is emitted after the response headers of a
+request have been received before the body of the response is downloaded. This
+event emits a `GuzzleHttp\Event\HeadersEvent`.
+
+You can intercept a request and inject a response using the `intercept()` event
+of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and
+`GuzzleHttp\Event\ErrorEvent` event.
+
+See: http://docs.guzzlephp.org/en/latest/events.html
+
+## Inflection
+
+The `Guzzle\Inflection` namespace has been removed. This is not a core concern
+of Guzzle.
+
+## Iterator
+
+The `Guzzle\Iterator` namespace has been removed.
+
+- `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and
+ `Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of
+ Guzzle itself.
+- `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent
+ class is shipped with PHP 5.4.
+- `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because
+ it's easier to just wrap an iterator in a generator that maps values.
+
+For a replacement of these iterators, see https://github.com/nikic/iter
+
+## Log
+
+The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The
+`Guzzle\Log` namespace has been removed. Guzzle now relies on
+`Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been
+moved to `GuzzleHttp\Subscriber\Log\Formatter`.
+
+## Parser
+
+The `Guzzle\Parser` namespace has been removed. This was previously used to
+make it possible to plug in custom parsers for cookies, messages, URI
+templates, and URLs; however, this level of complexity is not needed in Guzzle
+so it has been removed.
+
+- Cookie: Cookie parsing logic has been moved to
+ `GuzzleHttp\Cookie\SetCookie::fromString`.
+- Message: Message parsing logic for both requests and responses has been moved
+ to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only
+ used in debugging or deserializing messages, so it doesn't make sense for
+ Guzzle as a library to add this level of complexity to parsing messages.
+- UriTemplate: URI template parsing has been moved to
+ `GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL
+ URI template library if it is installed.
+- Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously
+ it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary,
+ then developers are free to subclass `GuzzleHttp\Url`.
+
+## Plugin
+
+The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`.
+Several plugins are shipping with the core Guzzle library under this namespace.
+
+- `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar
+ code has moved to `GuzzleHttp\Cookie`.
+- `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin.
+- `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is
+ received.
+- `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin.
+- `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before
+ sending. This subscriber is attached to all requests by default.
+- `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin.
+
+The following plugins have been removed (third-parties are free to re-implement
+these if needed):
+
+- `GuzzleHttp\Plugin\Async` has been removed.
+- `GuzzleHttp\Plugin\CurlAuth` has been removed.
+- `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This
+ functionality should instead be implemented with event listeners that occur
+ after normal response parsing occurs in the guzzle/command package.
+
+The following plugins are not part of the core Guzzle package, but are provided
+in separate repositories:
+
+- `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be muchs simpler
+ to build custom retry policies using simple functions rather than various
+ chained classes. See: https://github.com/guzzle/retry-subscriber
+- `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to
+ https://github.com/guzzle/cache-subscriber
+- `Guzzle\Http\Plugin\Log\LogPlugin` has moved to
+ https://github.com/guzzle/log-subscriber
+- `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to
+ https://github.com/guzzle/message-integrity-subscriber
+- `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to
+ `GuzzleHttp\Subscriber\MockSubscriber`.
+- `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to
+ https://github.com/guzzle/oauth-subscriber
+
+## Service
+
+The service description layer of Guzzle has moved into two separate packages:
+
+- http://github.com/guzzle/command Provides a high level abstraction over web
+ services by representing web service operations using commands.
+- http://github.com/guzzle/guzzle-services Provides an implementation of
+ guzzle/command that provides request serialization and response parsing using
+ Guzzle service descriptions.
+
+## Stream
+
+Stream have moved to a separate package available at
+https://github.com/guzzle/streams.
+
+`Guzzle\Stream\StreamInterface` has been given a large update to cleanly take
+on the responsibilities of `Guzzle\Http\EntityBody` and
+`Guzzle\Http\EntityBodyInterface` now that they have been removed. The number
+of methods implemented by the `StreamInterface` has been drastically reduced to
+allow developers to more easily extend and decorate stream behavior.
+
+## Removed methods from StreamInterface
+
+- `getStream` and `setStream` have been removed to better encapsulate streams.
+- `getMetadata` and `setMetadata` have been removed in favor of
+ `GuzzleHttp\Stream\MetadataStreamInterface`.
+- `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been
+ removed. This data is accessible when
+ using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`.
+- `rewind` has been removed. Use `seek(0)` for a similar behavior.
+
+## Renamed methods
+
+- `detachStream` has been renamed to `detach`.
+- `feof` has been renamed to `eof`.
+- `ftell` has been renamed to `tell`.
+- `readLine` has moved from an instance method to a static class method of
+ `GuzzleHttp\Stream\Stream`.
+
+## Metadata streams
+
+`GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams
+that contain additional metadata accessible via `getMetadata()`.
+`GuzzleHttp\Stream\StreamInterface::getMetadata` and
+`GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed.
+
+## StreamRequestFactory
+
+The entire concept of the StreamRequestFactory has been removed. The way this
+was used in Guzzle 3 broke the actual interface of sending streaming requests
+(instead of getting back a Response, you got a StreamInterface). Streeaming
+PHP requests are now implemented throught the `GuzzleHttp\Adapter\StreamAdapter`.
+
+3.6 to 3.7
+----------
+
+### Deprecations
+
+- You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.:
+
+```php
+\Guzzle\Common\Version::$emitWarnings = true;
+```
+
+The following APIs and options have been marked as deprecated:
+
+- Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead.
+- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+- Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
+- Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
+- Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
+- Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+- Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
+- Marked `Guzzle\Common\Collection::inject()` as deprecated.
+- Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use
+ `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or
+ `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));`
+
+3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational
+request methods. When paired with a client's configuration settings, these options allow you to specify default settings
+for various aspects of a request. Because these options make other previous configuration options redundant, several
+configuration options and methods of a client and AbstractCommand have been deprecated.
+
+- Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`.
+- Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`.
+- Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')`
+- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0
+
+ $command = $client->getCommand('foo', array(
+ 'command.headers' => array('Test' => '123'),
+ 'command.response_body' => '/path/to/file'
+ ));
+
+ // Should be changed to:
+
+ $command = $client->getCommand('foo', array(
+ 'command.request_options' => array(
+ 'headers' => array('Test' => '123'),
+ 'save_as' => '/path/to/file'
+ )
+ ));
+
+### Interface changes
+
+Additions and changes (you will need to update any implementations or subclasses you may have created):
+
+- Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+ createRequest, head, delete, put, patch, post, options, prepareRequest
+- Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+- Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+- Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+- Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+ default `array()`
+- Added `Guzzle\Stream\StreamInterface::isRepeatable`
+- Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
+
+The following methods were removed from interfaces. All of these methods are still available in the concrete classes
+that implement them, but you should update your code to use alternative methods:
+
+- Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+ `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+ `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or
+ `$client->setDefaultOption('headers/{header_name}', 'value')`. or
+ `$client->setDefaultOption('headers', array('header_name' => 'value'))`.
+- Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`.
+- Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail.
+- Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail.
+- Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail.
+- Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin.
+- Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin.
+- Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin.
+
+### Cache plugin breaking changes
+
+- CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
+- Always setting X-cache headers on cached responses
+- Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
+- `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
+ $request, Response $response);`
+- `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
+- `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
+- Added `CacheStorageInterface::purge($url)`
+- `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
+ CanCacheStrategyInterface $canCache = null)`
+- Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
+
+3.5 to 3.6
+----------
+
+* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
+* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
+* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
+ For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader().
+ Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request.
+* Specific header implementations can be created for complex headers. When a message creates a header, it uses a
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
+ CacheControl header implementation.
+* Moved getLinks() from Response to just be used on a Link header object.
+
+If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the
+HeaderInterface (e.g. toArray(), getAll(), etc.).
+
+### Interface changes
+
+* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
+* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
+* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
+ Guzzle\Http\Curl\RequestMediator
+* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
+* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
+* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
+
+### Removed deprecated functions
+
+* Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
+* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
+
+### Deprecations
+
+* The ability to case-insensitively search for header values
+* Guzzle\Http\Message\Header::hasExactHeader
+* Guzzle\Http\Message\Header::raw. Use getAll()
+* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
+ instead.
+
+### Other changes
+
+* All response header helper functions return a string rather than mixing Header objects and strings inconsistently
+* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
+ directly via interfaces
+* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
+ but are a no-op until removed.
+* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
+ `Guzzle\Service\Command\ArrayCommandInterface`.
+* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
+ on a request while the request is still being transferred
+* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
+
+3.3 to 3.4
+----------
+
+Base URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.
+
+3.2 to 3.3
+----------
+
+### Response::getEtag() quote stripping removed
+
+`Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header
+
+### Removed `Guzzle\Http\Utils`
+
+The `Guzzle\Http\Utils` class was removed. This class was only used for testing.
+
+### Stream wrapper and type
+
+`Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase.
+
+### curl.emit_io became emit_io
+
+Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the
+'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
+
+3.1 to 3.2
+----------
+
+### CurlMulti is no longer reused globally
+
+Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added
+to a single client can pollute requests dispatched from other clients.
+
+If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the
+ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is
+created.
+
+```php
+$multi = new Guzzle\Http\Curl\CurlMulti();
+$builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json');
+$builder->addListener('service_builder.create_client', function ($event) use ($multi) {
+ $event['client']->setCurlMulti($multi);
+}
+});
+```
+
+### No default path
+
+URLs no longer have a default path value of '/' if no path was specified.
+
+Before:
+
+```php
+$request = $client->get('http://www.foo.com');
+echo $request->getUrl();
+// >> http://www.foo.com/
+```
+
+After:
+
+```php
+$request = $client->get('http://www.foo.com');
+echo $request->getUrl();
+// >> http://www.foo.com
+```
+
+### Less verbose BadResponseException
+
+The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and
+response information. You can, however, get access to the request and response object by calling `getRequest()` or
+`getResponse()` on the exception object.
+
+### Query parameter aggregation
+
+Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a
+setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is
+responsible for handling the aggregation of multi-valued query string variables into a flattened hash.
+
+2.8 to 3.x
+----------
+
+### Guzzle\Service\Inspector
+
+Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig`
+
+**Before**
+
+```php
+use Guzzle\Service\Inspector;
+
+class YourClient extends \Guzzle\Service\Client
+{
+ public static function factory($config = array())
+ {
+ $default = array();
+ $required = array('base_url', 'username', 'api_key');
+ $config = Inspector::fromConfig($config, $default, $required);
+
+ $client = new self(
+ $config->get('base_url'),
+ $config->get('username'),
+ $config->get('api_key')
+ );
+ $client->setConfig($config);
+
+ $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
+
+ return $client;
+ }
+```
+
+**After**
+
+```php
+use Guzzle\Common\Collection;
+
+class YourClient extends \Guzzle\Service\Client
+{
+ public static function factory($config = array())
+ {
+ $default = array();
+ $required = array('base_url', 'username', 'api_key');
+ $config = Collection::fromConfig($config, $default, $required);
+
+ $client = new self(
+ $config->get('base_url'),
+ $config->get('username'),
+ $config->get('api_key')
+ );
+ $client->setConfig($config);
+
+ $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
+
+ return $client;
+ }
+```
+
+### Convert XML Service Descriptions to JSON
+
+**Before**
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<client>
+ <commands>
+ <!-- Groups -->
+ <command name="list_groups" method="GET" uri="groups.json">
+ <doc>Get a list of groups</doc>
+ </command>
+ <command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'>
+ <doc>Uses a search query to get a list of groups</doc>
+ <param name="query" type="string" required="true" />
+ </command>
+ <command name="create_group" method="POST" uri="groups.json">
+ <doc>Create a group</doc>
+ <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
+ <param name="Content-Type" location="header" static="application/json"/>
+ </command>
+ <command name="delete_group" method="DELETE" uri="groups/{{id}}.json">
+ <doc>Delete a group by ID</doc>
+ <param name="id" type="integer" required="true"/>
+ </command>
+ <command name="get_group" method="GET" uri="groups/{{id}}.json">
+ <param name="id" type="integer" required="true"/>
+ </command>
+ <command name="update_group" method="PUT" uri="groups/{{id}}.json">
+ <doc>Update a group</doc>
+ <param name="id" type="integer" required="true"/>
+ <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
+ <param name="Content-Type" location="header" static="application/json"/>
+ </command>
+ </commands>
+</client>
+```
+
+**After**
+
+```json
+{
+ "name": "Zendesk REST API v2",
+ "apiVersion": "2012-12-31",
+ "description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users",
+ "operations": {
+ "list_groups": {
+ "httpMethod":"GET",
+ "uri": "groups.json",
+ "summary": "Get a list of groups"
+ },
+ "search_groups":{
+ "httpMethod":"GET",
+ "uri": "search.json?query=\"{query} type:group\"",
+ "summary": "Uses a search query to get a list of groups",
+ "parameters":{
+ "query":{
+ "location": "uri",
+ "description":"Zendesk Search Query",
+ "type": "string",
+ "required": true
+ }
+ }
+ },
+ "create_group": {
+ "httpMethod":"POST",
+ "uri": "groups.json",
+ "summary": "Create a group",
+ "parameters":{
+ "data": {
+ "type": "array",
+ "location": "body",
+ "description":"Group JSON",
+ "filters": "json_encode",
+ "required": true
+ },
+ "Content-Type":{
+ "type": "string",
+ "location":"header",
+ "static": "application/json"
+ }
+ }
+ },
+ "delete_group": {
+ "httpMethod":"DELETE",
+ "uri": "groups/{id}.json",
+ "summary": "Delete a group",
+ "parameters":{
+ "id":{
+ "location": "uri",
+ "description":"Group to delete by ID",
+ "type": "integer",
+ "required": true
+ }
+ }
+ },
+ "get_group": {
+ "httpMethod":"GET",
+ "uri": "groups/{id}.json",
+ "summary": "Get a ticket",
+ "parameters":{
+ "id":{
+ "location": "uri",
+ "description":"Group to get by ID",
+ "type": "integer",
+ "required": true
+ }
+ }
+ },
+ "update_group": {
+ "httpMethod":"PUT",
+ "uri": "groups/{id}.json",
+ "summary": "Update a group",
+ "parameters":{
+ "id": {
+ "location": "uri",
+ "description":"Group to update by ID",
+ "type": "integer",
+ "required": true
+ },
+ "data": {
+ "type": "array",
+ "location": "body",
+ "description":"Group JSON",
+ "filters": "json_encode",
+ "required": true
+ },
+ "Content-Type":{
+ "type": "string",
+ "location":"header",
+ "static": "application/json"
+ }
+ }
+ }
+}
+```
+
+### Guzzle\Service\Description\ServiceDescription
+
+Commands are now called Operations
+
+**Before**
+
+```php
+use Guzzle\Service\Description\ServiceDescription;
+
+$sd = new ServiceDescription();
+$sd->getCommands(); // @returns ApiCommandInterface[]
+$sd->hasCommand($name);
+$sd->getCommand($name); // @returns ApiCommandInterface|null
+$sd->addCommand($command); // @param ApiCommandInterface $command
+```
+
+**After**
+
+```php
+use Guzzle\Service\Description\ServiceDescription;
+
+$sd = new ServiceDescription();
+$sd->getOperations(); // @returns OperationInterface[]
+$sd->hasOperation($name);
+$sd->getOperation($name); // @returns OperationInterface|null
+$sd->addOperation($operation); // @param OperationInterface $operation
+```
+
+### Guzzle\Common\Inflection\Inflector
+
+Namespace is now `Guzzle\Inflection\Inflector`
+
+### Guzzle\Http\Plugin
+
+Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below.
+
+### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log
+
+Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively.
+
+**Before**
+
+```php
+use Guzzle\Common\Log\ClosureLogAdapter;
+use Guzzle\Http\Plugin\LogPlugin;
+
+/** @var \Guzzle\Http\Client */
+$client;
+
+// $verbosity is an integer indicating desired message verbosity level
+$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE);
+```
+
+**After**
+
+```php
+use Guzzle\Log\ClosureLogAdapter;
+use Guzzle\Log\MessageFormatter;
+use Guzzle\Plugin\Log\LogPlugin;
+
+/** @var \Guzzle\Http\Client */
+$client;
+
+// $format is a string indicating desired message format -- @see MessageFormatter
+$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT);
+```
+
+### Guzzle\Http\Plugin\CurlAuthPlugin
+
+Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`.
+
+### Guzzle\Http\Plugin\ExponentialBackoffPlugin
+
+Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes.
+
+**Before**
+
+```php
+use Guzzle\Http\Plugin\ExponentialBackoffPlugin;
+
+$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge(
+ ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429)
+ ));
+
+$client->addSubscriber($backoffPlugin);
+```
+
+**After**
+
+```php
+use Guzzle\Plugin\Backoff\BackoffPlugin;
+use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
+
+// Use convenient factory method instead -- see implementation for ideas of what
+// you can do with chaining backoff strategies
+$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge(
+ HttpBackoffStrategy::getDefaultFailureCodes(), array(429)
+ ));
+$client->addSubscriber($backoffPlugin);
+```
+
+### Known Issues
+
+#### [BUG] Accept-Encoding header behavior changed unintentionally.
+
+(See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e)
+
+In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to
+properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen.
+See issue #217 for a workaround, or use a version containing the fix.
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/composer.json b/public/system/storage/vendor/guzzlehttp/guzzle/composer.json
new file mode 100644
index 0000000..d8bb120
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/composer.json
@@ -0,0 +1,38 @@
+{
+ "name": "guzzlehttp/guzzle",
+ "type": "library",
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
+ "keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"],
+ "homepage": "http://guzzlephp.org/",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "guzzlehttp/ringphp": "^1.1",
+ "react/promise": "^2.2"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "GuzzleHttp\\Tests\\": "tests/"
+ }
+ },
+ "scripts": {
+ "test": "make test",
+ "test-ci": "make coverage"
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/BatchResults.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/BatchResults.php
new file mode 100644
index 0000000..e5af433
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/BatchResults.php
@@ -0,0 +1,148 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Represents the result of a batch operation. This result container is
+ * iterable, countable, and you can can get a result by value using the
+ * getResult function.
+ *
+ * Successful results are anything other than exceptions. Failure results are
+ * exceptions.
+ *
+ * @package GuzzleHttp
+ */
+class BatchResults implements \Countable, \IteratorAggregate, \ArrayAccess
+{
+ private $hash;
+
+ /**
+ * @param \SplObjectStorage $hash Hash of key objects to result values.
+ */
+ public function __construct(\SplObjectStorage $hash)
+ {
+ $this->hash = $hash;
+ }
+
+ /**
+ * Get the keys that are available on the batch result.
+ *
+ * @return array
+ */
+ public function getKeys()
+ {
+ return iterator_to_array($this->hash);
+ }
+
+ /**
+ * Gets a result from the container for the given object. When getting
+ * results for a batch of requests, provide the request object.
+ *
+ * @param object $forObject Object to retrieve the result for.
+ *
+ * @return mixed|null
+ */
+ public function getResult($forObject)
+ {
+ return isset($this->hash[$forObject]) ? $this->hash[$forObject] : null;
+ }
+
+ /**
+ * Get an array of successful results.
+ *
+ * @return array
+ */
+ public function getSuccessful()
+ {
+ $results = [];
+ foreach ($this->hash as $key) {
+ if (!($this->hash[$key] instanceof \Exception)) {
+ $results[] = $this->hash[$key];
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Get an array of failed results.
+ *
+ * @return array
+ */
+ public function getFailures()
+ {
+ $results = [];
+ foreach ($this->hash as $key) {
+ if ($this->hash[$key] instanceof \Exception) {
+ $results[] = $this->hash[$key];
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Allows iteration over all batch result values.
+ *
+ * @return \ArrayIterator
+ */
+ public function getIterator()
+ {
+ $results = [];
+ foreach ($this->hash as $key) {
+ $results[] = $this->hash[$key];
+ }
+
+ return new \ArrayIterator($results);
+ }
+
+ /**
+ * Counts the number of elements in the batch result.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->hash);
+ }
+
+ /**
+ * Checks if the batch contains a specific numerical array index.
+ *
+ * @param int $key Index to access
+ *
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return $key < count($this->hash);
+ }
+
+ /**
+ * Allows access of the batch using a numerical array index.
+ *
+ * @param int $key Index to access.
+ *
+ * @return mixed|null
+ */
+ public function offsetGet($key)
+ {
+ $i = -1;
+ foreach ($this->hash as $obj) {
+ if ($key === ++$i) {
+ return $this->hash[$obj];
+ }
+ }
+
+ return null;
+ }
+
+ public function offsetUnset($key)
+ {
+ throw new \RuntimeException('Not implemented');
+ }
+
+ public function offsetSet($key, $value)
+ {
+ throw new \RuntimeException('Not implemented');
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Client.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Client.php
new file mode 100644
index 0000000..cf5dd46
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Client.php
@@ -0,0 +1,362 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Event\HasEmitterTrait;
+use GuzzleHttp\Message\MessageFactory;
+use GuzzleHttp\Message\MessageFactoryInterface;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\FutureResponse;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Future\FutureInterface;
+use GuzzleHttp\Exception\RequestException;
+use React\Promise\FulfilledPromise;
+use React\Promise\RejectedPromise;
+
+/**
+ * HTTP client
+ */
+class Client implements ClientInterface
+{
+ use HasEmitterTrait;
+
+ /** @var MessageFactoryInterface Request factory used by the client */
+ private $messageFactory;
+
+ /** @var Url Base URL of the client */
+ private $baseUrl;
+
+ /** @var array Default request options */
+ private $defaults;
+
+ /** @var callable Request state machine */
+ private $fsm;
+
+ /**
+ * Clients accept an array of constructor parameters.
+ *
+ * Here's an example of creating a client using an URI template for the
+ * client's base_url and an array of default request options to apply
+ * to each request:
+ *
+ * $client = new Client([
+ * 'base_url' => [
+ * 'http://www.foo.com/{version}/',
+ * ['version' => '123']
+ * ],
+ * 'defaults' => [
+ * 'timeout' => 10,
+ * 'allow_redirects' => false,
+ * 'proxy' => '192.168.16.1:10'
+ * ]
+ * ]);
+ *
+ * @param array $config Client configuration settings
+ * - base_url: Base URL of the client that is merged into relative URLs.
+ * Can be a string or an array that contains a URI template followed
+ * by an associative array of expansion variables to inject into the
+ * URI template.
+ * - handler: callable RingPHP handler used to transfer requests
+ * - message_factory: Factory used to create request and response object
+ * - defaults: Default request options to apply to each request
+ * - emitter: Event emitter used for request events
+ * - fsm: (internal use only) The request finite state machine. A
+ * function that accepts a transaction and optional final state. The
+ * function is responsible for transitioning a request through its
+ * lifecycle events.
+ */
+ public function __construct(array $config = [])
+ {
+ $this->configureBaseUrl($config);
+ $this->configureDefaults($config);
+
+ if (isset($config['emitter'])) {
+ $this->emitter = $config['emitter'];
+ }
+
+ $this->messageFactory = isset($config['message_factory'])
+ ? $config['message_factory']
+ : new MessageFactory();
+
+ if (isset($config['fsm'])) {
+ $this->fsm = $config['fsm'];
+ } else {
+ if (isset($config['handler'])) {
+ $handler = $config['handler'];
+ } elseif (isset($config['adapter'])) {
+ $handler = $config['adapter'];
+ } else {
+ $handler = Utils::getDefaultHandler();
+ }
+ $this->fsm = new RequestFsm($handler, $this->messageFactory);
+ }
+ }
+
+ public function getDefaultOption($keyOrPath = null)
+ {
+ return $keyOrPath === null
+ ? $this->defaults
+ : Utils::getPath($this->defaults, $keyOrPath);
+ }
+
+ public function setDefaultOption($keyOrPath, $value)
+ {
+ Utils::setPath($this->defaults, $keyOrPath, $value);
+ }
+
+ public function getBaseUrl()
+ {
+ return (string) $this->baseUrl;
+ }
+
+ public function createRequest($method, $url = null, array $options = [])
+ {
+ $options = $this->mergeDefaults($options);
+ // Use a clone of the client's emitter
+ $options['config']['emitter'] = clone $this->getEmitter();
+ $url = $url || (is_string($url) && strlen($url))
+ ? $this->buildUrl($url)
+ : (string) $this->baseUrl;
+
+ return $this->messageFactory->createRequest($method, $url, $options);
+ }
+
+ public function get($url = null, $options = [])
+ {
+ return $this->send($this->createRequest('GET', $url, $options));
+ }
+
+ public function head($url = null, array $options = [])
+ {
+ return $this->send($this->createRequest('HEAD', $url, $options));
+ }
+
+ public function delete($url = null, array $options = [])
+ {
+ return $this->send($this->createRequest('DELETE', $url, $options));
+ }
+
+ public function put($url = null, array $options = [])
+ {
+ return $this->send($this->createRequest('PUT', $url, $options));
+ }
+
+ public function patch($url = null, array $options = [])
+ {
+ return $this->send($this->createRequest('PATCH', $url, $options));
+ }
+
+ public function post($url = null, array $options = [])
+ {
+ return $this->send($this->createRequest('POST', $url, $options));
+ }
+
+ public function options($url = null, array $options = [])
+ {
+ return $this->send($this->createRequest('OPTIONS', $url, $options));
+ }
+
+ public function send(RequestInterface $request)
+ {
+ $isFuture = $request->getConfig()->get('future');
+ $trans = new Transaction($this, $request, $isFuture);
+ $fn = $this->fsm;
+
+ try {
+ $fn($trans);
+ if ($isFuture) {
+ // Turn the normal response into a future if needed.
+ return $trans->response instanceof FutureInterface
+ ? $trans->response
+ : new FutureResponse(new FulfilledPromise($trans->response));
+ }
+ // Resolve deep futures if this is not a future
+ // transaction. This accounts for things like retries
+ // that do not have an immediate side-effect.
+ while ($trans->response instanceof FutureInterface) {
+ $trans->response = $trans->response->wait();
+ }
+ return $trans->response;
+ } catch (\Exception $e) {
+ if ($isFuture) {
+ // Wrap the exception in a promise
+ return new FutureResponse(new RejectedPromise($e));
+ }
+ throw RequestException::wrapException($trans->request, $e);
+ } catch (\TypeError $error) {
+ $exception = new \Exception($error->getMessage(), $error->getCode(), $error);
+ if ($isFuture) {
+ // Wrap the exception in a promise
+ return new FutureResponse(new RejectedPromise($exception));
+ }
+ throw RequestException::wrapException($trans->request, $exception);
+ }
+ }
+
+ /**
+ * Get an array of default options to apply to the client
+ *
+ * @return array
+ */
+ protected function getDefaultOptions()
+ {
+ $settings = [
+ 'allow_redirects' => true,
+ 'exceptions' => true,
+ 'decode_content' => true,
+ 'verify' => true
+ ];
+
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
+ // We can only trust the HTTP_PROXY environment variable in a CLI
+ // process due to the fact that PHP has no reliable mechanism to
+ // get environment variables that start with "HTTP_".
+ if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {
+ $settings['proxy']['http'] = getenv('HTTP_PROXY');
+ }
+
+ if ($proxy = getenv('HTTPS_PROXY')) {
+ $settings['proxy']['https'] = $proxy;
+ }
+
+ return $settings;
+ }
+
+ /**
+ * Expand a URI template and inherit from the base URL if it's relative
+ *
+ * @param string|array $url URL or an array of the URI template to expand
+ * followed by a hash of template varnames.
+ * @return string
+ * @throws \InvalidArgumentException
+ */
+ private function buildUrl($url)
+ {
+ // URI template (absolute or relative)
+ if (!is_array($url)) {
+ return strpos($url, '://')
+ ? (string) $url
+ : (string) $this->baseUrl->combine($url);
+ }
+
+ if (!isset($url[1])) {
+ throw new \InvalidArgumentException('You must provide a hash of '
+ . 'varname options in the second element of a URL array.');
+ }
+
+ // Absolute URL
+ if (strpos($url[0], '://')) {
+ return Utils::uriTemplate($url[0], $url[1]);
+ }
+
+ // Combine the relative URL with the base URL
+ return (string) $this->baseUrl->combine(
+ Utils::uriTemplate($url[0], $url[1])
+ );
+ }
+
+ private function configureBaseUrl(&$config)
+ {
+ if (!isset($config['base_url'])) {
+ $this->baseUrl = new Url('', '');
+ } elseif (!is_array($config['base_url'])) {
+ $this->baseUrl = Url::fromString($config['base_url']);
+ } elseif (count($config['base_url']) < 2) {
+ throw new \InvalidArgumentException('You must provide a hash of '
+ . 'varname options in the second element of a base_url array.');
+ } else {
+ $this->baseUrl = Url::fromString(
+ Utils::uriTemplate(
+ $config['base_url'][0],
+ $config['base_url'][1]
+ )
+ );
+ $config['base_url'] = (string) $this->baseUrl;
+ }
+ }
+
+ private function configureDefaults($config)
+ {
+ if (!isset($config['defaults'])) {
+ $this->defaults = $this->getDefaultOptions();
+ } else {
+ $this->defaults = array_replace(
+ $this->getDefaultOptions(),
+ $config['defaults']
+ );
+ }
+
+ // Add the default user-agent header
+ if (!isset($this->defaults['headers'])) {
+ $this->defaults['headers'] = [
+ 'User-Agent' => Utils::getDefaultUserAgent()
+ ];
+ } elseif (!Core::hasHeader($this->defaults, 'User-Agent')) {
+ // Add the User-Agent header if one was not already set
+ $this->defaults['headers']['User-Agent'] = Utils::getDefaultUserAgent();
+ }
+ }
+
+ /**
+ * Merges default options into the array passed by reference.
+ *
+ * @param array $options Options to modify by reference
+ *
+ * @return array
+ */
+ private function mergeDefaults($options)
+ {
+ $defaults = $this->defaults;
+
+ // Case-insensitively merge in default headers if both defaults and
+ // options have headers specified.
+ if (!empty($defaults['headers']) && !empty($options['headers'])) {
+ // Create a set of lowercased keys that are present.
+ $lkeys = [];
+ foreach (array_keys($options['headers']) as $k) {
+ $lkeys[strtolower($k)] = true;
+ }
+ // Merge in lowercase default keys when not present in above set.
+ foreach ($defaults['headers'] as $key => $value) {
+ if (!isset($lkeys[strtolower($key)])) {
+ $options['headers'][$key] = $value;
+ }
+ }
+ // No longer need to merge in headers.
+ unset($defaults['headers']);
+ }
+
+ $result = array_replace_recursive($defaults, $options);
+ foreach ($options as $k => $v) {
+ if ($v === null) {
+ unset($result[$k]);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * @deprecated Use {@see GuzzleHttp\Pool} instead.
+ * @see GuzzleHttp\Pool
+ */
+ public function sendAll($requests, array $options = [])
+ {
+ Pool::send($this, $requests, $options);
+ }
+
+ /**
+ * @deprecated Use GuzzleHttp\Utils::getDefaultHandler
+ */
+ public static function getDefaultHandler()
+ {
+ return Utils::getDefaultHandler();
+ }
+
+ /**
+ * @deprecated Use GuzzleHttp\Utils::getDefaultUserAgent
+ */
+ public static function getDefaultUserAgent()
+ {
+ return Utils::getDefaultUserAgent();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/ClientInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/ClientInterface.php
new file mode 100644
index 0000000..6668597
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/ClientInterface.php
@@ -0,0 +1,150 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Event\HasEmitterInterface;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Client interface for sending HTTP requests
+ */
+interface ClientInterface extends HasEmitterInterface
+{
+ const VERSION = '5.3.1';
+
+ /**
+ * Create and return a new {@see RequestInterface} object.
+ *
+ * Use an absolute path to override the base path of the client, or a
+ * relative path to append to the base path of the client. The URL can
+ * contain the query string as well. Use an array to provide a URL
+ * template and additional variables to use in the URL template expansion.
+ *
+ * @param string $method HTTP method
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return RequestInterface
+ */
+ public function createRequest($method, $url = null, array $options = []);
+
+ /**
+ * Send a GET request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function get($url = null, $options = []);
+
+ /**
+ * Send a HEAD request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function head($url = null, array $options = []);
+
+ /**
+ * Send a DELETE request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function delete($url = null, array $options = []);
+
+ /**
+ * Send a PUT request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function put($url = null, array $options = []);
+
+ /**
+ * Send a PATCH request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function patch($url = null, array $options = []);
+
+ /**
+ * Send a POST request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function post($url = null, array $options = []);
+
+ /**
+ * Send an OPTIONS request
+ *
+ * @param string|array|Url $url URL or URI template
+ * @param array $options Array of request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws RequestException When an error is encountered
+ */
+ public function options($url = null, array $options = []);
+
+ /**
+ * Sends a single request
+ *
+ * @param RequestInterface $request Request to send
+ *
+ * @return \GuzzleHttp\Message\ResponseInterface
+ * @throws \LogicException When the handler does not populate a response
+ * @throws RequestException When an error is encountered
+ */
+ public function send(RequestInterface $request);
+
+ /**
+ * Get default request options of the client.
+ *
+ * @param string|null $keyOrPath The Path to a particular default request
+ * option to retrieve or pass null to retrieve all default request
+ * options. The syntax uses "/" to denote a path through nested PHP
+ * arrays. For example, "headers/content-type".
+ *
+ * @return mixed
+ */
+ public function getDefaultOption($keyOrPath = null);
+
+ /**
+ * Set a default request option on the client so that any request created
+ * by the client will use the provided default value unless overridden
+ * explicitly when creating a request.
+ *
+ * @param string|null $keyOrPath The Path to a particular configuration
+ * value to set. The syntax uses a path notation that allows you to
+ * specify nested configuration values (e.g., 'headers/content-type').
+ * @param mixed $value Default request option value to set
+ */
+ public function setDefaultOption($keyOrPath, $value);
+
+ /**
+ * Get the base URL of the client.
+ *
+ * @return string Returns the base URL if present
+ */
+ public function getBaseUrl();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Collection.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Collection.php
new file mode 100644
index 0000000..4aabd20
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Collection.php
@@ -0,0 +1,236 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Key value pair collection object
+ */
+class Collection implements
+ \ArrayAccess,
+ \IteratorAggregate,
+ \Countable,
+ ToArrayInterface
+{
+ use HasDataTrait;
+
+ /**
+ * @param array $data Associative array of data to set
+ */
+ public function __construct(array $data = [])
+ {
+ $this->data = $data;
+ }
+
+ /**
+ * Create a new collection from an array, validate the keys, and add default
+ * values where missing
+ *
+ * @param array $config Configuration values to apply.
+ * @param array $defaults Default parameters
+ * @param array $required Required parameter names
+ *
+ * @return self
+ * @throws \InvalidArgumentException if a parameter is missing
+ */
+ public static function fromConfig(
+ array $config = [],
+ array $defaults = [],
+ array $required = []
+ ) {
+ $data = $config + $defaults;
+
+ if ($missing = array_diff($required, array_keys($data))) {
+ throw new \InvalidArgumentException(
+ 'Config is missing the following keys: ' .
+ implode(', ', $missing));
+ }
+
+ return new self($data);
+ }
+
+ /**
+ * Removes all key value pairs
+ */
+ public function clear()
+ {
+ $this->data = [];
+ }
+
+ /**
+ * Get a specific key value.
+ *
+ * @param string $key Key to retrieve.
+ *
+ * @return mixed|null Value of the key or NULL
+ */
+ public function get($key)
+ {
+ return isset($this->data[$key]) ? $this->data[$key] : null;
+ }
+
+ /**
+ * Set a key value pair
+ *
+ * @param string $key Key to set
+ * @param mixed $value Value to set
+ */
+ public function set($key, $value)
+ {
+ $this->data[$key] = $value;
+ }
+
+ /**
+ * Add a value to a key. If a key of the same name has already been added,
+ * the key value will be converted into an array and the new value will be
+ * pushed to the end of the array.
+ *
+ * @param string $key Key to add
+ * @param mixed $value Value to add to the key
+ */
+ public function add($key, $value)
+ {
+ if (!array_key_exists($key, $this->data)) {
+ $this->data[$key] = $value;
+ } elseif (is_array($this->data[$key])) {
+ $this->data[$key][] = $value;
+ } else {
+ $this->data[$key] = array($this->data[$key], $value);
+ }
+ }
+
+ /**
+ * Remove a specific key value pair
+ *
+ * @param string $key A key to remove
+ */
+ public function remove($key)
+ {
+ unset($this->data[$key]);
+ }
+
+ /**
+ * Get all keys in the collection
+ *
+ * @return array
+ */
+ public function getKeys()
+ {
+ return array_keys($this->data);
+ }
+
+ /**
+ * Returns whether or not the specified key is present.
+ *
+ * @param string $key The key for which to check the existence.
+ *
+ * @return bool
+ */
+ public function hasKey($key)
+ {
+ return array_key_exists($key, $this->data);
+ }
+
+ /**
+ * Checks if any keys contains a certain value
+ *
+ * @param string $value Value to search for
+ *
+ * @return mixed Returns the key if the value was found FALSE if the value
+ * was not found.
+ */
+ public function hasValue($value)
+ {
+ return array_search($value, $this->data, true);
+ }
+
+ /**
+ * Replace the data of the object with the value of an array
+ *
+ * @param array $data Associative array of data
+ */
+ public function replace(array $data)
+ {
+ $this->data = $data;
+ }
+
+ /**
+ * Add and merge in a Collection or array of key value pair data.
+ *
+ * @param Collection|array $data Associative array of key value pair data
+ */
+ public function merge($data)
+ {
+ foreach ($data as $key => $value) {
+ $this->add($key, $value);
+ }
+ }
+
+ /**
+ * Overwrite key value pairs in this collection with all of the data from
+ * an array or collection.
+ *
+ * @param array|\Traversable $data Values to override over this config
+ */
+ public function overwriteWith($data)
+ {
+ if (is_array($data)) {
+ $this->data = $data + $this->data;
+ } elseif ($data instanceof Collection) {
+ $this->data = $data->toArray() + $this->data;
+ } else {
+ foreach ($data as $key => $value) {
+ $this->data[$key] = $value;
+ }
+ }
+ }
+
+ /**
+ * Returns a Collection containing all the elements of the collection after
+ * applying the callback function to each one.
+ *
+ * The callable should accept three arguments:
+ * - (string) $key
+ * - (string) $value
+ * - (array) $context
+ *
+ * The callable must return a the altered or unaltered value.
+ *
+ * @param callable $closure Map function to apply
+ * @param array $context Context to pass to the callable
+ *
+ * @return Collection
+ */
+ public function map(callable $closure, array $context = [])
+ {
+ $collection = new static();
+ foreach ($this as $key => $value) {
+ $collection[$key] = $closure($key, $value, $context);
+ }
+
+ return $collection;
+ }
+
+ /**
+ * Iterates over each key value pair in the collection passing them to the
+ * callable. If the callable returns true, the current value from input is
+ * returned into the result Collection.
+ *
+ * The callable must accept two arguments:
+ * - (string) $key
+ * - (string) $value
+ *
+ * @param callable $closure Evaluation function
+ *
+ * @return Collection
+ */
+ public function filter(callable $closure)
+ {
+ $collection = new static();
+ foreach ($this->data as $key => $value) {
+ if ($closure($key, $value)) {
+ $collection[$key] = $value;
+ }
+ }
+
+ return $collection;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
new file mode 100644
index 0000000..f8ac7dd
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
@@ -0,0 +1,248 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\ToArrayInterface;
+
+/**
+ * Cookie jar that stores cookies an an array
+ */
+class CookieJar implements CookieJarInterface, ToArrayInterface
+{
+ /** @var SetCookie[] Loaded cookie data */
+ private $cookies = [];
+
+ /** @var bool */
+ private $strictMode;
+
+ /**
+ * @param bool $strictMode Set to true to throw exceptions when invalid
+ * cookies are added to the cookie jar.
+ * @param array $cookieArray Array of SetCookie objects or a hash of arrays
+ * that can be used with the SetCookie constructor
+ */
+ public function __construct($strictMode = false, $cookieArray = [])
+ {
+ $this->strictMode = $strictMode;
+
+ foreach ($cookieArray as $cookie) {
+ if (!($cookie instanceof SetCookie)) {
+ $cookie = new SetCookie($cookie);
+ }
+ $this->setCookie($cookie);
+ }
+ }
+
+ /**
+ * Create a new Cookie jar from an associative array and domain.
+ *
+ * @param array $cookies Cookies to create the jar from
+ * @param string $domain Domain to set the cookies to
+ *
+ * @return self
+ */
+ public static function fromArray(array $cookies, $domain)
+ {
+ $cookieJar = new self();
+ foreach ($cookies as $name => $value) {
+ $cookieJar->setCookie(new SetCookie([
+ 'Domain' => $domain,
+ 'Name' => $name,
+ 'Value' => $value,
+ 'Discard' => true
+ ]));
+ }
+
+ return $cookieJar;
+ }
+
+ /**
+ * Quote the cookie value if it is not already quoted and it contains
+ * problematic characters.
+ *
+ * @param string $value Value that may or may not need to be quoted
+ *
+ * @return string
+ */
+ public static function getCookieValue($value)
+ {
+ if (substr($value, 0, 1) !== '"' &&
+ substr($value, -1, 1) !== '"' &&
+ strpbrk($value, ';,')
+ ) {
+ $value = '"' . $value . '"';
+ }
+
+ return $value;
+ }
+
+ public function toArray()
+ {
+ return array_map(function (SetCookie $cookie) {
+ return $cookie->toArray();
+ }, $this->getIterator()->getArrayCopy());
+ }
+
+ public function clear($domain = null, $path = null, $name = null)
+ {
+ if (!$domain) {
+ $this->cookies = [];
+ return;
+ } elseif (!$path) {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) use ($path, $domain) {
+ return !$cookie->matchesDomain($domain);
+ }
+ );
+ } elseif (!$name) {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) use ($path, $domain) {
+ return !($cookie->matchesPath($path) &&
+ $cookie->matchesDomain($domain));
+ }
+ );
+ } else {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) use ($path, $domain, $name) {
+ return !($cookie->getName() == $name &&
+ $cookie->matchesPath($path) &&
+ $cookie->matchesDomain($domain));
+ }
+ );
+ }
+ }
+
+ public function clearSessionCookies()
+ {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) {
+ return !$cookie->getDiscard() && $cookie->getExpires();
+ }
+ );
+ }
+
+ public function setCookie(SetCookie $cookie)
+ {
+ // Only allow cookies with set and valid domain, name, value
+ $result = $cookie->validate();
+ if ($result !== true) {
+ if ($this->strictMode) {
+ throw new \RuntimeException('Invalid cookie: ' . $result);
+ } else {
+ $this->removeCookieIfEmpty($cookie);
+ return false;
+ }
+ }
+
+ // Resolve conflicts with previously set cookies
+ foreach ($this->cookies as $i => $c) {
+
+ // Two cookies are identical, when their path, and domain are
+ // identical.
+ if ($c->getPath() != $cookie->getPath() ||
+ $c->getDomain() != $cookie->getDomain() ||
+ $c->getName() != $cookie->getName()
+ ) {
+ continue;
+ }
+
+ // The previously set cookie is a discard cookie and this one is
+ // not so allow the new cookie to be set
+ if (!$cookie->getDiscard() && $c->getDiscard()) {
+ unset($this->cookies[$i]);
+ continue;
+ }
+
+ // If the new cookie's expiration is further into the future, then
+ // replace the old cookie
+ if ($cookie->getExpires() > $c->getExpires()) {
+ unset($this->cookies[$i]);
+ continue;
+ }
+
+ // If the value has changed, we better change it
+ if ($cookie->getValue() !== $c->getValue()) {
+ unset($this->cookies[$i]);
+ continue;
+ }
+
+ // The cookie exists, so no need to continue
+ return false;
+ }
+
+ $this->cookies[] = $cookie;
+
+ return true;
+ }
+
+ public function count()
+ {
+ return count($this->cookies);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator(array_values($this->cookies));
+ }
+
+ public function extractCookies(
+ RequestInterface $request,
+ ResponseInterface $response
+ ) {
+ if ($cookieHeader = $response->getHeaderAsArray('Set-Cookie')) {
+ foreach ($cookieHeader as $cookie) {
+ $sc = SetCookie::fromString($cookie);
+ if (!$sc->getDomain()) {
+ $sc->setDomain($request->getHost());
+ }
+ $this->setCookie($sc);
+ }
+ }
+ }
+
+ public function addCookieHeader(RequestInterface $request)
+ {
+ $values = [];
+ $scheme = $request->getScheme();
+ $host = $request->getHost();
+ $path = $request->getPath();
+
+ foreach ($this->cookies as $cookie) {
+ if ($cookie->matchesPath($path) &&
+ $cookie->matchesDomain($host) &&
+ !$cookie->isExpired() &&
+ (!$cookie->getSecure() || $scheme == 'https')
+ ) {
+ $values[] = $cookie->getName() . '='
+ . self::getCookieValue($cookie->getValue());
+ }
+ }
+
+ if ($values) {
+ $request->setHeader('Cookie', implode('; ', $values));
+ }
+ }
+
+ /**
+ * If a cookie already exists and the server asks to set it again with a
+ * null value, the cookie must be deleted.
+ *
+ * @param SetCookie $cookie
+ */
+ private function removeCookieIfEmpty(SetCookie $cookie)
+ {
+ $cookieValue = $cookie->getValue();
+ if ($cookieValue === null || $cookieValue === '') {
+ $this->clear(
+ $cookie->getDomain(),
+ $cookie->getPath(),
+ $cookie->getName()
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
new file mode 100644
index 0000000..4ea8567
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
@@ -0,0 +1,75 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Stores HTTP cookies.
+ *
+ * It extracts cookies from HTTP requests, and returns them in HTTP responses.
+ * CookieJarInterface instances automatically expire contained cookies when
+ * necessary. Subclasses are also responsible for storing and retrieving
+ * cookies from a file, database, etc.
+ *
+ * @link http://docs.python.org/2/library/cookielib.html Inspiration
+ */
+interface CookieJarInterface extends \Countable, \IteratorAggregate
+{
+ /**
+ * Add a Cookie header to a request.
+ *
+ * If no matching cookies are found in the cookie jar, then no Cookie
+ * header is added to the request.
+ *
+ * @param RequestInterface $request Request object to update
+ */
+ public function addCookieHeader(RequestInterface $request);
+
+ /**
+ * Extract cookies from an HTTP response and store them in the CookieJar.
+ *
+ * @param RequestInterface $request Request that was sent
+ * @param ResponseInterface $response Response that was received
+ */
+ public function extractCookies(
+ RequestInterface $request,
+ ResponseInterface $response
+ );
+
+ /**
+ * Sets a cookie in the cookie jar.
+ *
+ * @param SetCookie $cookie Cookie to set.
+ *
+ * @return bool Returns true on success or false on failure
+ */
+ public function setCookie(SetCookie $cookie);
+
+ /**
+ * Remove cookies currently held in the cookie jar.
+ *
+ * Invoking this method without arguments will empty the whole cookie jar.
+ * If given a $domain argument only cookies belonging to that domain will
+ * be removed. If given a $domain and $path argument, cookies belonging to
+ * the specified path within that domain are removed. If given all three
+ * arguments, then the cookie with the specified name, path and domain is
+ * removed.
+ *
+ * @param string $domain Clears cookies matching a domain
+ * @param string $path Clears cookies matching a domain and path
+ * @param string $name Clears cookies matching a domain, path, and name
+ *
+ * @return CookieJarInterface
+ */
+ public function clear($domain = null, $path = null, $name = null);
+
+ /**
+ * Discard all sessions cookies.
+ *
+ * Removes cookies that don't have an expire field or a have a discard
+ * field set to true. To be called when the user agent shuts down according
+ * to RFC 2965.
+ */
+ public function clearSessionCookies();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
new file mode 100644
index 0000000..e431851
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
@@ -0,0 +1,86 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use GuzzleHttp\Utils;
+
+/**
+ * Persists non-session cookies using a JSON formatted file
+ */
+class FileCookieJar extends CookieJar
+{
+ /** @var string filename */
+ private $filename;
+
+ /**
+ * Create a new FileCookieJar object
+ *
+ * @param string $cookieFile File to store the cookie data
+ *
+ * @throws \RuntimeException if the file cannot be found or created
+ */
+ public function __construct($cookieFile)
+ {
+ $this->filename = $cookieFile;
+
+ if (file_exists($cookieFile)) {
+ $this->load($cookieFile);
+ }
+ }
+
+ /**
+ * Saves the file when shutting down
+ */
+ public function __destruct()
+ {
+ $this->save($this->filename);
+ }
+
+ /**
+ * Saves the cookies to a file.
+ *
+ * @param string $filename File to save
+ * @throws \RuntimeException if the file cannot be found or created
+ */
+ public function save($filename)
+ {
+ $json = [];
+ foreach ($this as $cookie) {
+ if ($cookie->getExpires() && !$cookie->getDiscard()) {
+ $json[] = $cookie->toArray();
+ }
+ }
+
+ if (false === file_put_contents($filename, json_encode($json))) {
+ // @codeCoverageIgnoreStart
+ throw new \RuntimeException("Unable to save file {$filename}");
+ // @codeCoverageIgnoreEnd
+ }
+ }
+
+ /**
+ * Load cookies from a JSON formatted file.
+ *
+ * Old cookies are kept unless overwritten by newly loaded ones.
+ *
+ * @param string $filename Cookie file to load.
+ * @throws \RuntimeException if the file cannot be loaded.
+ */
+ public function load($filename)
+ {
+ $json = file_get_contents($filename);
+ if (false === $json) {
+ // @codeCoverageIgnoreStart
+ throw new \RuntimeException("Unable to load file {$filename}");
+ // @codeCoverageIgnoreEnd
+ }
+
+ $data = Utils::jsonDecode($json, true);
+ if (is_array($data)) {
+ foreach (Utils::jsonDecode($json, true) as $cookie) {
+ $this->setCookie(new SetCookie($cookie));
+ }
+ } elseif (strlen($data)) {
+ throw new \RuntimeException("Invalid cookie file: {$filename}");
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
new file mode 100644
index 0000000..71a02d5
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
@@ -0,0 +1,66 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use GuzzleHttp\Utils;
+
+/**
+ * Persists cookies in the client session
+ */
+class SessionCookieJar extends CookieJar
+{
+ /** @var string session key */
+ private $sessionKey;
+
+ /**
+ * Create a new SessionCookieJar object
+ *
+ * @param string $sessionKey Session key name to store the cookie data in session
+ */
+ public function __construct($sessionKey)
+ {
+ $this->sessionKey = $sessionKey;
+ $this->load();
+ }
+
+ /**
+ * Saves cookies to session when shutting down
+ */
+ public function __destruct()
+ {
+ $this->save();
+ }
+
+ /**
+ * Save cookies to the client session
+ */
+ public function save()
+ {
+ $json = [];
+ foreach ($this as $cookie) {
+ if ($cookie->getExpires() && !$cookie->getDiscard()) {
+ $json[] = $cookie->toArray();
+ }
+ }
+
+ $_SESSION[$this->sessionKey] = json_encode($json);
+ }
+
+ /**
+ * Load the contents of the client session into the data array
+ */
+ protected function load()
+ {
+ $cookieJar = isset($_SESSION[$this->sessionKey])
+ ? $_SESSION[$this->sessionKey]
+ : null;
+
+ $data = Utils::jsonDecode($cookieJar, true);
+ if (is_array($data)) {
+ foreach ($data as $cookie) {
+ $this->setCookie(new SetCookie($cookie));
+ }
+ } elseif (strlen($data)) {
+ throw new \RuntimeException("Invalid cookie data");
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
new file mode 100644
index 0000000..6fdee0d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
@@ -0,0 +1,373 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use GuzzleHttp\ToArrayInterface;
+
+/**
+ * Set-Cookie object
+ */
+class SetCookie implements ToArrayInterface
+{
+ /** @var array */
+ private static $defaults = [
+ 'Name' => null,
+ 'Value' => null,
+ 'Domain' => null,
+ 'Path' => '/',
+ 'Max-Age' => null,
+ 'Expires' => null,
+ 'Secure' => false,
+ 'Discard' => false,
+ 'HttpOnly' => false
+ ];
+
+ /** @var array Cookie data */
+ private $data;
+
+ /**
+ * Create a new SetCookie object from a string
+ *
+ * @param string $cookie Set-Cookie header string
+ *
+ * @return self
+ */
+ public static function fromString($cookie)
+ {
+ // Create the default return array
+ $data = self::$defaults;
+ // Explode the cookie string using a series of semicolons
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
+ // The name of the cookie (first kvp) must include an equal sign.
+ if (empty($pieces) || !strpos($pieces[0], '=')) {
+ return new self($data);
+ }
+
+ // Add the cookie pieces into the parsed data array
+ foreach ($pieces as $part) {
+
+ $cookieParts = explode('=', $part, 2);
+ $key = trim($cookieParts[0]);
+ $value = isset($cookieParts[1])
+ ? trim($cookieParts[1], " \n\r\t\0\x0B\"")
+ : true;
+
+ // Only check for non-cookies when cookies have been found
+ if (empty($data['Name'])) {
+ $data['Name'] = $key;
+ $data['Value'] = $value;
+ } else {
+ foreach (array_keys(self::$defaults) as $search) {
+ if (!strcasecmp($search, $key)) {
+ $data[$search] = $value;
+ continue 2;
+ }
+ }
+ $data[$key] = $value;
+ }
+ }
+
+ return new self($data);
+ }
+
+ /**
+ * @param array $data Array of cookie data provided by a Cookie parser
+ */
+ public function __construct(array $data = [])
+ {
+ $this->data = array_replace(self::$defaults, $data);
+ // Extract the Expires value and turn it into a UNIX timestamp if needed
+ if (!$this->getExpires() && $this->getMaxAge()) {
+ // Calculate the Expires date
+ $this->setExpires(time() + $this->getMaxAge());
+ } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
+ $this->setExpires($this->getExpires());
+ }
+ }
+
+ public function __toString()
+ {
+ $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
+ foreach ($this->data as $k => $v) {
+ if ($k != 'Name' && $k != 'Value' && $v !== null && $v !== false) {
+ if ($k == 'Expires') {
+ $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
+ } else {
+ $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
+ }
+ }
+ }
+
+ return rtrim($str, '; ');
+ }
+
+ public function toArray()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Get the cookie name
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->data['Name'];
+ }
+
+ /**
+ * Set the cookie name
+ *
+ * @param string $name Cookie name
+ */
+ public function setName($name)
+ {
+ $this->data['Name'] = $name;
+ }
+
+ /**
+ * Get the cookie value
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->data['Value'];
+ }
+
+ /**
+ * Set the cookie value
+ *
+ * @param string $value Cookie value
+ */
+ public function setValue($value)
+ {
+ $this->data['Value'] = $value;
+ }
+
+ /**
+ * Get the domain
+ *
+ * @return string|null
+ */
+ public function getDomain()
+ {
+ return $this->data['Domain'];
+ }
+
+ /**
+ * Set the domain of the cookie
+ *
+ * @param string $domain
+ */
+ public function setDomain($domain)
+ {
+ $this->data['Domain'] = $domain;
+ }
+
+ /**
+ * Get the path
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->data['Path'];
+ }
+
+ /**
+ * Set the path of the cookie
+ *
+ * @param string $path Path of the cookie
+ */
+ public function setPath($path)
+ {
+ $this->data['Path'] = $path;
+ }
+
+ /**
+ * Maximum lifetime of the cookie in seconds
+ *
+ * @return int|null
+ */
+ public function getMaxAge()
+ {
+ return $this->data['Max-Age'];
+ }
+
+ /**
+ * Set the max-age of the cookie
+ *
+ * @param int $maxAge Max age of the cookie in seconds
+ */
+ public function setMaxAge($maxAge)
+ {
+ $this->data['Max-Age'] = $maxAge;
+ }
+
+ /**
+ * The UNIX timestamp when the cookie Expires
+ *
+ * @return mixed
+ */
+ public function getExpires()
+ {
+ return $this->data['Expires'];
+ }
+
+ /**
+ * Set the unix timestamp for which the cookie will expire
+ *
+ * @param int $timestamp Unix timestamp
+ */
+ public function setExpires($timestamp)
+ {
+ $this->data['Expires'] = is_numeric($timestamp)
+ ? (int) $timestamp
+ : strtotime($timestamp);
+ }
+
+ /**
+ * Get whether or not this is a secure cookie
+ *
+ * @return null|bool
+ */
+ public function getSecure()
+ {
+ return $this->data['Secure'];
+ }
+
+ /**
+ * Set whether or not the cookie is secure
+ *
+ * @param bool $secure Set to true or false if secure
+ */
+ public function setSecure($secure)
+ {
+ $this->data['Secure'] = $secure;
+ }
+
+ /**
+ * Get whether or not this is a session cookie
+ *
+ * @return null|bool
+ */
+ public function getDiscard()
+ {
+ return $this->data['Discard'];
+ }
+
+ /**
+ * Set whether or not this is a session cookie
+ *
+ * @param bool $discard Set to true or false if this is a session cookie
+ */
+ public function setDiscard($discard)
+ {
+ $this->data['Discard'] = $discard;
+ }
+
+ /**
+ * Get whether or not this is an HTTP only cookie
+ *
+ * @return bool
+ */
+ public function getHttpOnly()
+ {
+ return $this->data['HttpOnly'];
+ }
+
+ /**
+ * Set whether or not this is an HTTP only cookie
+ *
+ * @param bool $httpOnly Set to true or false if this is HTTP only
+ */
+ public function setHttpOnly($httpOnly)
+ {
+ $this->data['HttpOnly'] = $httpOnly;
+ }
+
+ /**
+ * Check if the cookie matches a path value
+ *
+ * @param string $path Path to check against
+ *
+ * @return bool
+ */
+ public function matchesPath($path)
+ {
+ return !$this->getPath() || 0 === stripos($path, $this->getPath());
+ }
+
+ /**
+ * Check if the cookie matches a domain value
+ *
+ * @param string $domain Domain to check against
+ *
+ * @return bool
+ */
+ public function matchesDomain($domain)
+ {
+ // Remove the leading '.' as per spec in RFC 6265.
+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
+ $cookieDomain = ltrim($this->getDomain(), '.');
+
+ // Domain not set or exact match.
+ if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
+ return true;
+ }
+
+ // Matching the subdomain according to RFC 6265.
+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
+ if (filter_var($domain, FILTER_VALIDATE_IP)) {
+ return false;
+ }
+
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/i', $domain);
+ }
+
+ /**
+ * Check if the cookie is expired
+ *
+ * @return bool
+ */
+ public function isExpired()
+ {
+ return $this->getExpires() !== null && time() > $this->getExpires();
+ }
+
+ /**
+ * Check if the cookie is valid according to RFC 6265
+ *
+ * @return bool|string Returns true if valid or an error message if invalid
+ */
+ public function validate()
+ {
+ // Names must not be empty, but can be 0
+ $name = $this->getName();
+ if (empty($name) && !is_numeric($name)) {
+ return 'The cookie name must not be empty';
+ }
+
+ // Check if any of the invalid characters are present in the cookie name
+ if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
+ return "Cookie name must not cannot invalid characters: =,; \\t\\r\\n\\013\\014";
+ }
+
+ // Value must not be empty, but can be 0
+ $value = $this->getValue();
+ if (empty($value) && !is_numeric($value)) {
+ return 'The cookie value must not be empty';
+ }
+
+ // Domains must not be empty, but can be 0
+ // A "0" is not a valid internet domain, but may be used as server name
+ // in a private network.
+ $domain = $this->getDomain();
+ if (empty($domain) && !is_numeric($domain)) {
+ return 'The cookie domain must not be empty';
+ }
+
+ return true;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php
new file mode 100644
index 0000000..0d2f4db
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractEvent.php
@@ -0,0 +1,20 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Basic event class that can be extended.
+ */
+abstract class AbstractEvent implements EventInterface
+{
+ private $propagationStopped = false;
+
+ public function isPropagationStopped()
+ {
+ return $this->propagationStopped;
+ }
+
+ public function stopPropagation()
+ {
+ $this->propagationStopped = true;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php
new file mode 100644
index 0000000..8a6ee47
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRequestEvent.php
@@ -0,0 +1,61 @@
+<?php
+namespace GuzzleHttp\Event;
+
+use GuzzleHttp\Transaction;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Message\RequestInterface;
+
+/**
+ * Base class for request events, providing a request and client getter.
+ */
+abstract class AbstractRequestEvent extends AbstractEvent
+{
+ /** @var Transaction */
+ protected $transaction;
+
+ /**
+ * @param Transaction $transaction
+ */
+ public function __construct(Transaction $transaction)
+ {
+ $this->transaction = $transaction;
+ }
+
+ /**
+ * Get the HTTP client associated with the event.
+ *
+ * @return ClientInterface
+ */
+ public function getClient()
+ {
+ return $this->transaction->client;
+ }
+
+ /**
+ * Get the request object
+ *
+ * @return RequestInterface
+ */
+ public function getRequest()
+ {
+ return $this->transaction->request;
+ }
+
+ /**
+ * Get the number of transaction retries.
+ *
+ * @return int
+ */
+ public function getRetryCount()
+ {
+ return $this->transaction->retries;
+ }
+
+ /**
+ * @return Transaction
+ */
+ public function getTransaction()
+ {
+ return $this->transaction;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php
new file mode 100644
index 0000000..bbbdfaf
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractRetryableEvent.php
@@ -0,0 +1,40 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Abstract request event that can be retried.
+ */
+class AbstractRetryableEvent extends AbstractTransferEvent
+{
+ /**
+ * Mark the request as needing a retry and stop event propagation.
+ *
+ * This action allows you to retry a request without emitting the "end"
+ * event multiple times for a given request. When retried, the request
+ * emits a before event and is then sent again using the client that sent
+ * the original request.
+ *
+ * When retrying, it is important to limit the number of retries you allow
+ * to prevent infinite loops.
+ *
+ * This action can only be taken during the "complete" and "error" events.
+ *
+ * @param int $afterDelay If specified, the amount of time in milliseconds
+ * to delay before retrying. Note that this must
+ * be supported by the underlying RingPHP handler
+ * to work properly. Set to 0 or provide no value
+ * to retry immediately.
+ */
+ public function retry($afterDelay = 0)
+ {
+ // Setting the transition state to 'retry' will cause the next state
+ // transition of the transaction to retry the request.
+ $this->transaction->state = 'retry';
+
+ if ($afterDelay) {
+ $this->transaction->request->getConfig()->set('delay', $afterDelay);
+ }
+
+ $this->stopPropagation();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php
new file mode 100644
index 0000000..3b106df
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/AbstractTransferEvent.php
@@ -0,0 +1,63 @@
+<?php
+namespace GuzzleHttp\Event;
+
+use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\Ring\Future\FutureInterface;
+
+/**
+ * Event that contains transfer statistics, and can be intercepted.
+ */
+abstract class AbstractTransferEvent extends AbstractRequestEvent
+{
+ /**
+ * Get all transfer information as an associative array if no $name
+ * argument is supplied, or gets a specific transfer statistic if
+ * a $name attribute is supplied (e.g., 'total_time').
+ *
+ * @param string $name Name of the transfer stat to retrieve
+ *
+ * @return mixed|null|array
+ */
+ public function getTransferInfo($name = null)
+ {
+ if (!$name) {
+ return $this->transaction->transferInfo;
+ }
+
+ return isset($this->transaction->transferInfo[$name])
+ ? $this->transaction->transferInfo[$name]
+ : null;
+ }
+
+ /**
+ * Returns true/false if a response is available.
+ *
+ * @return bool
+ */
+ public function hasResponse()
+ {
+ return !($this->transaction->response instanceof FutureInterface);
+ }
+
+ /**
+ * Get the response.
+ *
+ * @return ResponseInterface|null
+ */
+ public function getResponse()
+ {
+ return $this->hasResponse() ? $this->transaction->response : null;
+ }
+
+ /**
+ * Intercept the request and associate a response
+ *
+ * @param ResponseInterface $response Response to set
+ */
+ public function intercept(ResponseInterface $response)
+ {
+ $this->transaction->response = $response;
+ $this->transaction->exception = null;
+ $this->stopPropagation();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php
new file mode 100644
index 0000000..f313c37
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/BeforeEvent.php
@@ -0,0 +1,26 @@
+<?php
+namespace GuzzleHttp\Event;
+
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Event object emitted before a request is sent.
+ *
+ * This event MAY be emitted multiple times (i.e., if a request is retried).
+ * You MAY change the Response associated with the request using the
+ * intercept() method of the event.
+ */
+class BeforeEvent extends AbstractRequestEvent
+{
+ /**
+ * Intercept the request and associate a response
+ *
+ * @param ResponseInterface $response Response to set
+ */
+ public function intercept(ResponseInterface $response)
+ {
+ $this->transaction->response = $response;
+ $this->transaction->exception = null;
+ $this->stopPropagation();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php
new file mode 100644
index 0000000..56cc557
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/CompleteEvent.php
@@ -0,0 +1,14 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Event object emitted after a request has been completed.
+ *
+ * This event MAY be emitted multiple times for a single request. You MAY
+ * change the Response associated with the request using the intercept()
+ * method of the event.
+ *
+ * This event allows the request to be retried if necessary using the retry()
+ * method of the event.
+ */
+class CompleteEvent extends AbstractRetryableEvent {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/Emitter.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/Emitter.php
new file mode 100644
index 0000000..d034fda
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/Emitter.php
@@ -0,0 +1,145 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Guzzle event emitter.
+ *
+ * Some of this class is based on the Symfony EventDispatcher component, which
+ * ships with the following license:
+ *
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher
+ */
+class Emitter implements EmitterInterface
+{
+ /** @var array */
+ private $listeners = [];
+
+ /** @var array */
+ private $sorted = [];
+
+ public function on($eventName, callable $listener, $priority = 0)
+ {
+ if ($priority === 'first') {
+ $priority = isset($this->listeners[$eventName])
+ ? max(array_keys($this->listeners[$eventName])) + 1
+ : 1;
+ } elseif ($priority === 'last') {
+ $priority = isset($this->listeners[$eventName])
+ ? min(array_keys($this->listeners[$eventName])) - 1
+ : -1;
+ }
+
+ $this->listeners[$eventName][$priority][] = $listener;
+ unset($this->sorted[$eventName]);
+ }
+
+ public function once($eventName, callable $listener, $priority = 0)
+ {
+ $onceListener = function (
+ EventInterface $event
+ ) use (&$onceListener, $eventName, $listener, $priority) {
+ $this->removeListener($eventName, $onceListener);
+ $listener($event, $eventName);
+ };
+
+ $this->on($eventName, $onceListener, $priority);
+ }
+
+ public function removeListener($eventName, callable $listener)
+ {
+ if (empty($this->listeners[$eventName])) {
+ return;
+ }
+
+ foreach ($this->listeners[$eventName] as $priority => $listeners) {
+ if (false !== ($key = array_search($listener, $listeners, true))) {
+ unset(
+ $this->listeners[$eventName][$priority][$key],
+ $this->sorted[$eventName]
+ );
+ }
+ }
+ }
+
+ public function listeners($eventName = null)
+ {
+ // Return all events in a sorted priority order
+ if ($eventName === null) {
+ foreach (array_keys($this->listeners) as $eventName) {
+ if (empty($this->sorted[$eventName])) {
+ $this->listeners($eventName);
+ }
+ }
+ return $this->sorted;
+ }
+
+ // Return the listeners for a specific event, sorted in priority order
+ if (empty($this->sorted[$eventName])) {
+ $this->sorted[$eventName] = [];
+ if (isset($this->listeners[$eventName])) {
+ krsort($this->listeners[$eventName], SORT_NUMERIC);
+ foreach ($this->listeners[$eventName] as $listeners) {
+ foreach ($listeners as $listener) {
+ $this->sorted[$eventName][] = $listener;
+ }
+ }
+ }
+ }
+
+ return $this->sorted[$eventName];
+ }
+
+ public function hasListeners($eventName)
+ {
+ return !empty($this->listeners[$eventName]);
+ }
+
+ public function emit($eventName, EventInterface $event)
+ {
+ if (isset($this->listeners[$eventName])) {
+ foreach ($this->listeners($eventName) as $listener) {
+ $listener($event, $eventName);
+ if ($event->isPropagationStopped()) {
+ break;
+ }
+ }
+ }
+
+ return $event;
+ }
+
+ public function attach(SubscriberInterface $subscriber)
+ {
+ foreach ($subscriber->getEvents() as $eventName => $listeners) {
+ if (is_array($listeners[0])) {
+ foreach ($listeners as $listener) {
+ $this->on(
+ $eventName,
+ [$subscriber, $listener[0]],
+ isset($listener[1]) ? $listener[1] : 0
+ );
+ }
+ } else {
+ $this->on(
+ $eventName,
+ [$subscriber, $listeners[0]],
+ isset($listeners[1]) ? $listeners[1] : 0
+ );
+ }
+ }
+ }
+
+ public function detach(SubscriberInterface $subscriber)
+ {
+ foreach ($subscriber->getEvents() as $eventName => $listener) {
+ $this->removeListener($eventName, [$subscriber, $listener[0]]);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php
new file mode 100644
index 0000000..9783efd
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EmitterInterface.php
@@ -0,0 +1,96 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Guzzle event emitter.
+ */
+interface EmitterInterface
+{
+ /**
+ * Binds a listener to a specific event.
+ *
+ * @param string $eventName Name of the event to bind to.
+ * @param callable $listener Listener to invoke when triggered.
+ * @param int|string $priority The higher this value, the earlier an event
+ * listener will be triggered in the chain (defaults to 0). You can
+ * pass "first" or "last" to dynamically specify the event priority
+ * based on the current event priorities associated with the given
+ * event name in the emitter. Use "first" to set the priority to the
+ * current highest priority plus one. Use "last" to set the priority to
+ * the current lowest event priority minus one.
+ */
+ public function on($eventName, callable $listener, $priority = 0);
+
+ /**
+ * Binds a listener to a specific event. After the listener is triggered
+ * once, it is removed as a listener.
+ *
+ * @param string $eventName Name of the event to bind to.
+ * @param callable $listener Listener to invoke when triggered.
+ * @param int $priority The higher this value, the earlier an event
+ * listener will be triggered in the chain (defaults to 0)
+ */
+ public function once($eventName, callable $listener, $priority = 0);
+
+ /**
+ * Removes an event listener from the specified event.
+ *
+ * @param string $eventName The event to remove a listener from
+ * @param callable $listener The listener to remove
+ */
+ public function removeListener($eventName, callable $listener);
+
+ /**
+ * Gets the listeners of a specific event or all listeners if no event is
+ * specified.
+ *
+ * @param string $eventName The name of the event. Pass null (the default)
+ * to retrieve all listeners.
+ *
+ * @return array The event listeners for the specified event, or all event
+ * listeners by event name. The format of the array when retrieving a
+ * specific event list is an array of callables. The format of the array
+ * when retrieving all listeners is an associative array of arrays of
+ * callables.
+ */
+ public function listeners($eventName = null);
+
+ /**
+ * Checks if the emitter has listeners by the given name.
+ *
+ * @param string $eventName The name of the event to check.
+ *
+ * @return bool
+ */
+ public function hasListeners($eventName);
+
+ /**
+ * Emits an event to all registered listeners.
+ *
+ * Each event that is bound to the emitted eventName receives a
+ * EventInterface, the name of the event, and the event emitter.
+ *
+ * @param string $eventName The name of the event to dispatch.
+ * @param EventInterface $event The event to pass to the event handlers/listeners.
+ *
+ * @return EventInterface Returns the provided event object
+ */
+ public function emit($eventName, EventInterface $event);
+
+ /**
+ * Attaches an event subscriber.
+ *
+ * The subscriber is asked for all the events it is interested in and added
+ * as an event listener for each event.
+ *
+ * @param SubscriberInterface $subscriber Subscriber to attach.
+ */
+ public function attach(SubscriberInterface $subscriber);
+
+ /**
+ * Detaches an event subscriber.
+ *
+ * @param SubscriberInterface $subscriber Subscriber to detach.
+ */
+ public function detach(SubscriberInterface $subscriber);
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EndEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EndEvent.php
new file mode 100644
index 0000000..c89432b
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EndEvent.php
@@ -0,0 +1,28 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * A terminal event that is emitted when a request transaction has ended.
+ *
+ * This event is emitted for both successful responses and responses that
+ * encountered an exception. You need to check if an exception is present
+ * in your listener to know the difference.
+ *
+ * You MAY intercept the response associated with the event if needed, but keep
+ * in mind that the "complete" event will not be triggered as a result.
+ */
+class EndEvent extends AbstractTransferEvent
+{
+ /**
+ * Get the exception that was encountered (if any).
+ *
+ * This method should be used to check if the request was sent successfully
+ * or if it encountered errors.
+ *
+ * @return \Exception|null
+ */
+ public function getException()
+ {
+ return $this->transaction->exception;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php
new file mode 100644
index 0000000..7432134
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ErrorEvent.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Event;
+
+use GuzzleHttp\Exception\RequestException;
+
+/**
+ * Event emitted when an error occurs while sending a request.
+ *
+ * This event MAY be emitted multiple times. You MAY intercept the exception
+ * and inject a response into the event to rescue the request using the
+ * intercept() method of the event.
+ *
+ * This event allows the request to be retried using the "retry" method of the
+ * event.
+ */
+class ErrorEvent extends AbstractRetryableEvent
+{
+ /**
+ * Get the exception that was encountered
+ *
+ * @return RequestException
+ */
+ public function getException()
+ {
+ return $this->transaction->exception;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EventInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EventInterface.php
new file mode 100644
index 0000000..97247e8
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/EventInterface.php
@@ -0,0 +1,23 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Base event interface used when dispatching events to listeners using an
+ * event emitter.
+ */
+interface EventInterface
+{
+ /**
+ * Returns whether or not stopPropagation was called on the event.
+ *
+ * @return bool
+ * @see Event::stopPropagation
+ */
+ public function isPropagationStopped();
+
+ /**
+ * Stops the propagation of the event, preventing subsequent listeners
+ * registered to the same event from being invoked.
+ */
+ public function stopPropagation();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php
new file mode 100644
index 0000000..a1a8612
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterInterface.php
@@ -0,0 +1,15 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Holds an event emitter
+ */
+interface HasEmitterInterface
+{
+ /**
+ * Get the event emitter of the object
+ *
+ * @return EmitterInterface
+ */
+ public function getEmitter();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php
new file mode 100644
index 0000000..8e36ce3
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/HasEmitterTrait.php
@@ -0,0 +1,20 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Trait that implements the methods of HasEmitterInterface
+ */
+trait HasEmitterTrait
+{
+ /** @var EmitterInterface */
+ private $emitter;
+
+ public function getEmitter()
+ {
+ if (!$this->emitter) {
+ $this->emitter = new Emitter();
+ }
+
+ return $this->emitter;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php
new file mode 100644
index 0000000..407dc92
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ListenerAttacherTrait.php
@@ -0,0 +1,88 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Trait that provides methods for extract event listeners specified in an array
+ * and attaching them to an emitter owned by the object or one of its direct
+ * dependencies.
+ */
+trait ListenerAttacherTrait
+{
+ /**
+ * Attaches event listeners and properly sets their priorities and whether
+ * or not they are are only executed once.
+ *
+ * @param HasEmitterInterface $object Object that has the event emitter.
+ * @param array $listeners Array of hashes representing event
+ * event listeners. Each item contains
+ * "name", "fn", "priority", & "once".
+ */
+ private function attachListeners(HasEmitterInterface $object, array $listeners)
+ {
+ $emitter = $object->getEmitter();
+ foreach ($listeners as $el) {
+ if ($el['once']) {
+ $emitter->once($el['name'], $el['fn'], $el['priority']);
+ } else {
+ $emitter->on($el['name'], $el['fn'], $el['priority']);
+ }
+ }
+ }
+
+ /**
+ * Extracts the allowed events from the provided array, and ignores anything
+ * else in the array. The event listener must be specified as a callable or
+ * as an array of event listener data ("name", "fn", "priority", "once").
+ *
+ * @param array $source Array containing callables or hashes of data to be
+ * prepared as event listeners.
+ * @param array $events Names of events to look for in the provided $source
+ * array. Other keys are ignored.
+ * @return array
+ */
+ private function prepareListeners(array $source, array $events)
+ {
+ $listeners = [];
+ foreach ($events as $name) {
+ if (isset($source[$name])) {
+ $this->buildListener($name, $source[$name], $listeners);
+ }
+ }
+
+ return $listeners;
+ }
+
+ /**
+ * Creates a complete event listener definition from the provided array of
+ * listener data. Also works recursively if more than one listeners are
+ * contained in the provided array.
+ *
+ * @param string $name Name of the event the listener is for.
+ * @param array|callable $data Event listener data to prepare.
+ * @param array $listeners Array of listeners, passed by reference.
+ *
+ * @throws \InvalidArgumentException if the event data is malformed.
+ */
+ private function buildListener($name, $data, &$listeners)
+ {
+ static $defaults = ['priority' => 0, 'once' => false];
+
+ // If a callable is provided, normalize it to the array format.
+ if (is_callable($data)) {
+ $data = ['fn' => $data];
+ }
+
+ // Prepare the listener and add it to the array, recursively.
+ if (isset($data['fn'])) {
+ $data['name'] = $name;
+ $listeners[] = $data + $defaults;
+ } elseif (is_array($data)) {
+ foreach ($data as $listenerData) {
+ $this->buildListener($name, $listenerData, $listeners);
+ }
+ } else {
+ throw new \InvalidArgumentException('Each event listener must be a '
+ . 'callable or an associative array containing a "fn" key.');
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php
new file mode 100644
index 0000000..3fd0de4
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/ProgressEvent.php
@@ -0,0 +1,51 @@
+<?php
+namespace GuzzleHttp\Event;
+
+use GuzzleHttp\Transaction;
+
+/**
+ * Event object emitted when upload or download progress is made.
+ *
+ * You can access the progress values using their corresponding public
+ * properties:
+ *
+ * - $downloadSize: The number of bytes that will be downloaded (if known)
+ * - $downloaded: The number of bytes that have been downloaded
+ * - $uploadSize: The number of bytes that will be uploaded (if known)
+ * - $uploaded: The number of bytes that have been uploaded
+ */
+class ProgressEvent extends AbstractRequestEvent
+{
+ /** @var int Amount of data to be downloaded */
+ public $downloadSize;
+
+ /** @var int Amount of data that has been downloaded */
+ public $downloaded;
+
+ /** @var int Amount of data to upload */
+ public $uploadSize;
+
+ /** @var int Amount of data that has been uploaded */
+ public $uploaded;
+
+ /**
+ * @param Transaction $transaction Transaction being sent.
+ * @param int $downloadSize Amount of data to download (if known)
+ * @param int $downloaded Amount of data that has been downloaded
+ * @param int $uploadSize Amount of data to upload (if known)
+ * @param int $uploaded Amount of data that had been uploaded
+ */
+ public function __construct(
+ Transaction $transaction,
+ $downloadSize,
+ $downloaded,
+ $uploadSize,
+ $uploaded
+ ) {
+ parent::__construct($transaction);
+ $this->downloadSize = $downloadSize;
+ $this->downloaded = $downloaded;
+ $this->uploadSize = $uploadSize;
+ $this->uploaded = $uploaded;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php
new file mode 100644
index 0000000..f51d420
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/RequestEvents.php
@@ -0,0 +1,56 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * Contains methods used to manage the request event lifecycle.
+ */
+final class RequestEvents
+{
+ // Generic event priorities
+ const EARLY = 10000;
+ const LATE = -10000;
+
+ // "before" priorities
+ const PREPARE_REQUEST = -100;
+ const SIGN_REQUEST = -10000;
+
+ // "complete" and "error" response priorities
+ const VERIFY_RESPONSE = 100;
+ const REDIRECT_RESPONSE = 200;
+
+ /**
+ * Converts an array of event options into a formatted array of valid event
+ * configuration.
+ *
+ * @param array $options Event array to convert
+ * @param array $events Event names to convert in the options array.
+ * @param mixed $handler Event handler to utilize
+ *
+ * @return array
+ * @throws \InvalidArgumentException if the event config is invalid
+ * @internal
+ */
+ public static function convertEventArray(
+ array $options,
+ array $events,
+ $handler
+ ) {
+ foreach ($events as $name) {
+ if (!isset($options[$name])) {
+ $options[$name] = [$handler];
+ } elseif (is_callable($options[$name])) {
+ $options[$name] = [$options[$name], $handler];
+ } elseif (is_array($options[$name])) {
+ if (isset($options[$name]['fn'])) {
+ $options[$name] = [$options[$name], $handler];
+ } else {
+ $options[$name][] = $handler;
+ }
+ } else {
+ throw new \InvalidArgumentException('Invalid event format');
+ }
+ }
+
+ return $options;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php
new file mode 100644
index 0000000..33d7702
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Event/SubscriberInterface.php
@@ -0,0 +1,34 @@
+<?php
+namespace GuzzleHttp\Event;
+
+/**
+ * SubscriberInterface provides an array of events to an
+ * EventEmitterInterface when it is registered. The emitter then binds the
+ * listeners specified by the EventSubscriber.
+ *
+ * This interface is based on the SubscriberInterface of the Symfony.
+ * @link https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher
+ */
+interface SubscriberInterface
+{
+ /**
+ * Returns an array of event names this subscriber wants to listen to.
+ *
+ * The returned array keys MUST map to an event name. Each array value
+ * MUST be an array in which the first element is the name of a function
+ * on the EventSubscriber OR an array of arrays in the aforementioned
+ * format. The second element in the array is optional, and if specified,
+ * designates the event priority.
+ *
+ * For example, the following are all valid:
+ *
+ * - ['eventName' => ['methodName']]
+ * - ['eventName' => ['methodName', $priority]]
+ * - ['eventName' => [['methodName'], ['otherMethod']]
+ * - ['eventName' => [['methodName'], ['otherMethod', $priority]]
+ * - ['eventName' => [['methodName', $priority], ['otherMethod', $priority]]
+ *
+ * @return array
+ */
+ public function getEvents();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
new file mode 100644
index 0000000..fd78431
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when an HTTP error occurs (4xx or 5xx error)
+ */
+class BadResponseException extends RequestException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
new file mode 100644
index 0000000..f95c09f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when a client error is encountered (4xx codes)
+ */
+class ClientException extends BadResponseException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
new file mode 100644
index 0000000..a91c5a6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class ConnectException extends RequestException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php
new file mode 100644
index 0000000..fbe2dcd
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/CouldNotRewindStreamException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class CouldNotRewindStreamException extends RequestException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ParseException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ParseException.php
new file mode 100644
index 0000000..e593e3d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ParseException.php
@@ -0,0 +1,31 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Exception when a client is unable to parse the response body as XML or JSON
+ */
+class ParseException extends TransferException
+{
+ /** @var ResponseInterface */
+ private $response;
+
+ public function __construct(
+ $message = '',
+ ResponseInterface $response = null,
+ \Exception $previous = null
+ ) {
+ parent::__construct($message, 0, $previous);
+ $this->response = $response;
+ }
+ /**
+ * Get the associated response
+ *
+ * @return ResponseInterface|null
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
new file mode 100644
index 0000000..3f052d3
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
@@ -0,0 +1,121 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\Ring\Exception\ConnectException;
+use GuzzleHttp\Exception\ConnectException as HttpConnectException;
+use GuzzleHttp\Ring\Future\FutureInterface;
+
+/**
+ * HTTP Request exception
+ */
+class RequestException extends TransferException
+{
+ /** @var RequestInterface */
+ private $request;
+
+ /** @var ResponseInterface */
+ private $response;
+
+ public function __construct(
+ $message,
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ \Exception $previous = null
+ ) {
+ // Set the code of the exception if the response is set and not future.
+ $code = $response && !($response instanceof FutureInterface)
+ ? $response->getStatusCode()
+ : 0;
+ parent::__construct($message, $code, $previous);
+ $this->request = $request;
+ $this->response = $response;
+ }
+
+ /**
+ * Wrap non-RequestExceptions with a RequestException
+ *
+ * @param RequestInterface $request
+ * @param \Exception $e
+ *
+ * @return RequestException
+ */
+ public static function wrapException(RequestInterface $request, \Exception $e)
+ {
+ if ($e instanceof RequestException) {
+ return $e;
+ } elseif ($e instanceof ConnectException) {
+ return new HttpConnectException($e->getMessage(), $request, null, $e);
+ } else {
+ return new RequestException($e->getMessage(), $request, null, $e);
+ }
+ }
+
+ /**
+ * Factory method to create a new exception with a normalized error message
+ *
+ * @param RequestInterface $request Request
+ * @param ResponseInterface $response Response received
+ * @param \Exception $previous Previous exception
+ *
+ * @return self
+ */
+ public static function create(
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ \Exception $previous = null
+ ) {
+ if (!$response) {
+ return new self('Error completing request', $request, null, $previous);
+ }
+
+ $level = floor($response->getStatusCode() / 100);
+ if ($level == '4') {
+ $label = 'Client error response';
+ $className = __NAMESPACE__ . '\\ClientException';
+ } elseif ($level == '5') {
+ $label = 'Server error response';
+ $className = __NAMESPACE__ . '\\ServerException';
+ } else {
+ $label = 'Unsuccessful response';
+ $className = __CLASS__;
+ }
+
+ $message = $label . ' [url] ' . $request->getUrl()
+ . ' [status code] ' . $response->getStatusCode()
+ . ' [reason phrase] ' . $response->getReasonPhrase();
+
+ return new $className($message, $request, $response, $previous);
+ }
+
+ /**
+ * Get the request that caused the exception
+ *
+ * @return RequestInterface
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * Get the associated response
+ *
+ * @return ResponseInterface|null
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ /**
+ * Check if a response was received
+ *
+ * @return bool
+ */
+ public function hasResponse()
+ {
+ return $this->response !== null;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
new file mode 100644
index 0000000..7cdd340
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when a server error is encountered (5xx codes)
+ */
+class ServerException extends BadResponseException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/StateException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/StateException.php
new file mode 100644
index 0000000..a7652a3
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/StateException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class StateException extends TransferException {};
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
new file mode 100644
index 0000000..b60a967
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class TooManyRedirectsException extends RequestException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
new file mode 100644
index 0000000..92d7de6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class TransferException extends \RuntimeException {}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php
new file mode 100644
index 0000000..a4a1a0a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Exception/XmlParseException.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace GuzzleHttp\Exception;
+
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Exception when a client is unable to parse the response body as XML
+ */
+class XmlParseException extends ParseException
+{
+ /** @var \LibXMLError */
+ protected $error;
+
+ public function __construct(
+ $message = '',
+ ResponseInterface $response = null,
+ \Exception $previous = null,
+ \LibXMLError $error = null
+ ) {
+ parent::__construct($message, $response, $previous);
+ $this->error = $error;
+ }
+
+ /**
+ * Get the associated error
+ *
+ * @return \LibXMLError|null
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/HasDataTrait.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/HasDataTrait.php
new file mode 100644
index 0000000..020dfc9
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/HasDataTrait.php
@@ -0,0 +1,75 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Trait implementing ToArrayInterface, \ArrayAccess, \Countable,
+ * \IteratorAggregate, and some path style methods.
+ */
+trait HasDataTrait
+{
+ /** @var array */
+ protected $data = [];
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->data);
+ }
+
+ public function offsetGet($offset)
+ {
+ return isset($this->data[$offset]) ? $this->data[$offset] : null;
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->data[$offset] = $value;
+ }
+
+ public function offsetExists($offset)
+ {
+ return isset($this->data[$offset]);
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->data[$offset]);
+ }
+
+ public function toArray()
+ {
+ return $this->data;
+ }
+
+ public function count()
+ {
+ return count($this->data);
+ }
+
+ /**
+ * Get a value from the collection using a path syntax to retrieve nested
+ * data.
+ *
+ * @param string $path Path to traverse and retrieve a value from
+ *
+ * @return mixed|null
+ */
+ public function getPath($path)
+ {
+ return Utils::getPath($this->data, $path);
+ }
+
+ /**
+ * Set a value into a nested array key. Keys will be created as needed to
+ * set the value.
+ *
+ * @param string $path Path to set
+ * @param mixed $value Value to set at the key
+ *
+ * @throws \RuntimeException when trying to setPath using a nested path
+ * that travels through a scalar value
+ */
+ public function setPath($path, $value)
+ {
+ Utils::setPath($this->data, $path, $value);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php
new file mode 100644
index 0000000..f118e0f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AbstractMessage.php
@@ -0,0 +1,253 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Stream\StreamInterface;
+
+abstract class AbstractMessage implements MessageInterface
+{
+ /** @var array HTTP header collection */
+ private $headers = [];
+
+ /** @var array mapping a lowercase header name to its name over the wire */
+ private $headerNames = [];
+
+ /** @var StreamInterface Message body */
+ private $body;
+
+ /** @var string HTTP protocol version of the message */
+ private $protocolVersion = '1.1';
+
+ public function __toString()
+ {
+ return static::getStartLineAndHeaders($this)
+ . "\r\n\r\n" . $this->getBody();
+ }
+
+ public function getProtocolVersion()
+ {
+ return $this->protocolVersion;
+ }
+
+ public function getBody()
+ {
+ return $this->body;
+ }
+
+ public function setBody(StreamInterface $body = null)
+ {
+ if ($body === null) {
+ // Setting a null body will remove the body of the request
+ $this->removeHeader('Content-Length');
+ $this->removeHeader('Transfer-Encoding');
+ }
+
+ $this->body = $body;
+ }
+
+ public function addHeader($header, $value)
+ {
+ if (is_array($value)) {
+ $current = array_merge($this->getHeaderAsArray($header), $value);
+ } else {
+ $current = $this->getHeaderAsArray($header);
+ $current[] = (string) $value;
+ }
+
+ $this->setHeader($header, $current);
+ }
+
+ public function addHeaders(array $headers)
+ {
+ foreach ($headers as $name => $header) {
+ $this->addHeader($name, $header);
+ }
+ }
+
+ public function getHeader($header)
+ {
+ $name = strtolower($header);
+ return isset($this->headers[$name])
+ ? implode(', ', $this->headers[$name])
+ : '';
+ }
+
+ public function getHeaderAsArray($header)
+ {
+ $name = strtolower($header);
+ return isset($this->headers[$name]) ? $this->headers[$name] : [];
+ }
+
+ public function getHeaders()
+ {
+ $headers = [];
+ foreach ($this->headers as $name => $values) {
+ $headers[$this->headerNames[$name]] = $values;
+ }
+
+ return $headers;
+ }
+
+ public function setHeader($header, $value)
+ {
+ $header = trim($header);
+ $name = strtolower($header);
+ $this->headerNames[$name] = $header;
+
+ if (is_array($value)) {
+ foreach ($value as &$v) {
+ $v = trim($v);
+ }
+ $this->headers[$name] = $value;
+ } else {
+ $this->headers[$name] = [trim($value)];
+ }
+ }
+
+ public function setHeaders(array $headers)
+ {
+ $this->headers = $this->headerNames = [];
+ foreach ($headers as $key => $value) {
+ $this->addHeader($key, $value);
+ }
+ }
+
+ public function hasHeader($header)
+ {
+ return isset($this->headers[strtolower($header)]);
+ }
+
+ public function removeHeader($header)
+ {
+ $name = strtolower($header);
+ unset($this->headers[$name], $this->headerNames[$name]);
+ }
+
+ /**
+ * Parse an array of header values containing ";" separated data into an
+ * array of associative arrays representing the header key value pair
+ * data of the header. When a parameter does not contain a value, but just
+ * contains a key, this function will inject a key with a '' string value.
+ *
+ * @param MessageInterface $message That contains the header
+ * @param string $header Header to retrieve from the message
+ *
+ * @return array Returns the parsed header values.
+ */
+ public static function parseHeader(MessageInterface $message, $header)
+ {
+ static $trimmed = "\"' \n\t\r";
+ $params = $matches = [];
+
+ foreach (self::normalizeHeader($message, $header) as $val) {
+ $part = [];
+ foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
+ if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
+ $m = $matches[0];
+ if (isset($m[1])) {
+ $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
+ } else {
+ $part[] = trim($m[0], $trimmed);
+ }
+ }
+ }
+ if ($part) {
+ $params[] = $part;
+ }
+ }
+
+ return $params;
+ }
+
+ /**
+ * Converts an array of header values that may contain comma separated
+ * headers into an array of headers with no comma separated values.
+ *
+ * @param MessageInterface $message That contains the header
+ * @param string $header Header to retrieve from the message
+ *
+ * @return array Returns the normalized header field values.
+ */
+ public static function normalizeHeader(MessageInterface $message, $header)
+ {
+ $h = $message->getHeaderAsArray($header);
+ for ($i = 0, $total = count($h); $i < $total; $i++) {
+ if (strpos($h[$i], ',') === false) {
+ continue;
+ }
+ foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $h[$i]) as $v) {
+ $h[] = trim($v);
+ }
+ unset($h[$i]);
+ }
+
+ return $h;
+ }
+
+ /**
+ * Gets the start-line and headers of a message as a string
+ *
+ * @param MessageInterface $message
+ *
+ * @return string
+ */
+ public static function getStartLineAndHeaders(MessageInterface $message)
+ {
+ return static::getStartLine($message)
+ . self::getHeadersAsString($message);
+ }
+
+ /**
+ * Gets the headers of a message as a string
+ *
+ * @param MessageInterface $message
+ *
+ * @return string
+ */
+ public static function getHeadersAsString(MessageInterface $message)
+ {
+ $result = '';
+ foreach ($message->getHeaders() as $name => $values) {
+ $result .= "\r\n{$name}: " . implode(', ', $values);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Gets the start line of a message
+ *
+ * @param MessageInterface $message
+ *
+ * @return string
+ * @throws \InvalidArgumentException
+ */
+ public static function getStartLine(MessageInterface $message)
+ {
+ if ($message instanceof RequestInterface) {
+ return trim($message->getMethod() . ' '
+ . $message->getResource())
+ . ' HTTP/' . $message->getProtocolVersion();
+ } elseif ($message instanceof ResponseInterface) {
+ return 'HTTP/' . $message->getProtocolVersion() . ' '
+ . $message->getStatusCode() . ' '
+ . $message->getReasonPhrase();
+ } else {
+ throw new \InvalidArgumentException('Unknown message type');
+ }
+ }
+
+ /**
+ * Accepts and modifies the options provided to the message in the
+ * constructor.
+ *
+ * Can be overridden in subclasses as necessary.
+ *
+ * @param array $options Options array passed by reference.
+ */
+ protected function handleOptions(array &$options)
+ {
+ if (isset($options['protocol_version'])) {
+ $this->protocolVersion = $options['protocol_version'];
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AppliesHeadersInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AppliesHeadersInterface.php
new file mode 100644
index 0000000..ca42f20
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/AppliesHeadersInterface.php
@@ -0,0 +1,24 @@
+<?php
+namespace GuzzleHttp\Message;
+
+/**
+ * Applies headers to a request.
+ *
+ * This interface can be used with Guzzle streams to apply body specific
+ * headers to a request during the PREPARE_REQUEST priority of the before event
+ *
+ * NOTE: a body that implements this interface will prevent a default
+ * content-type from being added to a request during the before event. If you
+ * want a default content-type to be added, then it will need to be done
+ * manually (e.g., using {@see GuzzleHttp\Mimetypes}).
+ */
+interface AppliesHeadersInterface
+{
+ /**
+ * Apply headers to a request appropriate for the current state of the
+ * object.
+ *
+ * @param RequestInterface $request Request
+ */
+ public function applyRequestHeaders(RequestInterface $request);
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php
new file mode 100644
index 0000000..5e5037e
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php
@@ -0,0 +1,158 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Ring\Future\MagicFutureTrait;
+use GuzzleHttp\Ring\Future\FutureInterface;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Represents a response that has not been fulfilled.
+ *
+ * When created, you must provide a function that is used to dereference the
+ * future result and return it's value. The function has no arguments and MUST
+ * return an instance of a {@see GuzzleHttp\Message\ResponseInterface} object.
+ *
+ * You can optionally provide a function in the constructor that can be used to
+ * cancel the future from completing if possible. This function has no
+ * arguments and returns a boolean value representing whether or not the
+ * response could be cancelled.
+ *
+ * @property ResponseInterface $_value
+ */
+class FutureResponse implements ResponseInterface, FutureInterface
+{
+ use MagicFutureTrait;
+
+ /**
+ * Returns a FutureResponse that wraps another future.
+ *
+ * @param FutureInterface $future Future to wrap with a new future
+ * @param callable $onFulfilled Invoked when the future fulfilled
+ * @param callable $onRejected Invoked when the future rejected
+ * @param callable $onProgress Invoked when the future progresses
+ *
+ * @return FutureResponse
+ */
+ public static function proxy(
+ FutureInterface $future,
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return new FutureResponse(
+ $future->then($onFulfilled, $onRejected, $onProgress),
+ [$future, 'wait'],
+ [$future, 'cancel']
+ );
+ }
+
+ public function getStatusCode()
+ {
+ return $this->_value->getStatusCode();
+ }
+
+ public function setStatusCode($code)
+ {
+ $this->_value->setStatusCode($code);
+ }
+
+ public function getReasonPhrase()
+ {
+ return $this->_value->getReasonPhrase();
+ }
+
+ public function setReasonPhrase($phrase)
+ {
+ $this->_value->setReasonPhrase($phrase);
+ }
+
+ public function getEffectiveUrl()
+ {
+ return $this->_value->getEffectiveUrl();
+ }
+
+ public function setEffectiveUrl($url)
+ {
+ $this->_value->setEffectiveUrl($url);
+ }
+
+ public function json(array $config = [])
+ {
+ return $this->_value->json($config);
+ }
+
+ public function xml(array $config = [])
+ {
+ return $this->_value->xml($config);
+ }
+
+ public function __toString()
+ {
+ try {
+ return $this->_value->__toString();
+ } catch (\Exception $e) {
+ trigger_error($e->getMessage(), E_USER_WARNING);
+ return '';
+ }
+ }
+
+ public function getProtocolVersion()
+ {
+ return $this->_value->getProtocolVersion();
+ }
+
+ public function setBody(StreamInterface $body = null)
+ {
+ $this->_value->setBody($body);
+ }
+
+ public function getBody()
+ {
+ return $this->_value->getBody();
+ }
+
+ public function getHeaders()
+ {
+ return $this->_value->getHeaders();
+ }
+
+ public function getHeader($header)
+ {
+ return $this->_value->getHeader($header);
+ }
+
+ public function getHeaderAsArray($header)
+ {
+ return $this->_value->getHeaderAsArray($header);
+ }
+
+ public function hasHeader($header)
+ {
+ return $this->_value->hasHeader($header);
+ }
+
+ public function removeHeader($header)
+ {
+ $this->_value->removeHeader($header);
+ }
+
+ public function addHeader($header, $value)
+ {
+ $this->_value->addHeader($header, $value);
+ }
+
+ public function addHeaders(array $headers)
+ {
+ $this->_value->addHeaders($headers);
+ }
+
+ public function setHeader($header, $value)
+ {
+ $this->_value->setHeader($header, $value);
+ }
+
+ public function setHeaders(array $headers)
+ {
+ $this->_value->setHeaders($headers);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php
new file mode 100644
index 0000000..b366d6d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactory.php
@@ -0,0 +1,364 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Cookie\CookieJar;
+use GuzzleHttp\Cookie\CookieJarInterface;
+use GuzzleHttp\Event\ListenerAttacherTrait;
+use GuzzleHttp\Post\PostBody;
+use GuzzleHttp\Post\PostFile;
+use GuzzleHttp\Post\PostFileInterface;
+use GuzzleHttp\Query;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Subscriber\Cookie;
+use GuzzleHttp\Subscriber\HttpError;
+use GuzzleHttp\Subscriber\Redirect;
+use GuzzleHttp\Url;
+use \InvalidArgumentException as Iae;
+
+/**
+ * Default HTTP request factory used to create Request and Response objects.
+ */
+class MessageFactory implements MessageFactoryInterface
+{
+ use ListenerAttacherTrait;
+
+ /** @var HttpError */
+ private $errorPlugin;
+
+ /** @var Redirect */
+ private $redirectPlugin;
+
+ /** @var array */
+ private $customOptions;
+
+ /** @var array Request options passed through to request Config object */
+ private static $configMap = [
+ 'connect_timeout' => 1, 'timeout' => 1, 'verify' => 1, 'ssl_key' => 1,
+ 'cert' => 1, 'proxy' => 1, 'debug' => 1, 'save_to' => 1, 'stream' => 1,
+ 'expect' => 1, 'future' => 1
+ ];
+
+ /** @var array Default allow_redirects request option settings */
+ private static $defaultRedirect = [
+ 'max' => 5,
+ 'strict' => false,
+ 'referer' => false,
+ 'protocols' => ['http', 'https']
+ ];
+
+ /**
+ * @param array $customOptions Associative array of custom request option
+ * names mapping to functions used to apply
+ * the option. The function accepts the request
+ * and the option value to apply.
+ */
+ public function __construct(array $customOptions = [])
+ {
+ $this->errorPlugin = new HttpError();
+ $this->redirectPlugin = new Redirect();
+ $this->customOptions = $customOptions;
+ }
+
+ public function createResponse(
+ $statusCode,
+ array $headers = [],
+ $body = null,
+ array $options = []
+ ) {
+ if (null !== $body) {
+ $body = Stream::factory($body);
+ }
+
+ return new Response($statusCode, $headers, $body, $options);
+ }
+
+ public function createRequest($method, $url, array $options = [])
+ {
+ // Handle the request protocol version option that needs to be
+ // specified in the request constructor.
+ if (isset($options['version'])) {
+ $options['config']['protocol_version'] = $options['version'];
+ unset($options['version']);
+ }
+
+ $request = new Request($method, $url, [], null,
+ isset($options['config']) ? $options['config'] : []);
+
+ unset($options['config']);
+
+ // Use a POST body by default
+ if (strtoupper($method) == 'POST'
+ && !isset($options['body'])
+ && !isset($options['json'])
+ ) {
+ $options['body'] = [];
+ }
+
+ if ($options) {
+ $this->applyOptions($request, $options);
+ }
+
+ return $request;
+ }
+
+ /**
+ * Create a request or response object from an HTTP message string
+ *
+ * @param string $message Message to parse
+ *
+ * @return RequestInterface|ResponseInterface
+ * @throws \InvalidArgumentException if unable to parse a message
+ */
+ public function fromMessage($message)
+ {
+ static $parser;
+ if (!$parser) {
+ $parser = new MessageParser();
+ }
+
+ // Parse a response
+ if (strtoupper(substr($message, 0, 4)) == 'HTTP') {
+ $data = $parser->parseResponse($message);
+ return $this->createResponse(
+ $data['code'],
+ $data['headers'],
+ $data['body'] === '' ? null : $data['body'],
+ $data
+ );
+ }
+
+ // Parse a request
+ if (!($data = ($parser->parseRequest($message)))) {
+ throw new \InvalidArgumentException('Unable to parse request');
+ }
+
+ return $this->createRequest(
+ $data['method'],
+ Url::buildUrl($data['request_url']),
+ [
+ 'headers' => $data['headers'],
+ 'body' => $data['body'] === '' ? null : $data['body'],
+ 'config' => [
+ 'protocol_version' => $data['protocol_version']
+ ]
+ ]
+ );
+ }
+
+ /**
+ * Apply POST fields and files to a request to attempt to give an accurate
+ * representation.
+ *
+ * @param RequestInterface $request Request to update
+ * @param array $body Body to apply
+ */
+ protected function addPostData(RequestInterface $request, array $body)
+ {
+ static $fields = ['string' => true, 'array' => true, 'NULL' => true,
+ 'boolean' => true, 'double' => true, 'integer' => true];
+
+ $post = new PostBody();
+ foreach ($body as $key => $value) {
+ if (isset($fields[gettype($value)])) {
+ $post->setField($key, $value);
+ } elseif ($value instanceof PostFileInterface) {
+ $post->addFile($value);
+ } else {
+ $post->addFile(new PostFile($key, $value));
+ }
+ }
+
+ if ($request->getHeader('Content-Type') == 'multipart/form-data') {
+ $post->forceMultipartUpload(true);
+ }
+
+ $request->setBody($post);
+ }
+
+ protected function applyOptions(
+ RequestInterface $request,
+ array $options = []
+ ) {
+ $config = $request->getConfig();
+ $emitter = $request->getEmitter();
+
+ foreach ($options as $key => $value) {
+
+ if (isset(self::$configMap[$key])) {
+ $config[$key] = $value;
+ continue;
+ }
+
+ switch ($key) {
+
+ case 'allow_redirects':
+
+ if ($value === false) {
+ continue 2;
+ }
+
+ if ($value === true) {
+ $value = self::$defaultRedirect;
+ } elseif (!is_array($value)) {
+ throw new Iae('allow_redirects must be true, false, or array');
+ } else {
+ // Merge the default settings with the provided settings
+ $value += self::$defaultRedirect;
+ }
+
+ $config['redirect'] = $value;
+ $emitter->attach($this->redirectPlugin);
+ break;
+
+ case 'decode_content':
+
+ if ($value === false) {
+ continue 2;
+ }
+
+ $config['decode_content'] = true;
+ if ($value !== true) {
+ $request->setHeader('Accept-Encoding', $value);
+ }
+ break;
+
+ case 'headers':
+
+ if (!is_array($value)) {
+ throw new Iae('header value must be an array');
+ }
+ foreach ($value as $k => $v) {
+ $request->setHeader($k, $v);
+ }
+ break;
+
+ case 'exceptions':
+
+ if ($value === true) {
+ $emitter->attach($this->errorPlugin);
+ }
+ break;
+
+ case 'body':
+
+ if (is_array($value)) {
+ $this->addPostData($request, $value);
+ } elseif ($value !== null) {
+ $request->setBody(Stream::factory($value));
+ }
+ break;
+
+ case 'auth':
+
+ if (!$value) {
+ continue 2;
+ }
+
+ if (is_array($value)) {
+ $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
+ } else {
+ $type = strtolower($value);
+ }
+
+ $config['auth'] = $value;
+
+ if ($type == 'basic') {
+ $request->setHeader(
+ 'Authorization',
+ 'Basic ' . base64_encode("$value[0]:$value[1]")
+ );
+ } elseif ($type == 'digest') {
+ // @todo: Do not rely on curl
+ $config->setPath('curl/' . CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ $config->setPath('curl/' . CURLOPT_USERPWD, "$value[0]:$value[1]");
+ }
+ break;
+
+ case 'query':
+
+ if ($value instanceof Query) {
+ $original = $request->getQuery();
+ // Do not overwrite existing query string variables by
+ // overwriting the object with the query string data passed
+ // in the URL
+ $value->overwriteWith($original->toArray());
+ $request->setQuery($value);
+ } elseif (is_array($value)) {
+ // Do not overwrite existing query string variables
+ $query = $request->getQuery();
+ foreach ($value as $k => $v) {
+ if (!isset($query[$k])) {
+ $query[$k] = $v;
+ }
+ }
+ } else {
+ throw new Iae('query must be an array or Query object');
+ }
+ break;
+
+ case 'cookies':
+
+ if ($value === true) {
+ static $cookie = null;
+ if (!$cookie) {
+ $cookie = new Cookie();
+ }
+ $emitter->attach($cookie);
+ } elseif (is_array($value)) {
+ $emitter->attach(
+ new Cookie(CookieJar::fromArray($value, $request->getHost()))
+ );
+ } elseif ($value instanceof CookieJarInterface) {
+ $emitter->attach(new Cookie($value));
+ } elseif ($value !== false) {
+ throw new Iae('cookies must be an array, true, or CookieJarInterface');
+ }
+ break;
+
+ case 'events':
+
+ if (!is_array($value)) {
+ throw new Iae('events must be an array');
+ }
+
+ $this->attachListeners($request,
+ $this->prepareListeners(
+ $value,
+ ['before', 'complete', 'error', 'progress', 'end']
+ )
+ );
+ break;
+
+ case 'subscribers':
+
+ if (!is_array($value)) {
+ throw new Iae('subscribers must be an array');
+ }
+
+ foreach ($value as $subscribers) {
+ $emitter->attach($subscribers);
+ }
+ break;
+
+ case 'json':
+
+ $request->setBody(Stream::factory(json_encode($value)));
+ if (!$request->hasHeader('Content-Type')) {
+ $request->setHeader('Content-Type', 'application/json');
+ }
+ break;
+
+ default:
+
+ // Check for custom handler functions.
+ if (isset($this->customOptions[$key])) {
+ $fn = $this->customOptions[$key];
+ $fn($request, $value);
+ continue 2;
+ }
+
+ throw new Iae("No method can handle the {$key} config key");
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php
new file mode 100644
index 0000000..86ae9c7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageFactoryInterface.php
@@ -0,0 +1,71 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Url;
+
+/**
+ * Request and response factory
+ */
+interface MessageFactoryInterface
+{
+ /**
+ * Creates a response
+ *
+ * @param string $statusCode HTTP status code
+ * @param array $headers Response headers
+ * @param mixed $body Response body
+ * @param array $options Response options
+ * - protocol_version: HTTP protocol version
+ * - header_factory: Factory used to create headers
+ * - And any other options used by a concrete message implementation
+ *
+ * @return ResponseInterface
+ */
+ public function createResponse(
+ $statusCode,
+ array $headers = [],
+ $body = null,
+ array $options = []
+ );
+
+ /**
+ * Create a new request based on the HTTP method.
+ *
+ * This method accepts an associative array of request options. Below is a
+ * brief description of each parameter. See
+ * http://docs.guzzlephp.org/en/latest/clients.html#request-options for a much more
+ * in-depth description of each parameter.
+ *
+ * - headers: Associative array of headers to add to the request
+ * - body: string|resource|array|StreamInterface request body to send
+ * - json: mixed Uploads JSON encoded data using an application/json Content-Type header.
+ * - query: Associative array of query string values to add to the request
+ * - auth: array|string HTTP auth settings (user, pass[, type="basic"])
+ * - version: The HTTP protocol version to use with the request
+ * - cookies: true|false|CookieJarInterface To enable or disable cookies
+ * - allow_redirects: true|false|array Controls HTTP redirects
+ * - save_to: string|resource|StreamInterface Where the response is saved
+ * - events: Associative array of event names to callables or arrays
+ * - subscribers: Array of event subscribers to add to the request
+ * - exceptions: Specifies whether or not exceptions are thrown for HTTP protocol errors
+ * - timeout: Timeout of the request in seconds. Use 0 to wait indefinitely
+ * - connect_timeout: Number of seconds to wait while trying to connect. (0 to wait indefinitely)
+ * - verify: SSL validation. True/False or the path to a PEM file
+ * - cert: Path a SSL cert or array of (path, pwd)
+ * - ssl_key: Path to a private SSL key or array of (path, pwd)
+ * - proxy: Specify an HTTP proxy or hash of protocols to proxies
+ * - debug: Set to true or a resource to view handler specific debug info
+ * - stream: Set to true to stream a response body rather than download it all up front
+ * - expect: true/false/integer Controls the "Expect: 100-Continue" header
+ * - config: Associative array of request config collection options
+ * - decode_content: true/false/string to control decoding content-encoding responses
+ *
+ * @param string $method HTTP method (GET, POST, PUT, etc.)
+ * @param string|Url $url HTTP URL to connect to
+ * @param array $options Array of options to apply to the request
+ *
+ * @return RequestInterface
+ * @link http://docs.guzzlephp.org/en/latest/clients.html#request-options
+ */
+ public function createRequest($method, $url, array $options = []);
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php
new file mode 100644
index 0000000..b2b472b
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageInterface.php
@@ -0,0 +1,136 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Request and response message interface
+ */
+interface MessageInterface
+{
+ /**
+ * Get a string representation of the message
+ *
+ * @return string
+ */
+ public function __toString();
+
+ /**
+ * Get the HTTP protocol version of the message
+ *
+ * @return string
+ */
+ public function getProtocolVersion();
+
+ /**
+ * Sets the body of the message.
+ *
+ * The body MUST be a StreamInterface object. Setting the body to null MUST
+ * remove the existing body.
+ *
+ * @param StreamInterface|null $body Body.
+ */
+ public function setBody(StreamInterface $body = null);
+
+ /**
+ * Get the body of the message
+ *
+ * @return StreamInterface|null
+ */
+ public function getBody();
+
+ /**
+ * Gets all message headers.
+ *
+ * The keys represent the header name as it will be sent over the wire, and
+ * each value is an array of strings associated with the header.
+ *
+ * // Represent the headers as a string
+ * foreach ($message->getHeaders() as $name => $values) {
+ * echo $name . ": " . implode(", ", $values);
+ * }
+ *
+ * @return array Returns an associative array of the message's headers.
+ */
+ public function getHeaders();
+
+ /**
+ * Retrieve a header by the given case-insensitive name.
+ *
+ * @param string $header Case-insensitive header name.
+ *
+ * @return string
+ */
+ public function getHeader($header);
+
+ /**
+ * Retrieves a header by the given case-insensitive name as an array of strings.
+ *
+ * @param string $header Case-insensitive header name.
+ *
+ * @return string[]
+ */
+ public function getHeaderAsArray($header);
+
+ /**
+ * Checks if a header exists by the given case-insensitive name.
+ *
+ * @param string $header Case-insensitive header name.
+ *
+ * @return bool Returns true if any header names match the given header
+ * name using a case-insensitive string comparison. Returns false if
+ * no matching header name is found in the message.
+ */
+ public function hasHeader($header);
+
+ /**
+ * Remove a specific header by case-insensitive name.
+ *
+ * @param string $header Case-insensitive header name.
+ */
+ public function removeHeader($header);
+
+ /**
+ * Appends a header value to any existing values associated with the
+ * given header name.
+ *
+ * @param string $header Header name to add
+ * @param string $value Value of the header
+ */
+ public function addHeader($header, $value);
+
+ /**
+ * Merges in an associative array of headers.
+ *
+ * Each array key MUST be a string representing the case-insensitive name
+ * of a header. Each value MUST be either a string or an array of strings.
+ * For each value, the value is appended to any existing header of the same
+ * name, or, if a header does not already exist by the given name, then the
+ * header is added.
+ *
+ * @param array $headers Associative array of headers to add to the message
+ */
+ public function addHeaders(array $headers);
+
+ /**
+ * Sets a header, replacing any existing values of any headers with the
+ * same case-insensitive name.
+ *
+ * The header values MUST be a string or an array of strings.
+ *
+ * @param string $header Header name
+ * @param string|array $value Header value(s)
+ */
+ public function setHeader($header, $value);
+
+ /**
+ * Sets headers, replacing any headers that have already been set on the
+ * message.
+ *
+ * The array keys MUST be a string. The array values must be either a
+ * string or an array of strings.
+ *
+ * @param array $headers Headers to set.
+ */
+ public function setHeaders(array $headers);
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageParser.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageParser.php
new file mode 100644
index 0000000..c3cc195
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/MessageParser.php
@@ -0,0 +1,171 @@
+<?php
+namespace GuzzleHttp\Message;
+
+/**
+ * Request and response parser used by Guzzle
+ */
+class MessageParser
+{
+ /**
+ * Parse an HTTP request message into an associative array of parts.
+ *
+ * @param string $message HTTP request to parse
+ *
+ * @return array|bool Returns false if the message is invalid
+ */
+ public function parseRequest($message)
+ {
+ if (!($parts = $this->parseMessage($message))) {
+ return false;
+ }
+
+ // Parse the protocol and protocol version
+ if (isset($parts['start_line'][2])) {
+ $startParts = explode('/', $parts['start_line'][2]);
+ $protocol = strtoupper($startParts[0]);
+ $version = isset($startParts[1]) ? $startParts[1] : '1.1';
+ } else {
+ $protocol = 'HTTP';
+ $version = '1.1';
+ }
+
+ $parsed = [
+ 'method' => strtoupper($parts['start_line'][0]),
+ 'protocol' => $protocol,
+ 'protocol_version' => $version,
+ 'headers' => $parts['headers'],
+ 'body' => $parts['body']
+ ];
+
+ $parsed['request_url'] = $this->getUrlPartsFromMessage(
+ (isset($parts['start_line'][1]) ? $parts['start_line'][1] : ''), $parsed);
+
+ return $parsed;
+ }
+
+ /**
+ * Parse an HTTP response message into an associative array of parts.
+ *
+ * @param string $message HTTP response to parse
+ *
+ * @return array|bool Returns false if the message is invalid
+ */
+ public function parseResponse($message)
+ {
+ if (!($parts = $this->parseMessage($message))) {
+ return false;
+ }
+
+ list($protocol, $version) = explode('/', trim($parts['start_line'][0]));
+
+ return [
+ 'protocol' => $protocol,
+ 'protocol_version' => $version,
+ 'code' => $parts['start_line'][1],
+ 'reason_phrase' => isset($parts['start_line'][2]) ? $parts['start_line'][2] : '',
+ 'headers' => $parts['headers'],
+ 'body' => $parts['body']
+ ];
+ }
+
+ /**
+ * Parse a message into parts
+ *
+ * @param string $message Message to parse
+ *
+ * @return array|bool
+ */
+ private function parseMessage($message)
+ {
+ if (!$message) {
+ return false;
+ }
+
+ $startLine = null;
+ $headers = [];
+ $body = '';
+
+ // Iterate over each line in the message, accounting for line endings
+ $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
+ for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
+
+ $line = $lines[$i];
+
+ // If two line breaks were encountered, then this is the end of body
+ if (empty($line)) {
+ if ($i < $totalLines - 1) {
+ $body = implode('', array_slice($lines, $i + 2));
+ }
+ break;
+ }
+
+ // Parse message headers
+ if (!$startLine) {
+ $startLine = explode(' ', $line, 3);
+ } elseif (strpos($line, ':')) {
+ $parts = explode(':', $line, 2);
+ $key = trim($parts[0]);
+ $value = isset($parts[1]) ? trim($parts[1]) : '';
+ if (!isset($headers[$key])) {
+ $headers[$key] = $value;
+ } elseif (!is_array($headers[$key])) {
+ $headers[$key] = [$headers[$key], $value];
+ } else {
+ $headers[$key][] = $value;
+ }
+ }
+ }
+
+ return [
+ 'start_line' => $startLine,
+ 'headers' => $headers,
+ 'body' => $body
+ ];
+ }
+
+ /**
+ * Create URL parts from HTTP message parts
+ *
+ * @param string $requestUrl Associated URL
+ * @param array $parts HTTP message parts
+ *
+ * @return array
+ */
+ private function getUrlPartsFromMessage($requestUrl, array $parts)
+ {
+ // Parse the URL information from the message
+ $urlParts = ['path' => $requestUrl, 'scheme' => 'http'];
+
+ // Check for the Host header
+ if (isset($parts['headers']['Host'])) {
+ $urlParts['host'] = $parts['headers']['Host'];
+ } elseif (isset($parts['headers']['host'])) {
+ $urlParts['host'] = $parts['headers']['host'];
+ } else {
+ $urlParts['host'] = null;
+ }
+
+ if (false === strpos($urlParts['host'], ':')) {
+ $urlParts['port'] = '';
+ } else {
+ $hostParts = explode(':', $urlParts['host']);
+ $urlParts['host'] = trim($hostParts[0]);
+ $urlParts['port'] = (int) trim($hostParts[1]);
+ if ($urlParts['port'] == 443) {
+ $urlParts['scheme'] = 'https';
+ }
+ }
+
+ // Check if a query is present
+ $path = $urlParts['path'];
+ $qpos = strpos($path, '?');
+ if ($qpos) {
+ $urlParts['query'] = substr($path, $qpos + 1);
+ $urlParts['path'] = substr($path, 0, $qpos);
+ } else {
+ $urlParts['query'] = '';
+ }
+
+ return $urlParts;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Request.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Request.php
new file mode 100644
index 0000000..38714af
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Request.php
@@ -0,0 +1,195 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Collection;
+use GuzzleHttp\Event\HasEmitterTrait;
+use GuzzleHttp\Subscriber\Prepare;
+use GuzzleHttp\Url;
+
+/**
+ * HTTP request class to send requests
+ */
+class Request extends AbstractMessage implements RequestInterface
+{
+ use HasEmitterTrait;
+
+ /** @var Url HTTP Url */
+ private $url;
+
+ /** @var string HTTP method */
+ private $method;
+
+ /** @var Collection Transfer options */
+ private $transferOptions;
+
+ /**
+ * @param string $method HTTP method
+ * @param string|Url $url HTTP URL to connect to. The URI scheme,
+ * host header, and URI are parsed from the full URL. If query string
+ * parameters are present they will be parsed as well.
+ * @param array|Collection $headers HTTP headers
+ * @param mixed $body Body to send with the request
+ * @param array $options Array of options to use with the request
+ * - emitter: Event emitter to use with the request
+ */
+ public function __construct(
+ $method,
+ $url,
+ $headers = [],
+ $body = null,
+ array $options = []
+ ) {
+ $this->setUrl($url);
+ $this->method = strtoupper($method);
+ $this->handleOptions($options);
+ $this->transferOptions = new Collection($options);
+ $this->addPrepareEvent();
+
+ if ($body !== null) {
+ $this->setBody($body);
+ }
+
+ if ($headers) {
+ foreach ($headers as $key => $value) {
+ $this->addHeader($key, $value);
+ }
+ }
+ }
+
+ public function __clone()
+ {
+ if ($this->emitter) {
+ $this->emitter = clone $this->emitter;
+ }
+ $this->transferOptions = clone $this->transferOptions;
+ $this->url = clone $this->url;
+ }
+
+ public function setUrl($url)
+ {
+ $this->url = $url instanceof Url ? $url : Url::fromString($url);
+ $this->updateHostHeaderFromUrl();
+ }
+
+ public function getUrl()
+ {
+ return (string) $this->url;
+ }
+
+ public function setQuery($query)
+ {
+ $this->url->setQuery($query);
+ }
+
+ public function getQuery()
+ {
+ return $this->url->getQuery();
+ }
+
+ public function setMethod($method)
+ {
+ $this->method = strtoupper($method);
+ }
+
+ public function getMethod()
+ {
+ return $this->method;
+ }
+
+ public function getScheme()
+ {
+ return $this->url->getScheme();
+ }
+
+ public function setScheme($scheme)
+ {
+ $this->url->setScheme($scheme);
+ }
+
+ public function getPort()
+ {
+ return $this->url->getPort();
+ }
+
+ public function setPort($port)
+ {
+ $this->url->setPort($port);
+ $this->updateHostHeaderFromUrl();
+ }
+
+ public function getHost()
+ {
+ return $this->url->getHost();
+ }
+
+ public function setHost($host)
+ {
+ $this->url->setHost($host);
+ $this->updateHostHeaderFromUrl();
+ }
+
+ public function getPath()
+ {
+ return '/' . ltrim($this->url->getPath(), '/');
+ }
+
+ public function setPath($path)
+ {
+ $this->url->setPath($path);
+ }
+
+ public function getResource()
+ {
+ $resource = $this->getPath();
+ if ($query = (string) $this->url->getQuery()) {
+ $resource .= '?' . $query;
+ }
+
+ return $resource;
+ }
+
+ public function getConfig()
+ {
+ return $this->transferOptions;
+ }
+
+ protected function handleOptions(array &$options)
+ {
+ parent::handleOptions($options);
+ // Use a custom emitter if one is specified, and remove it from
+ // options that are exposed through getConfig()
+ if (isset($options['emitter'])) {
+ $this->emitter = $options['emitter'];
+ unset($options['emitter']);
+ }
+ }
+
+ /**
+ * Adds a subscriber that ensures a request's body is prepared before
+ * sending.
+ */
+ private function addPrepareEvent()
+ {
+ static $subscriber;
+ if (!$subscriber) {
+ $subscriber = new Prepare();
+ }
+
+ $this->getEmitter()->attach($subscriber);
+ }
+
+ private function updateHostHeaderFromUrl()
+ {
+ $port = $this->url->getPort();
+ $scheme = $this->url->getScheme();
+ if ($host = $this->url->getHost()) {
+ if (($port == 80 && $scheme == 'http') ||
+ ($port == 443 && $scheme == 'https')
+ ) {
+ $this->setHeader('Host', $host);
+ } else {
+ $this->setHeader('Host', "{$host}:{$port}");
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php
new file mode 100644
index 0000000..f6a69d1
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/RequestInterface.php
@@ -0,0 +1,136 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Event\HasEmitterInterface;
+use GuzzleHttp\Query;
+
+/**
+ * Generic HTTP request interface
+ */
+interface RequestInterface extends MessageInterface, HasEmitterInterface
+{
+ /**
+ * Sets the request URL.
+ *
+ * The URL MUST be a string, or an object that implements the
+ * `__toString()` method.
+ *
+ * @param string $url Request URL.
+ *
+ * @throws \InvalidArgumentException If the URL is invalid.
+ */
+ public function setUrl($url);
+
+ /**
+ * Gets the request URL as a string.
+ *
+ * @return string Returns the URL as a string.
+ */
+ public function getUrl();
+
+ /**
+ * Get the resource part of the the request, including the path, query
+ * string, and fragment.
+ *
+ * @return string
+ */
+ public function getResource();
+
+ /**
+ * Get the collection of key value pairs that will be used as the query
+ * string in the request.
+ *
+ * @return Query
+ */
+ public function getQuery();
+
+ /**
+ * Set the query string used by the request
+ *
+ * @param array|Query $query Query to set
+ */
+ public function setQuery($query);
+
+ /**
+ * Get the HTTP method of the request.
+ *
+ * @return string
+ */
+ public function getMethod();
+
+ /**
+ * Set the HTTP method of the request.
+ *
+ * @param string $method HTTP method
+ */
+ public function setMethod($method);
+
+ /**
+ * Get the URI scheme of the request (http, https, etc.).
+ *
+ * @return string
+ */
+ public function getScheme();
+
+ /**
+ * Set the URI scheme of the request (http, https, etc.).
+ *
+ * @param string $scheme Scheme to set
+ */
+ public function setScheme($scheme);
+
+ /**
+ * Get the port scheme of the request (e.g., 80, 443, etc.).
+ *
+ * @return int
+ */
+ public function getPort();
+
+ /**
+ * Set the port of the request.
+ *
+ * Setting a port modifies the Host header of a request as necessary.
+ *
+ * @param int $port Port to set
+ */
+ public function setPort($port);
+
+ /**
+ * Get the host of the request.
+ *
+ * @return string
+ */
+ public function getHost();
+
+ /**
+ * Set the host of the request including an optional port.
+ *
+ * Including a port in the host argument will explicitly change the port of
+ * the request. If no port is found, the default port of the current
+ * request scheme will be utilized.
+ *
+ * @param string $host Host to set (e.g. www.yahoo.com, www.yahoo.com:80)
+ */
+ public function setHost($host);
+
+ /**
+ * Get the path of the request (e.g. '/', '/index.html').
+ *
+ * @return string
+ */
+ public function getPath();
+
+ /**
+ * Set the path of the request (e.g. '/', '/index.html').
+ *
+ * @param string|array $path Path to set or array of segments to implode
+ */
+ public function setPath($path);
+
+ /**
+ * Get the request's configuration options.
+ *
+ * @return \GuzzleHttp\Collection
+ */
+ public function getConfig();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Response.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Response.php
new file mode 100644
index 0000000..42e10e6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/Response.php
@@ -0,0 +1,208 @@
+<?php
+namespace GuzzleHttp\Message;
+
+use GuzzleHttp\Exception\ParseException;
+use GuzzleHttp\Exception\XmlParseException;
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Utils;
+
+/**
+ * Guzzle HTTP response object
+ */
+class Response extends AbstractMessage implements ResponseInterface
+{
+ /** @var array Mapping of status codes to reason phrases */
+ private static $statusTexts = [
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+ 102 => 'Processing',
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+ 207 => 'Multi-Status',
+ 208 => 'Already Reported',
+ 226 => 'IM Used',
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+ 308 => 'Permanent Redirect',
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity',
+ 423 => 'Locked',
+ 424 => 'Failed Dependency',
+ 425 => 'Reserved for WebDAV advanced collections expired proposal',
+ 426 => 'Upgrade required',
+ 428 => 'Precondition Required',
+ 429 => 'Too Many Requests',
+ 431 => 'Request Header Fields Too Large',
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ 506 => 'Variant Also Negotiates (Experimental)',
+ 507 => 'Insufficient Storage',
+ 508 => 'Loop Detected',
+ 510 => 'Not Extended',
+ 511 => 'Network Authentication Required',
+ ];
+
+ /** @var string The reason phrase of the response (human readable code) */
+ private $reasonPhrase;
+
+ /** @var string The status code of the response */
+ private $statusCode;
+
+ /** @var string The effective URL that returned this response */
+ private $effectiveUrl;
+
+ /**
+ * @param int|string $statusCode The response status code (e.g. 200)
+ * @param array $headers The response headers
+ * @param StreamInterface $body The body of the response
+ * @param array $options Response message options
+ * - reason_phrase: Set a custom reason phrase
+ * - protocol_version: Set a custom protocol version
+ */
+ public function __construct(
+ $statusCode,
+ array $headers = [],
+ StreamInterface $body = null,
+ array $options = []
+ ) {
+ $this->statusCode = (int) $statusCode;
+ $this->handleOptions($options);
+
+ // Assume a reason phrase if one was not applied as an option
+ if (!$this->reasonPhrase &&
+ isset(self::$statusTexts[$this->statusCode])
+ ) {
+ $this->reasonPhrase = self::$statusTexts[$this->statusCode];
+ }
+
+ if ($headers) {
+ $this->setHeaders($headers);
+ }
+
+ if ($body) {
+ $this->setBody($body);
+ }
+ }
+
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ public function setStatusCode($code)
+ {
+ return $this->statusCode = (int) $code;
+ }
+
+ public function getReasonPhrase()
+ {
+ return $this->reasonPhrase;
+ }
+
+ public function setReasonPhrase($phrase)
+ {
+ return $this->reasonPhrase = $phrase;
+ }
+
+ public function json(array $config = [])
+ {
+ try {
+ return Utils::jsonDecode(
+ (string) $this->getBody(),
+ isset($config['object']) ? !$config['object'] : true,
+ 512,
+ isset($config['big_int_strings']) ? JSON_BIGINT_AS_STRING : 0
+ );
+ } catch (\InvalidArgumentException $e) {
+ throw new ParseException(
+ $e->getMessage(),
+ $this
+ );
+ }
+ }
+
+ public function xml(array $config = [])
+ {
+ $disableEntities = libxml_disable_entity_loader(true);
+ $internalErrors = libxml_use_internal_errors(true);
+
+ try {
+ // Allow XML to be retrieved even if there is no response body
+ $xml = new \SimpleXMLElement(
+ (string) $this->getBody() ?: '<root />',
+ isset($config['libxml_options']) ? $config['libxml_options'] : LIBXML_NONET,
+ false,
+ isset($config['ns']) ? $config['ns'] : '',
+ isset($config['ns_is_prefix']) ? $config['ns_is_prefix'] : false
+ );
+ libxml_disable_entity_loader($disableEntities);
+ libxml_use_internal_errors($internalErrors);
+ } catch (\Exception $e) {
+ libxml_disable_entity_loader($disableEntities);
+ libxml_use_internal_errors($internalErrors);
+ throw new XmlParseException(
+ 'Unable to parse response body into XML: ' . $e->getMessage(),
+ $this,
+ $e,
+ (libxml_get_last_error()) ?: null
+ );
+ }
+
+ return $xml;
+ }
+
+ public function getEffectiveUrl()
+ {
+ return $this->effectiveUrl;
+ }
+
+ public function setEffectiveUrl($url)
+ {
+ $this->effectiveUrl = $url;
+ }
+
+ /**
+ * Accepts and modifies the options provided to the response in the
+ * constructor.
+ *
+ * @param array $options Options array passed by reference.
+ */
+ protected function handleOptions(array &$options = [])
+ {
+ parent::handleOptions($options);
+ if (isset($options['reason_phrase'])) {
+ $this->reasonPhrase = $options['reason_phrase'];
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php
new file mode 100644
index 0000000..c0ae9be
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Message/ResponseInterface.php
@@ -0,0 +1,111 @@
+<?php
+namespace GuzzleHttp\Message;
+
+/**
+ * Represents an HTTP response message.
+ */
+interface ResponseInterface extends MessageInterface
+{
+ /**
+ * Gets the response Status-Code.
+ *
+ * The Status-Code is a 3-digit integer result code of the server's attempt
+ * to understand and satisfy the request.
+ *
+ * @return int Status code.
+ */
+ public function getStatusCode();
+
+ /**
+ * Sets the status code of this response.
+ *
+ * @param int $code The 3-digit integer result code to set.
+ */
+ public function setStatusCode($code);
+
+ /**
+ * Gets the response Reason-Phrase, a short textual description of the
+ * Status-Code.
+ *
+ * Because a Reason-Phrase is not a required element in response
+ * Status-Line, the Reason-Phrase value MAY be null. Implementations MAY
+ * choose to return the default RFC 2616 recommended reason phrase for the
+ * response's Status-Code.
+ *
+ * @return string|null Reason phrase, or null if unknown.
+ */
+ public function getReasonPhrase();
+
+ /**
+ * Sets the Reason-Phrase of the response.
+ *
+ * If no Reason-Phrase is specified, implementations MAY choose to default
+ * to the RFC 2616 recommended reason phrase for the response's Status-Code.
+ *
+ * @param string $phrase The Reason-Phrase to set.
+ */
+ public function setReasonPhrase($phrase);
+
+ /**
+ * Get the effective URL that resulted in this response (e.g. the last
+ * redirect URL).
+ *
+ * @return string
+ */
+ public function getEffectiveUrl();
+
+ /**
+ * Set the effective URL that resulted in this response (e.g. the last
+ * redirect URL).
+ *
+ * @param string $url Effective URL
+ */
+ public function setEffectiveUrl($url);
+
+ /**
+ * Parse the JSON response body and return the JSON decoded data.
+ *
+ * @param array $config Associative array of configuration settings used
+ * to control how the JSON data is parsed. Concrete implementations MAY
+ * add further configuration settings as needed, but they MUST implement
+ * functionality for the following options:
+ *
+ * - object: Set to true to parse JSON objects as PHP objects rather
+ * than associative arrays. Defaults to false.
+ * - big_int_strings: When set to true, large integers are converted to
+ * strings rather than floats. Defaults to false.
+ *
+ * Implementations are free to add further configuration settings as
+ * needed.
+ *
+ * @return mixed Returns the JSON decoded data based on the provided
+ * parse settings.
+ * @throws \RuntimeException if the response body is not in JSON format
+ */
+ public function json(array $config = []);
+
+ /**
+ * Parse the XML response body and return a \SimpleXMLElement.
+ *
+ * In order to prevent XXE attacks, this method disables loading external
+ * entities. If you rely on external entities, then you must parse the
+ * XML response manually by accessing the response body directly.
+ *
+ * @param array $config Associative array of configuration settings used
+ * to control how the XML is parsed. Concrete implementations MAY add
+ * further configuration settings as needed, but they MUST implement
+ * functionality for the following options:
+ *
+ * - ns: Set to a string to represent the namespace prefix or URI
+ * - ns_is_prefix: Set to true to specify that the NS is a prefix rather
+ * than a URI (defaults to false).
+ * - libxml_options: Bitwise OR of the libxml option constants
+ * listed at http://php.net/manual/en/libxml.constants.php
+ * (defaults to LIBXML_NONET)
+ *
+ * @return \SimpleXMLElement
+ * @throws \RuntimeException if the response body is not in XML format
+ * @link http://websec.io/2012/08/27/Preventing-XXE-in-PHP.html
+ */
+ public function xml(array $config = []);
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Mimetypes.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Mimetypes.php
new file mode 100644
index 0000000..66ac63c
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Mimetypes.php
@@ -0,0 +1,963 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Provides mappings of file extensions to mimetypes
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
+ */
+class Mimetypes
+{
+ /** @var self */
+ protected static $instance;
+
+ /** @var array Mapping of extension to mimetype */
+ protected $mimetypes = array(
+ '3dml' => 'text/vnd.in3d.3dml',
+ '3g2' => 'video/3gpp2',
+ '3gp' => 'video/3gpp',
+ '7z' => 'application/x-7z-compressed',
+ 'aab' => 'application/x-authorware-bin',
+ 'aac' => 'audio/x-aac',
+ 'aam' => 'application/x-authorware-map',
+ 'aas' => 'application/x-authorware-seg',
+ 'abw' => 'application/x-abiword',
+ 'ac' => 'application/pkix-attr-cert',
+ 'acc' => 'application/vnd.americandynamics.acc',
+ 'ace' => 'application/x-ace-compressed',
+ 'acu' => 'application/vnd.acucobol',
+ 'acutc' => 'application/vnd.acucorp',
+ 'adp' => 'audio/adpcm',
+ 'aep' => 'application/vnd.audiograph',
+ 'afm' => 'application/x-font-type1',
+ 'afp' => 'application/vnd.ibm.modcap',
+ 'ahead' => 'application/vnd.ahead.space',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
+ 'ait' => 'application/vnd.dvb.ait',
+ 'ami' => 'application/vnd.amiga.ami',
+ 'apk' => 'application/vnd.android.package-archive',
+ 'application' => 'application/x-ms-application',
+ 'apr' => 'application/vnd.lotus-approach',
+ 'asa' => 'text/plain',
+ 'asax' => 'application/octet-stream',
+ 'asc' => 'application/pgp-signature',
+ 'ascx' => 'text/plain',
+ 'asf' => 'video/x-ms-asf',
+ 'ashx' => 'text/plain',
+ 'asm' => 'text/x-asm',
+ 'asmx' => 'text/plain',
+ 'aso' => 'application/vnd.accpac.simply.aso',
+ 'asp' => 'text/plain',
+ 'aspx' => 'text/plain',
+ 'asx' => 'video/x-ms-asf',
+ 'atc' => 'application/vnd.acucorp',
+ 'atom' => 'application/atom+xml',
+ 'atomcat' => 'application/atomcat+xml',
+ 'atomsvc' => 'application/atomsvc+xml',
+ 'atx' => 'application/vnd.antix.game-component',
+ 'au' => 'audio/basic',
+ 'avi' => 'video/x-msvideo',
+ 'aw' => 'application/applixware',
+ 'axd' => 'text/plain',
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
+ 'azw' => 'application/vnd.amazon.ebook',
+ 'bat' => 'application/x-msdownload',
+ 'bcpio' => 'application/x-bcpio',
+ 'bdf' => 'application/x-font-bdf',
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
+ 'bed' => 'application/vnd.realvnc.bed',
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
+ 'bin' => 'application/octet-stream',
+ 'bmi' => 'application/vnd.bmi',
+ 'bmp' => 'image/bmp',
+ 'book' => 'application/vnd.framemaker',
+ 'box' => 'application/vnd.previewsystems.box',
+ 'boz' => 'application/x-bzip2',
+ 'bpk' => 'application/octet-stream',
+ 'btif' => 'image/prs.btif',
+ 'bz' => 'application/x-bzip',
+ 'bz2' => 'application/x-bzip2',
+ 'c' => 'text/x-c',
+ 'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
+ 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
+ 'c4d' => 'application/vnd.clonk.c4group',
+ 'c4f' => 'application/vnd.clonk.c4group',
+ 'c4g' => 'application/vnd.clonk.c4group',
+ 'c4p' => 'application/vnd.clonk.c4group',
+ 'c4u' => 'application/vnd.clonk.c4group',
+ 'cab' => 'application/vnd.ms-cab-compressed',
+ 'car' => 'application/vnd.curl.car',
+ 'cat' => 'application/vnd.ms-pki.seccat',
+ 'cc' => 'text/x-c',
+ 'cct' => 'application/x-director',
+ 'ccxml' => 'application/ccxml+xml',
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
+ 'cdf' => 'application/x-netcdf',
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
+ 'cdmia' => 'application/cdmi-capability',
+ 'cdmic' => 'application/cdmi-container',
+ 'cdmid' => 'application/cdmi-domain',
+ 'cdmio' => 'application/cdmi-object',
+ 'cdmiq' => 'application/cdmi-queue',
+ 'cdx' => 'chemical/x-cdx',
+ 'cdxml' => 'application/vnd.chemdraw+xml',
+ 'cdy' => 'application/vnd.cinderella',
+ 'cer' => 'application/pkix-cert',
+ 'cfc' => 'application/x-coldfusion',
+ 'cfm' => 'application/x-coldfusion',
+ 'cgm' => 'image/cgm',
+ 'chat' => 'application/x-chat',
+ 'chm' => 'application/vnd.ms-htmlhelp',
+ 'chrt' => 'application/vnd.kde.kchart',
+ 'cif' => 'chemical/x-cif',
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+ 'cil' => 'application/vnd.ms-artgalry',
+ 'cla' => 'application/vnd.claymore',
+ 'class' => 'application/java-vm',
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
+ 'clkp' => 'application/vnd.crick.clicker.palette',
+ 'clkt' => 'application/vnd.crick.clicker.template',
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
+ 'clkx' => 'application/vnd.crick.clicker',
+ 'clp' => 'application/x-msclip',
+ 'cmc' => 'application/vnd.cosmocaller',
+ 'cmdf' => 'chemical/x-cmdf',
+ 'cml' => 'chemical/x-cml',
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
+ 'cmx' => 'image/x-cmx',
+ 'cod' => 'application/vnd.rim.cod',
+ 'com' => 'application/x-msdownload',
+ 'conf' => 'text/plain',
+ 'cpio' => 'application/x-cpio',
+ 'cpp' => 'text/x-c',
+ 'cpt' => 'application/mac-compactpro',
+ 'crd' => 'application/x-mscardfile',
+ 'crl' => 'application/pkix-crl',
+ 'crt' => 'application/x-x509-ca-cert',
+ 'cryptonote' => 'application/vnd.rig.cryptonote',
+ 'cs' => 'text/plain',
+ 'csh' => 'application/x-csh',
+ 'csml' => 'chemical/x-csml',
+ 'csp' => 'application/vnd.commonspace',
+ 'css' => 'text/css',
+ 'cst' => 'application/x-director',
+ 'csv' => 'text/csv',
+ 'cu' => 'application/cu-seeme',
+ 'curl' => 'text/vnd.curl',
+ 'cww' => 'application/prs.cww',
+ 'cxt' => 'application/x-director',
+ 'cxx' => 'text/x-c',
+ 'dae' => 'model/vnd.collada+xml',
+ 'daf' => 'application/vnd.mobius.daf',
+ 'dataless' => 'application/vnd.fdsn.seed',
+ 'davmount' => 'application/davmount+xml',
+ 'dcr' => 'application/x-director',
+ 'dcurl' => 'text/vnd.curl.dcurl',
+ 'dd2' => 'application/vnd.oma.dd2+xml',
+ 'ddd' => 'application/vnd.fujixerox.ddd',
+ 'deb' => 'application/x-debian-package',
+ 'def' => 'text/plain',
+ 'deploy' => 'application/octet-stream',
+ 'der' => 'application/x-x509-ca-cert',
+ 'dfac' => 'application/vnd.dreamfactory',
+ 'dic' => 'text/x-c',
+ 'dir' => 'application/x-director',
+ 'dis' => 'application/vnd.mobius.dis',
+ 'dist' => 'application/octet-stream',
+ 'distz' => 'application/octet-stream',
+ 'djv' => 'image/vnd.djvu',
+ 'djvu' => 'image/vnd.djvu',
+ 'dll' => 'application/x-msdownload',
+ 'dmg' => 'application/octet-stream',
+ 'dms' => 'application/octet-stream',
+ 'dna' => 'application/vnd.dna',
+ 'doc' => 'application/msword',
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dot' => 'application/msword',
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'dp' => 'application/vnd.osgi.dp',
+ 'dpg' => 'application/vnd.dpgraph',
+ 'dra' => 'audio/vnd.dra',
+ 'dsc' => 'text/prs.lines.tag',
+ 'dssc' => 'application/dssc+der',
+ 'dtb' => 'application/x-dtbook+xml',
+ 'dtd' => 'application/xml-dtd',
+ 'dts' => 'audio/vnd.dts',
+ 'dtshd' => 'audio/vnd.dts.hd',
+ 'dump' => 'application/octet-stream',
+ 'dvi' => 'application/x-dvi',
+ 'dwf' => 'model/vnd.dwf',
+ 'dwg' => 'image/vnd.dwg',
+ 'dxf' => 'image/vnd.dxf',
+ 'dxp' => 'application/vnd.spotfire.dxp',
+ 'dxr' => 'application/x-director',
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
+ 'ecma' => 'application/ecmascript',
+ 'edm' => 'application/vnd.novadigm.edm',
+ 'edx' => 'application/vnd.novadigm.edx',
+ 'efif' => 'application/vnd.picsel',
+ 'ei6' => 'application/vnd.pg.osasli',
+ 'elc' => 'application/octet-stream',
+ 'eml' => 'message/rfc822',
+ 'emma' => 'application/emma+xml',
+ 'eol' => 'audio/vnd.digital-winds',
+ 'eot' => 'application/vnd.ms-fontobject',
+ 'eps' => 'application/postscript',
+ 'epub' => 'application/epub+zip',
+ 'es3' => 'application/vnd.eszigno3+xml',
+ 'esf' => 'application/vnd.epson.esf',
+ 'et3' => 'application/vnd.eszigno3+xml',
+ 'etx' => 'text/x-setext',
+ 'exe' => 'application/x-msdownload',
+ 'exi' => 'application/exi',
+ 'ext' => 'application/vnd.novadigm.ext',
+ 'ez' => 'application/andrew-inset',
+ 'ez2' => 'application/vnd.ezpix-album',
+ 'ez3' => 'application/vnd.ezpix-package',
+ 'f' => 'text/x-fortran',
+ 'f4v' => 'video/x-f4v',
+ 'f77' => 'text/x-fortran',
+ 'f90' => 'text/x-fortran',
+ 'fbs' => 'image/vnd.fastbidsheet',
+ 'fcs' => 'application/vnd.isac.fcs',
+ 'fdf' => 'application/vnd.fdf',
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
+ 'fgd' => 'application/x-director',
+ 'fh' => 'image/x-freehand',
+ 'fh4' => 'image/x-freehand',
+ 'fh5' => 'image/x-freehand',
+ 'fh7' => 'image/x-freehand',
+ 'fhc' => 'image/x-freehand',
+ 'fig' => 'application/x-xfig',
+ 'fli' => 'video/x-fli',
+ 'flo' => 'application/vnd.micrografx.flo',
+ 'flv' => 'video/x-flv',
+ 'flw' => 'application/vnd.kde.kivio',
+ 'flx' => 'text/vnd.fmi.flexstor',
+ 'fly' => 'text/vnd.fly',
+ 'fm' => 'application/vnd.framemaker',
+ 'fnc' => 'application/vnd.frogans.fnc',
+ 'for' => 'text/x-fortran',
+ 'fpx' => 'image/vnd.fpx',
+ 'frame' => 'application/vnd.framemaker',
+ 'fsc' => 'application/vnd.fsc.weblaunch',
+ 'fst' => 'image/vnd.fst',
+ 'ftc' => 'application/vnd.fluxtime.clip',
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+ 'fvt' => 'video/vnd.fvt',
+ 'fxp' => 'application/vnd.adobe.fxp',
+ 'fxpl' => 'application/vnd.adobe.fxp',
+ 'fzs' => 'application/vnd.fuzzysheet',
+ 'g2w' => 'application/vnd.geoplan',
+ 'g3' => 'image/g3fax',
+ 'g3w' => 'application/vnd.geospace',
+ 'gac' => 'application/vnd.groove-account',
+ 'gdl' => 'model/vnd.gdl',
+ 'geo' => 'application/vnd.dynageo',
+ 'gex' => 'application/vnd.geometry-explorer',
+ 'ggb' => 'application/vnd.geogebra.file',
+ 'ggt' => 'application/vnd.geogebra.tool',
+ 'ghf' => 'application/vnd.groove-help',
+ 'gif' => 'image/gif',
+ 'gim' => 'application/vnd.groove-identity-message',
+ 'gmx' => 'application/vnd.gmx',
+ 'gnumeric' => 'application/x-gnumeric',
+ 'gph' => 'application/vnd.flographit',
+ 'gqf' => 'application/vnd.grafeq',
+ 'gqs' => 'application/vnd.grafeq',
+ 'gram' => 'application/srgs',
+ 'gre' => 'application/vnd.geometry-explorer',
+ 'grv' => 'application/vnd.groove-injector',
+ 'grxml' => 'application/srgs+xml',
+ 'gsf' => 'application/x-font-ghostscript',
+ 'gtar' => 'application/x-gtar',
+ 'gtm' => 'application/vnd.groove-tool-message',
+ 'gtw' => 'model/vnd.gtw',
+ 'gv' => 'text/vnd.graphviz',
+ 'gxt' => 'application/vnd.geonext',
+ 'h' => 'text/x-c',
+ 'h261' => 'video/h261',
+ 'h263' => 'video/h263',
+ 'h264' => 'video/h264',
+ 'hal' => 'application/vnd.hal+xml',
+ 'hbci' => 'application/vnd.hbci',
+ 'hdf' => 'application/x-hdf',
+ 'hh' => 'text/x-c',
+ 'hlp' => 'application/winhlp',
+ 'hpgl' => 'application/vnd.hp-hpgl',
+ 'hpid' => 'application/vnd.hp-hpid',
+ 'hps' => 'application/vnd.hp-hps',
+ 'hqx' => 'application/mac-binhex40',
+ 'hta' => 'application/octet-stream',
+ 'htc' => 'text/html',
+ 'htke' => 'application/vnd.kenameaapp',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
+ 'hvs' => 'application/vnd.yamaha.hv-script',
+ 'i2g' => 'application/vnd.intergeo',
+ 'icc' => 'application/vnd.iccprofile',
+ 'ice' => 'x-conference/x-cooltalk',
+ 'icm' => 'application/vnd.iccprofile',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ief' => 'image/ief',
+ 'ifb' => 'text/calendar',
+ 'ifm' => 'application/vnd.shana.informed.formdata',
+ 'iges' => 'model/iges',
+ 'igl' => 'application/vnd.igloader',
+ 'igm' => 'application/vnd.insors.igm',
+ 'igs' => 'model/iges',
+ 'igx' => 'application/vnd.micrografx.igx',
+ 'iif' => 'application/vnd.shana.informed.interchange',
+ 'imp' => 'application/vnd.accpac.simply.imp',
+ 'ims' => 'application/vnd.ms-ims',
+ 'in' => 'text/plain',
+ 'ini' => 'text/plain',
+ 'ipfix' => 'application/ipfix',
+ 'ipk' => 'application/vnd.shana.informed.package',
+ 'irm' => 'application/vnd.ibm.rights-management',
+ 'irp' => 'application/vnd.irepository.package+xml',
+ 'iso' => 'application/octet-stream',
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
+ 'ivp' => 'application/vnd.immervision-ivp',
+ 'ivu' => 'application/vnd.immervision-ivu',
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
+ 'jam' => 'application/vnd.jam',
+ 'jar' => 'application/java-archive',
+ 'java' => 'text/x-java-source',
+ 'jisp' => 'application/vnd.jisp',
+ 'jlt' => 'application/vnd.hp-jlyt',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'joda' => 'application/vnd.joost.joda-archive',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'jpgm' => 'video/jpm',
+ 'jpgv' => 'video/jpeg',
+ 'jpm' => 'video/jpm',
+ 'js' => 'text/javascript',
+ 'json' => 'application/json',
+ 'kar' => 'audio/midi',
+ 'karbon' => 'application/vnd.kde.karbon',
+ 'kfo' => 'application/vnd.kde.kformula',
+ 'kia' => 'application/vnd.kidspiration',
+ 'kml' => 'application/vnd.google-earth.kml+xml',
+ 'kmz' => 'application/vnd.google-earth.kmz',
+ 'kne' => 'application/vnd.kinar',
+ 'knp' => 'application/vnd.kinar',
+ 'kon' => 'application/vnd.kde.kontour',
+ 'kpr' => 'application/vnd.kde.kpresenter',
+ 'kpt' => 'application/vnd.kde.kpresenter',
+ 'ksp' => 'application/vnd.kde.kspread',
+ 'ktr' => 'application/vnd.kahootz',
+ 'ktx' => 'image/ktx',
+ 'ktz' => 'application/vnd.kahootz',
+ 'kwd' => 'application/vnd.kde.kword',
+ 'kwt' => 'application/vnd.kde.kword',
+ 'lasxml' => 'application/vnd.las.las+xml',
+ 'latex' => 'application/x-latex',
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+ 'les' => 'application/vnd.hhe.lesson-player',
+ 'lha' => 'application/octet-stream',
+ 'link66' => 'application/vnd.route66.link66+xml',
+ 'list' => 'text/plain',
+ 'list3820' => 'application/vnd.ibm.modcap',
+ 'listafp' => 'application/vnd.ibm.modcap',
+ 'log' => 'text/plain',
+ 'lostxml' => 'application/lost+xml',
+ 'lrf' => 'application/octet-stream',
+ 'lrm' => 'application/vnd.ms-lrm',
+ 'ltf' => 'application/vnd.frogans.ltf',
+ 'lvp' => 'audio/vnd.lucent.voice',
+ 'lwp' => 'application/vnd.lotus-wordpro',
+ 'lzh' => 'application/octet-stream',
+ 'm13' => 'application/x-msmediaview',
+ 'm14' => 'application/x-msmediaview',
+ 'm1v' => 'video/mpeg',
+ 'm21' => 'application/mp21',
+ 'm2a' => 'audio/mpeg',
+ 'm2v' => 'video/mpeg',
+ 'm3a' => 'audio/mpeg',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm3u8' => 'application/vnd.apple.mpegurl',
+ 'm4a' => 'audio/mp4',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'm4v' => 'video/mp4',
+ 'ma' => 'application/mathematica',
+ 'mads' => 'application/mads+xml',
+ 'mag' => 'application/vnd.ecowin.chart',
+ 'maker' => 'application/vnd.framemaker',
+ 'man' => 'text/troff',
+ 'mathml' => 'application/mathml+xml',
+ 'mb' => 'application/mathematica',
+ 'mbk' => 'application/vnd.mobius.mbk',
+ 'mbox' => 'application/mbox',
+ 'mc1' => 'application/vnd.medcalcdata',
+ 'mcd' => 'application/vnd.mcd',
+ 'mcurl' => 'text/vnd.curl.mcurl',
+ 'mdb' => 'application/x-msaccess',
+ 'mdi' => 'image/vnd.ms-modi',
+ 'me' => 'text/troff',
+ 'mesh' => 'model/mesh',
+ 'meta4' => 'application/metalink4+xml',
+ 'mets' => 'application/mets+xml',
+ 'mfm' => 'application/vnd.mfmp',
+ 'mgp' => 'application/vnd.osgeo.mapguide.package',
+ 'mgz' => 'application/vnd.proteus.magazine',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mif' => 'application/vnd.mif',
+ 'mime' => 'message/rfc822',
+ 'mj2' => 'video/mj2',
+ 'mjp2' => 'video/mj2',
+ 'mlp' => 'application/vnd.dolby.mlp',
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+ 'mmf' => 'application/vnd.smaf',
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+ 'mny' => 'application/x-msmoney',
+ 'mobi' => 'application/x-mobipocket-ebook',
+ 'mods' => 'application/mods+xml',
+ 'mov' => 'video/quicktime',
+ 'movie' => 'video/x-sgi-movie',
+ 'mp2' => 'audio/mpeg',
+ 'mp21' => 'application/mp21',
+ 'mp2a' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mp4a' => 'audio/mp4',
+ 'mp4s' => 'application/mp4',
+ 'mp4v' => 'video/mp4',
+ 'mpc' => 'application/vnd.mophun.certificate',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpg4' => 'video/mp4',
+ 'mpga' => 'audio/mpeg',
+ 'mpkg' => 'application/vnd.apple.installer+xml',
+ 'mpm' => 'application/vnd.blueice.multipass',
+ 'mpn' => 'application/vnd.mophun.application',
+ 'mpp' => 'application/vnd.ms-project',
+ 'mpt' => 'application/vnd.ms-project',
+ 'mpy' => 'application/vnd.ibm.minipay',
+ 'mqy' => 'application/vnd.mobius.mqy',
+ 'mrc' => 'application/marc',
+ 'mrcx' => 'application/marcxml+xml',
+ 'ms' => 'text/troff',
+ 'mscml' => 'application/mediaservercontrol+xml',
+ 'mseed' => 'application/vnd.fdsn.mseed',
+ 'mseq' => 'application/vnd.mseq',
+ 'msf' => 'application/vnd.epson.msf',
+ 'msh' => 'model/mesh',
+ 'msi' => 'application/x-msdownload',
+ 'msl' => 'application/vnd.mobius.msl',
+ 'msty' => 'application/vnd.muvee.style',
+ 'mts' => 'model/vnd.mts',
+ 'mus' => 'application/vnd.musician',
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
+ 'mvb' => 'application/x-msmediaview',
+ 'mwf' => 'application/vnd.mfer',
+ 'mxf' => 'application/mxf',
+ 'mxl' => 'application/vnd.recordare.musicxml',
+ 'mxml' => 'application/xv+xml',
+ 'mxs' => 'application/vnd.triscape.mxs',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+ 'n3' => 'text/n3',
+ 'nb' => 'application/mathematica',
+ 'nbp' => 'application/vnd.wolfram.player',
+ 'nc' => 'application/x-netcdf',
+ 'ncx' => 'application/x-dtbncx+xml',
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
+ 'nml' => 'application/vnd.enliven',
+ 'nnd' => 'application/vnd.noblenet-directory',
+ 'nns' => 'application/vnd.noblenet-sealer',
+ 'nnw' => 'application/vnd.noblenet-web',
+ 'npx' => 'image/vnd.net-fpx',
+ 'nsf' => 'application/vnd.lotus-notes',
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
+ 'oas' => 'application/vnd.fujitsu.oasys',
+ 'obd' => 'application/x-msbinder',
+ 'oda' => 'application/oda',
+ 'odb' => 'application/vnd.oasis.opendocument.database',
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
+ 'odi' => 'application/vnd.oasis.opendocument.image',
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'oga' => 'audio/ogg',
+ 'ogg' => 'audio/ogg',
+ 'ogv' => 'video/ogg',
+ 'ogx' => 'application/ogg',
+ 'onepkg' => 'application/onenote',
+ 'onetmp' => 'application/onenote',
+ 'onetoc' => 'application/onenote',
+ 'onetoc2' => 'application/onenote',
+ 'opf' => 'application/oebps-package+xml',
+ 'oprc' => 'application/vnd.palm',
+ 'org' => 'application/vnd.lotus-organizer',
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
+ 'otf' => 'application/x-font-otf',
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
+ 'oxt' => 'application/vnd.openofficeorg.extension',
+ 'p' => 'text/x-pascal',
+ 'p10' => 'application/pkcs10',
+ 'p12' => 'application/x-pkcs12',
+ 'p7b' => 'application/x-pkcs7-certificates',
+ 'p7c' => 'application/pkcs7-mime',
+ 'p7m' => 'application/pkcs7-mime',
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'p7s' => 'application/pkcs7-signature',
+ 'p8' => 'application/pkcs8',
+ 'pas' => 'text/x-pascal',
+ 'paw' => 'application/vnd.pawaafile',
+ 'pbd' => 'application/vnd.powerbuilder6',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pcf' => 'application/x-font-pcf',
+ 'pcl' => 'application/vnd.hp-pcl',
+ 'pclxl' => 'application/vnd.hp-pclxl',
+ 'pct' => 'image/x-pict',
+ 'pcurl' => 'application/vnd.curl.pcurl',
+ 'pcx' => 'image/x-pcx',
+ 'pdb' => 'application/vnd.palm',
+ 'pdf' => 'application/pdf',
+ 'pfa' => 'application/x-font-type1',
+ 'pfb' => 'application/x-font-type1',
+ 'pfm' => 'application/x-font-type1',
+ 'pfr' => 'application/font-tdpfr',
+ 'pfx' => 'application/x-pkcs12',
+ 'pgm' => 'image/x-portable-graymap',
+ 'pgn' => 'application/x-chess-pgn',
+ 'pgp' => 'application/pgp-encrypted',
+ 'php' => 'text/x-php',
+ 'phps' => 'application/x-httpd-phps',
+ 'pic' => 'image/x-pict',
+ 'pkg' => 'application/octet-stream',
+ 'pki' => 'application/pkixcmp',
+ 'pkipath' => 'application/pkix-pkipath',
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
+ 'plc' => 'application/vnd.mobius.plc',
+ 'plf' => 'application/vnd.pocketlearn',
+ 'pls' => 'application/pls+xml',
+ 'pml' => 'application/vnd.ctc-posml',
+ 'png' => 'image/png',
+ 'pnm' => 'image/x-portable-anymap',
+ 'portpkg' => 'application/vnd.macports.portpkg',
+ 'pot' => 'application/vnd.ms-powerpoint',
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
+ 'ppd' => 'application/vnd.cups-ppd',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'pps' => 'application/vnd.ms-powerpoint',
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'pqa' => 'application/vnd.palm',
+ 'prc' => 'application/x-mobipocket-ebook',
+ 'pre' => 'application/vnd.lotus-freelance',
+ 'prf' => 'application/pics-rules',
+ 'ps' => 'application/postscript',
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'psf' => 'application/x-font-linux-psf',
+ 'pskcxml' => 'application/pskc+xml',
+ 'ptid' => 'application/vnd.pvi.ptid1',
+ 'pub' => 'application/x-mspublisher',
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
+ 'pwn' => 'application/vnd.3m.post-it-notes',
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
+ 'qam' => 'application/vnd.epson.quickanime',
+ 'qbo' => 'application/vnd.intu.qbo',
+ 'qfx' => 'application/vnd.intu.qfx',
+ 'qps' => 'application/vnd.publishare-delta-tree',
+ 'qt' => 'video/quicktime',
+ 'qwd' => 'application/vnd.quark.quarkxpress',
+ 'qwt' => 'application/vnd.quark.quarkxpress',
+ 'qxb' => 'application/vnd.quark.quarkxpress',
+ 'qxd' => 'application/vnd.quark.quarkxpress',
+ 'qxl' => 'application/vnd.quark.quarkxpress',
+ 'qxt' => 'application/vnd.quark.quarkxpress',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rar' => 'application/x-rar-compressed',
+ 'ras' => 'image/x-cmu-raster',
+ 'rb' => 'text/plain',
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
+ 'rdf' => 'application/rdf+xml',
+ 'rdz' => 'application/vnd.data-vision.rdz',
+ 'rep' => 'application/vnd.businessobjects',
+ 'res' => 'application/x-dtbresource+xml',
+ 'resx' => 'text/xml',
+ 'rgb' => 'image/x-rgb',
+ 'rif' => 'application/reginfo+xml',
+ 'rip' => 'audio/vnd.rip',
+ 'rl' => 'application/resource-lists+xml',
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+ 'rld' => 'application/resource-lists-diff+xml',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'rmi' => 'audio/midi',
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
+ 'rnc' => 'application/relax-ng-compact-syntax',
+ 'roff' => 'text/troff',
+ 'rp9' => 'application/vnd.cloanto.rp9',
+ 'rpss' => 'application/vnd.nokia.radio-presets',
+ 'rpst' => 'application/vnd.nokia.radio-preset',
+ 'rq' => 'application/sparql-query',
+ 'rs' => 'application/rls-services+xml',
+ 'rsd' => 'application/rsd+xml',
+ 'rss' => 'application/rss+xml',
+ 'rtf' => 'application/rtf',
+ 'rtx' => 'text/richtext',
+ 's' => 'text/x-asm',
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
+ 'sbml' => 'application/sbml+xml',
+ 'sc' => 'application/vnd.ibm.secure-container',
+ 'scd' => 'application/x-msschedule',
+ 'scm' => 'application/vnd.lotus-screencam',
+ 'scq' => 'application/scvp-cv-request',
+ 'scs' => 'application/scvp-cv-response',
+ 'scurl' => 'text/vnd.curl.scurl',
+ 'sda' => 'application/vnd.stardivision.draw',
+ 'sdc' => 'application/vnd.stardivision.calc',
+ 'sdd' => 'application/vnd.stardivision.impress',
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
+ 'sdp' => 'application/sdp',
+ 'sdw' => 'application/vnd.stardivision.writer',
+ 'see' => 'application/vnd.seemail',
+ 'seed' => 'application/vnd.fdsn.seed',
+ 'sema' => 'application/vnd.sema',
+ 'semd' => 'application/vnd.semd',
+ 'semf' => 'application/vnd.semf',
+ 'ser' => 'application/java-serialized-object',
+ 'setpay' => 'application/set-payment-initiation',
+ 'setreg' => 'application/set-registration-initiation',
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
+ 'sfs' => 'application/vnd.spotfire.sfs',
+ 'sgl' => 'application/vnd.stardivision.writer-global',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'shf' => 'application/shf+xml',
+ 'sig' => 'application/pgp-signature',
+ 'silo' => 'model/mesh',
+ 'sis' => 'application/vnd.symbian.install',
+ 'sisx' => 'application/vnd.symbian.install',
+ 'sit' => 'application/x-stuffit',
+ 'sitx' => 'application/x-stuffitx',
+ 'skd' => 'application/vnd.koan',
+ 'skm' => 'application/vnd.koan',
+ 'skp' => 'application/vnd.koan',
+ 'skt' => 'application/vnd.koan',
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+ 'slt' => 'application/vnd.epson.salt',
+ 'sm' => 'application/vnd.stepmania.stepchart',
+ 'smf' => 'application/vnd.stardivision.math',
+ 'smi' => 'application/smil+xml',
+ 'smil' => 'application/smil+xml',
+ 'snd' => 'audio/basic',
+ 'snf' => 'application/x-font-snf',
+ 'so' => 'application/octet-stream',
+ 'spc' => 'application/x-pkcs7-certificates',
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
+ 'spl' => 'application/x-futuresplash',
+ 'spot' => 'text/vnd.in3d.spot',
+ 'spp' => 'application/scvp-vp-response',
+ 'spq' => 'application/scvp-vp-request',
+ 'spx' => 'audio/ogg',
+ 'src' => 'application/x-wais-source',
+ 'sru' => 'application/sru+xml',
+ 'srx' => 'application/sparql-results+xml',
+ 'sse' => 'application/vnd.kodak-descriptor',
+ 'ssf' => 'application/vnd.epson.ssf',
+ 'ssml' => 'application/ssml+xml',
+ 'st' => 'application/vnd.sailingtracker.track',
+ 'stc' => 'application/vnd.sun.xml.calc.template',
+ 'std' => 'application/vnd.sun.xml.draw.template',
+ 'stf' => 'application/vnd.wt.stf',
+ 'sti' => 'application/vnd.sun.xml.impress.template',
+ 'stk' => 'application/hyperstudio',
+ 'stl' => 'application/vnd.ms-pki.stl',
+ 'str' => 'application/vnd.pg.format',
+ 'stw' => 'application/vnd.sun.xml.writer.template',
+ 'sub' => 'image/vnd.dvb.subtitle',
+ 'sus' => 'application/vnd.sus-calendar',
+ 'susp' => 'application/vnd.sus-calendar',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'svc' => 'application/vnd.dvb.service',
+ 'svd' => 'application/vnd.svd',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+ 'swa' => 'application/x-director',
+ 'swf' => 'application/x-shockwave-flash',
+ 'swi' => 'application/vnd.aristanetworks.swi',
+ 'sxc' => 'application/vnd.sun.xml.calc',
+ 'sxd' => 'application/vnd.sun.xml.draw',
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
+ 'sxi' => 'application/vnd.sun.xml.impress',
+ 'sxm' => 'application/vnd.sun.xml.math',
+ 'sxw' => 'application/vnd.sun.xml.writer',
+ 't' => 'text/troff',
+ 'tao' => 'application/vnd.tao.intent-module-archive',
+ 'tar' => 'application/x-tar',
+ 'tcap' => 'application/vnd.3gpp2.tcap',
+ 'tcl' => 'application/x-tcl',
+ 'teacher' => 'application/vnd.smart.teacher',
+ 'tei' => 'application/tei+xml',
+ 'teicorpus' => 'application/tei+xml',
+ 'tex' => 'application/x-tex',
+ 'texi' => 'application/x-texinfo',
+ 'texinfo' => 'application/x-texinfo',
+ 'text' => 'text/plain',
+ 'tfi' => 'application/thraud+xml',
+ 'tfm' => 'application/x-tex-tfm',
+ 'thmx' => 'application/vnd.ms-officetheme',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tmo' => 'application/vnd.tmobile-livetv',
+ 'torrent' => 'application/x-bittorrent',
+ 'tpl' => 'application/vnd.groove-tool-template',
+ 'tpt' => 'application/vnd.trid.tpt',
+ 'tr' => 'text/troff',
+ 'tra' => 'application/vnd.trueapp',
+ 'trm' => 'application/x-msterminal',
+ 'tsd' => 'application/timestamped-data',
+ 'tsv' => 'text/tab-separated-values',
+ 'ttc' => 'application/x-font-ttf',
+ 'ttf' => 'application/x-font-ttf',
+ 'ttl' => 'text/turtle',
+ 'twd' => 'application/vnd.simtech-mindmapper',
+ 'twds' => 'application/vnd.simtech-mindmapper',
+ 'txd' => 'application/vnd.genomatix.tuxedo',
+ 'txf' => 'application/vnd.mobius.txf',
+ 'txt' => 'text/plain',
+ 'u32' => 'application/x-authorware-bin',
+ 'udeb' => 'application/x-debian-package',
+ 'ufd' => 'application/vnd.ufdl',
+ 'ufdl' => 'application/vnd.ufdl',
+ 'umj' => 'application/vnd.umajin',
+ 'unityweb' => 'application/vnd.unity',
+ 'uoml' => 'application/vnd.uoml+xml',
+ 'uri' => 'text/uri-list',
+ 'uris' => 'text/uri-list',
+ 'urls' => 'text/uri-list',
+ 'ustar' => 'application/x-ustar',
+ 'utz' => 'application/vnd.uiq.theme',
+ 'uu' => 'text/x-uuencode',
+ 'uva' => 'audio/vnd.dece.audio',
+ 'uvd' => 'application/vnd.dece.data',
+ 'uvf' => 'application/vnd.dece.data',
+ 'uvg' => 'image/vnd.dece.graphic',
+ 'uvh' => 'video/vnd.dece.hd',
+ 'uvi' => 'image/vnd.dece.graphic',
+ 'uvm' => 'video/vnd.dece.mobile',
+ 'uvp' => 'video/vnd.dece.pd',
+ 'uvs' => 'video/vnd.dece.sd',
+ 'uvt' => 'application/vnd.dece.ttml+xml',
+ 'uvu' => 'video/vnd.uvvu.mp4',
+ 'uvv' => 'video/vnd.dece.video',
+ 'uvva' => 'audio/vnd.dece.audio',
+ 'uvvd' => 'application/vnd.dece.data',
+ 'uvvf' => 'application/vnd.dece.data',
+ 'uvvg' => 'image/vnd.dece.graphic',
+ 'uvvh' => 'video/vnd.dece.hd',
+ 'uvvi' => 'image/vnd.dece.graphic',
+ 'uvvm' => 'video/vnd.dece.mobile',
+ 'uvvp' => 'video/vnd.dece.pd',
+ 'uvvs' => 'video/vnd.dece.sd',
+ 'uvvt' => 'application/vnd.dece.ttml+xml',
+ 'uvvu' => 'video/vnd.uvvu.mp4',
+ 'uvvv' => 'video/vnd.dece.video',
+ 'uvvx' => 'application/vnd.dece.unspecified',
+ 'uvx' => 'application/vnd.dece.unspecified',
+ 'vcd' => 'application/x-cdlink',
+ 'vcf' => 'text/x-vcard',
+ 'vcg' => 'application/vnd.groove-vcard',
+ 'vcs' => 'text/x-vcalendar',
+ 'vcx' => 'application/vnd.vcx',
+ 'vis' => 'application/vnd.visionary',
+ 'viv' => 'video/vnd.vivo',
+ 'vor' => 'application/vnd.stardivision.writer',
+ 'vox' => 'application/x-authorware-bin',
+ 'vrml' => 'model/vrml',
+ 'vsd' => 'application/vnd.visio',
+ 'vsf' => 'application/vnd.vsf',
+ 'vss' => 'application/vnd.visio',
+ 'vst' => 'application/vnd.visio',
+ 'vsw' => 'application/vnd.visio',
+ 'vtu' => 'model/vnd.vtu',
+ 'vxml' => 'application/voicexml+xml',
+ 'w3d' => 'application/x-director',
+ 'wad' => 'application/x-doom',
+ 'wav' => 'audio/x-wav',
+ 'wax' => 'audio/x-ms-wax',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wcm' => 'application/vnd.ms-works',
+ 'wdb' => 'application/vnd.ms-works',
+ 'weba' => 'audio/webm',
+ 'webm' => 'video/webm',
+ 'webp' => 'image/webp',
+ 'wg' => 'application/vnd.pmi.widget',
+ 'wgt' => 'application/widget',
+ 'wks' => 'application/vnd.ms-works',
+ 'wm' => 'video/x-ms-wm',
+ 'wma' => 'audio/x-ms-wma',
+ 'wmd' => 'application/x-ms-wmd',
+ 'wmf' => 'application/x-msmetafile',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wmx' => 'video/x-ms-wmx',
+ 'wmz' => 'application/x-ms-wmz',
+ 'woff' => 'application/x-font-woff',
+ 'wpd' => 'application/vnd.wordperfect',
+ 'wpl' => 'application/vnd.ms-wpl',
+ 'wps' => 'application/vnd.ms-works',
+ 'wqd' => 'application/vnd.wqd',
+ 'wri' => 'application/x-mswrite',
+ 'wrl' => 'model/vrml',
+ 'wsdl' => 'application/wsdl+xml',
+ 'wspolicy' => 'application/wspolicy+xml',
+ 'wtb' => 'application/vnd.webturbo',
+ 'wvx' => 'video/x-ms-wvx',
+ 'x32' => 'application/x-authorware-bin',
+ 'x3d' => 'application/vnd.hzn-3d-crossword',
+ 'xap' => 'application/x-silverlight-app',
+ 'xar' => 'application/vnd.xara',
+ 'xbap' => 'application/x-ms-xbap',
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+ 'xbm' => 'image/x-xbitmap',
+ 'xdf' => 'application/xcap-diff+xml',
+ 'xdm' => 'application/vnd.syncml.dm+xml',
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
+ 'xdssc' => 'application/dssc+xml',
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
+ 'xenc' => 'application/xenc+xml',
+ 'xer' => 'application/patch-ops-error+xml',
+ 'xfdf' => 'application/vnd.adobe.xfdf',
+ 'xfdl' => 'application/vnd.xfdl',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xhvml' => 'application/xv+xml',
+ 'xif' => 'image/vnd.xiff',
+ 'xla' => 'application/vnd.ms-excel',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
+ 'xlc' => 'application/vnd.ms-excel',
+ 'xlm' => 'application/vnd.ms-excel',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xlt' => 'application/vnd.ms-excel',
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'xlw' => 'application/vnd.ms-excel',
+ 'xml' => 'application/xml',
+ 'xo' => 'application/vnd.olpc-sugar',
+ 'xop' => 'application/xop+xml',
+ 'xpi' => 'application/x-xpinstall',
+ 'xpm' => 'image/x-xpixmap',
+ 'xpr' => 'application/vnd.is-xpr',
+ 'xps' => 'application/vnd.ms-xpsdocument',
+ 'xpw' => 'application/vnd.intercon.formnet',
+ 'xpx' => 'application/vnd.intercon.formnet',
+ 'xsl' => 'application/xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xsm' => 'application/vnd.syncml+xml',
+ 'xspf' => 'application/xspf+xml',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ 'xvm' => 'application/xv+xml',
+ 'xvml' => 'application/xv+xml',
+ 'xwd' => 'image/x-xwindowdump',
+ 'xyz' => 'chemical/x-xyz',
+ 'yaml' => 'text/yaml',
+ 'yang' => 'application/yang',
+ 'yin' => 'application/yin+xml',
+ 'yml' => 'text/yaml',
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
+ 'zip' => 'application/zip',
+ 'zir' => 'application/vnd.zul',
+ 'zirz' => 'application/vnd.zul',
+ 'zmm' => 'application/vnd.handheld-entertainment+xml'
+ );
+
+ /**
+ * Get a singleton instance of the class
+ *
+ * @return self
+ * @codeCoverageIgnore
+ */
+ public static function getInstance()
+ {
+ if (!self::$instance) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Get a mimetype value from a file extension
+ *
+ * @param string $extension File extension
+ *
+ * @return string|null
+ *
+ */
+ public function fromExtension($extension)
+ {
+ $extension = strtolower($extension);
+
+ return isset($this->mimetypes[$extension])
+ ? $this->mimetypes[$extension]
+ : null;
+ }
+
+ /**
+ * Get a mimetype from a filename
+ *
+ * @param string $filename Filename to generate a mimetype from
+ *
+ * @return string|null
+ */
+ public function fromFilename($filename)
+ {
+ return $this->fromExtension(pathinfo($filename, PATHINFO_EXTENSION));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Pool.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Pool.php
new file mode 100644
index 0000000..7b9d83a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Pool.php
@@ -0,0 +1,333 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Future\FutureInterface;
+use GuzzleHttp\Event\ListenerAttacherTrait;
+use GuzzleHttp\Event\EndEvent;
+use React\Promise\Deferred;
+use React\Promise\FulfilledPromise;
+use React\Promise\PromiseInterface;
+use React\Promise\RejectedPromise;
+
+/**
+ * Sends and iterator of requests concurrently using a capped pool size.
+ *
+ * The Pool object implements FutureInterface, meaning it can be used later
+ * when necessary, the requests provided to the pool can be cancelled, and
+ * you can check the state of the pool to know if it has been dereferenced
+ * (sent) or has been cancelled.
+ *
+ * When sending the pool, keep in mind that no results are returned: callers
+ * are expected to handle results asynchronously using Guzzle's event system.
+ * When requests complete, more are added to the pool to ensure that the
+ * requested pool size is always filled as much as possible.
+ *
+ * IMPORTANT: Do not provide a pool size greater that what the utilized
+ * underlying RingPHP handler can support. This will result is extremely poor
+ * performance.
+ */
+class Pool implements FutureInterface
+{
+ use ListenerAttacherTrait;
+
+ /** @var \GuzzleHttp\ClientInterface */
+ private $client;
+
+ /** @var \Iterator Yields requests */
+ private $iter;
+
+ /** @var Deferred */
+ private $deferred;
+
+ /** @var PromiseInterface */
+ private $promise;
+
+ private $waitQueue = [];
+ private $eventListeners = [];
+ private $poolSize;
+ private $isRealized = false;
+
+ /**
+ * The option values for 'before', 'complete', 'error' and 'end' can be a
+ * callable, an associative array containing event data, or an array of
+ * event data arrays. Event data arrays contain the following keys:
+ *
+ * - fn: callable to invoke that receives the event
+ * - priority: Optional event priority (defaults to 0)
+ * - once: Set to true so that the event is removed after it is triggered
+ *
+ * @param ClientInterface $client Client used to send the requests.
+ * @param array|\Iterator $requests Requests to send in parallel
+ * @param array $options Associative array of options
+ * - pool_size: (callable|int) Maximum number of requests to send
+ * concurrently, or a callback that receives
+ * the current queue size and returns the
+ * number of new requests to send
+ * - before: (callable|array) Receives a BeforeEvent
+ * - complete: (callable|array) Receives a CompleteEvent
+ * - error: (callable|array) Receives a ErrorEvent
+ * - end: (callable|array) Receives an EndEvent
+ */
+ public function __construct(
+ ClientInterface $client,
+ $requests,
+ array $options = []
+ ) {
+ $this->client = $client;
+ $this->iter = $this->coerceIterable($requests);
+ $this->deferred = new Deferred();
+ $this->promise = $this->deferred->promise();
+ $this->poolSize = isset($options['pool_size'])
+ ? $options['pool_size'] : 25;
+ $this->eventListeners = $this->prepareListeners(
+ $options,
+ ['before', 'complete', 'error', 'end']
+ );
+ }
+
+ /**
+ * Sends multiple requests in parallel and returns an array of responses
+ * and exceptions that uses the same ordering as the provided requests.
+ *
+ * IMPORTANT: This method keeps every request and response in memory, and
+ * as such, is NOT recommended when sending a large number or an
+ * indeterminate number of requests concurrently.
+ *
+ * @param ClientInterface $client Client used to send the requests
+ * @param array|\Iterator $requests Requests to send in parallel
+ * @param array $options Passes through the options available in
+ * {@see GuzzleHttp\Pool::__construct}
+ *
+ * @return BatchResults Returns a container for the results.
+ * @throws \InvalidArgumentException if the event format is incorrect.
+ */
+ public static function batch(
+ ClientInterface $client,
+ $requests,
+ array $options = []
+ ) {
+ $hash = new \SplObjectStorage();
+ foreach ($requests as $request) {
+ $hash->attach($request);
+ }
+
+ // In addition to the normally run events when requests complete, add
+ // and event to continuously track the results of transfers in the hash.
+ (new self($client, $requests, RequestEvents::convertEventArray(
+ $options,
+ ['end'],
+ [
+ 'priority' => RequestEvents::LATE,
+ 'fn' => function (EndEvent $e) use ($hash) {
+ $hash[$e->getRequest()] = $e->getException()
+ ? $e->getException()
+ : $e->getResponse();
+ }
+ ]
+ )))->wait();
+
+ return new BatchResults($hash);
+ }
+
+ /**
+ * Creates a Pool and immediately sends the requests.
+ *
+ * @param ClientInterface $client Client used to send the requests
+ * @param array|\Iterator $requests Requests to send in parallel
+ * @param array $options Passes through the options available in
+ * {@see GuzzleHttp\Pool::__construct}
+ */
+ public static function send(
+ ClientInterface $client,
+ $requests,
+ array $options = []
+ ) {
+ $pool = new self($client, $requests, $options);
+ $pool->wait();
+ }
+
+ private function getPoolSize()
+ {
+ return is_callable($this->poolSize)
+ ? call_user_func($this->poolSize, count($this->waitQueue))
+ : $this->poolSize;
+ }
+
+ /**
+ * Add as many requests as possible up to the current pool limit.
+ */
+ private function addNextRequests()
+ {
+ $limit = max($this->getPoolSize() - count($this->waitQueue), 0);
+ while ($limit--) {
+ if (!$this->addNextRequest()) {
+ break;
+ }
+ }
+ }
+
+ public function wait()
+ {
+ if ($this->isRealized) {
+ return false;
+ }
+
+ // Seed the pool with N number of requests.
+ $this->addNextRequests();
+
+ // Stop if the pool was cancelled while transferring requests.
+ if ($this->isRealized) {
+ return false;
+ }
+
+ // Wait on any outstanding FutureResponse objects.
+ while ($response = array_pop($this->waitQueue)) {
+ try {
+ $response->wait();
+ } catch (\Exception $e) {
+ // Eat exceptions because they should be handled asynchronously
+ }
+ $this->addNextRequests();
+ }
+
+ // Clean up no longer needed state.
+ $this->isRealized = true;
+ $this->waitQueue = $this->eventListeners = [];
+ $this->client = $this->iter = null;
+ $this->deferred->resolve(true);
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Attempt to cancel all outstanding requests (requests that are queued for
+ * dereferencing). Returns true if all outstanding requests can be
+ * cancelled.
+ *
+ * @return bool
+ */
+ public function cancel()
+ {
+ if ($this->isRealized) {
+ return false;
+ }
+
+ $success = $this->isRealized = true;
+ foreach ($this->waitQueue as $response) {
+ if (!$response->cancel()) {
+ $success = false;
+ }
+ }
+
+ return $success;
+ }
+
+ /**
+ * Returns a promise that is invoked when the pool completed. There will be
+ * no passed value.
+ *
+ * {@inheritdoc}
+ */
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return $this->promise->then($onFulfilled, $onRejected, $onProgress);
+ }
+
+ public function promise()
+ {
+ return $this->promise;
+ }
+
+ private function coerceIterable($requests)
+ {
+ if ($requests instanceof \Iterator) {
+ return $requests;
+ } elseif (is_array($requests)) {
+ return new \ArrayIterator($requests);
+ }
+
+ throw new \InvalidArgumentException('Expected Iterator or array. '
+ . 'Found ' . Core::describeType($requests));
+ }
+
+ /**
+ * Adds the next request to pool and tracks what requests need to be
+ * dereferenced when completing the pool.
+ */
+ private function addNextRequest()
+ {
+ add_next:
+
+ if ($this->isRealized || !$this->iter || !$this->iter->valid()) {
+ return false;
+ }
+
+ $request = $this->iter->current();
+ $this->iter->next();
+
+ if (!($request instanceof RequestInterface)) {
+ throw new \InvalidArgumentException(sprintf(
+ 'All requests in the provided iterator must implement '
+ . 'RequestInterface. Found %s',
+ Core::describeType($request)
+ ));
+ }
+
+ // Be sure to use "lazy" futures, meaning they do not send right away.
+ $request->getConfig()->set('future', 'lazy');
+ $hash = spl_object_hash($request);
+ $this->attachListeners($request, $this->eventListeners);
+ $request->getEmitter()->on('before', [$this, '_trackRetries'], RequestEvents::EARLY);
+ $response = $this->client->send($request);
+ $this->waitQueue[$hash] = $response;
+ $promise = $response->promise();
+
+ // Don't recursively call itself for completed or rejected responses.
+ if ($promise instanceof FulfilledPromise
+ || $promise instanceof RejectedPromise
+ ) {
+ try {
+ $this->finishResponse($request, $response->wait(), $hash);
+ } catch (\Exception $e) {
+ $this->finishResponse($request, $e, $hash);
+ }
+ goto add_next;
+ }
+
+ // Use this function for both resolution and rejection.
+ $thenFn = function ($value) use ($request, $hash) {
+ $this->finishResponse($request, $value, $hash);
+ if (!$request->getConfig()->get('_pool_retries')) {
+ $this->addNextRequests();
+ }
+ };
+
+ $promise->then($thenFn, $thenFn);
+
+ return true;
+ }
+
+ public function _trackRetries(BeforeEvent $e)
+ {
+ $e->getRequest()->getConfig()->set('_pool_retries', $e->getRetryCount());
+ }
+
+ private function finishResponse($request, $value, $hash)
+ {
+ unset($this->waitQueue[$hash]);
+ $result = $value instanceof ResponseInterface
+ ? ['request' => $request, 'response' => $value, 'error' => null]
+ : ['request' => $request, 'response' => null, 'error' => $value];
+ $this->deferred->notify($result);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php
new file mode 100644
index 0000000..1149e62
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/MultipartBody.php
@@ -0,0 +1,109 @@
+<?php
+namespace GuzzleHttp\Post;
+
+use GuzzleHttp\Stream\AppendStream;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\StreamDecoratorTrait;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Stream that when read returns bytes for a streaming multipart/form-data body
+ */
+class MultipartBody implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ private $boundary;
+
+ /**
+ * @param array $fields Associative array of field names to values where
+ * each value is a string or array of strings.
+ * @param array $files Associative array of PostFileInterface objects
+ * @param string $boundary You can optionally provide a specific boundary
+ * @throws \InvalidArgumentException
+ */
+ public function __construct(
+ array $fields = [],
+ array $files = [],
+ $boundary = null
+ ) {
+ $this->boundary = $boundary ?: uniqid();
+ $this->stream = $this->createStream($fields, $files);
+ }
+
+ /**
+ * Get the boundary
+ *
+ * @return string
+ */
+ public function getBoundary()
+ {
+ return $this->boundary;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ /**
+ * Get the string needed to transfer a POST field
+ */
+ private function getFieldString($name, $value)
+ {
+ return sprintf(
+ "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n",
+ $this->boundary,
+ $name,
+ $value
+ );
+ }
+
+ /**
+ * Get the headers needed before transferring the content of a POST file
+ */
+ private function getFileHeaders(PostFileInterface $file)
+ {
+ $headers = '';
+ foreach ($file->getHeaders() as $key => $value) {
+ $headers .= "{$key}: {$value}\r\n";
+ }
+
+ return "--{$this->boundary}\r\n" . trim($headers) . "\r\n\r\n";
+ }
+
+ /**
+ * Create the aggregate stream that will be used to upload the POST data
+ */
+ protected function createStream(array $fields, array $files)
+ {
+ $stream = new AppendStream();
+
+ foreach ($fields as $name => $fieldValues) {
+ foreach ((array) $fieldValues as $value) {
+ $stream->addStream(
+ Stream::factory($this->getFieldString($name, $value))
+ );
+ }
+ }
+
+ foreach ($files as $file) {
+
+ if (!$file instanceof PostFileInterface) {
+ throw new \InvalidArgumentException('All POST fields must '
+ . 'implement PostFieldInterface');
+ }
+
+ $stream->addStream(
+ Stream::factory($this->getFileHeaders($file))
+ );
+ $stream->addStream($file->getContent());
+ $stream->addStream(Stream::factory("\r\n"));
+ }
+
+ // Add the trailing boundary with CRLF
+ $stream->addStream(Stream::factory("--{$this->boundary}--\r\n"));
+
+ return $stream;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBody.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBody.php
new file mode 100644
index 0000000..ed14d1f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBody.php
@@ -0,0 +1,287 @@
+<?php
+namespace GuzzleHttp\Post;
+
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Query;
+
+/**
+ * Holds POST fields and files and creates a streaming body when read methods
+ * are called on the object.
+ */
+class PostBody implements PostBodyInterface
+{
+ /** @var StreamInterface */
+ private $body;
+
+ /** @var callable */
+ private $aggregator;
+
+ private $fields = [];
+
+ /** @var PostFileInterface[] */
+ private $files = [];
+ private $forceMultipart = false;
+ private $detached = false;
+
+ /**
+ * Applies request headers to a request based on the POST state
+ *
+ * @param RequestInterface $request Request to update
+ */
+ public function applyRequestHeaders(RequestInterface $request)
+ {
+ if ($this->files || $this->forceMultipart) {
+ $request->setHeader(
+ 'Content-Type',
+ 'multipart/form-data; boundary=' . $this->getBody()->getBoundary()
+ );
+ } elseif ($this->fields && !$request->hasHeader('Content-Type')) {
+ $request->setHeader(
+ 'Content-Type',
+ 'application/x-www-form-urlencoded'
+ );
+ }
+
+ if ($size = $this->getSize()) {
+ $request->setHeader('Content-Length', $size);
+ }
+ }
+
+ public function forceMultipartUpload($force)
+ {
+ $this->forceMultipart = $force;
+ }
+
+ public function setAggregator(callable $aggregator)
+ {
+ $this->aggregator = $aggregator;
+ }
+
+ public function setField($name, $value)
+ {
+ $this->fields[$name] = $value;
+ $this->mutate();
+ }
+
+ public function replaceFields(array $fields)
+ {
+ $this->fields = $fields;
+ $this->mutate();
+ }
+
+ public function getField($name)
+ {
+ return isset($this->fields[$name]) ? $this->fields[$name] : null;
+ }
+
+ public function removeField($name)
+ {
+ unset($this->fields[$name]);
+ $this->mutate();
+ }
+
+ public function getFields($asString = false)
+ {
+ if (!$asString) {
+ return $this->fields;
+ }
+
+ $query = new Query($this->fields);
+ $query->setEncodingType(Query::RFC1738);
+ $query->setAggregator($this->getAggregator());
+
+ return (string) $query;
+ }
+
+ public function hasField($name)
+ {
+ return isset($this->fields[$name]);
+ }
+
+ public function getFile($name)
+ {
+ foreach ($this->files as $file) {
+ if ($file->getName() == $name) {
+ return $file;
+ }
+ }
+
+ return null;
+ }
+
+ public function getFiles()
+ {
+ return $this->files;
+ }
+
+ public function addFile(PostFileInterface $file)
+ {
+ $this->files[] = $file;
+ $this->mutate();
+ }
+
+ public function clearFiles()
+ {
+ $this->files = [];
+ $this->mutate();
+ }
+
+ /**
+ * Returns the numbers of fields + files
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->files) + count($this->fields);
+ }
+
+ public function __toString()
+ {
+ return (string) $this->getBody();
+ }
+
+ public function getContents($maxLength = -1)
+ {
+ return $this->getBody()->getContents();
+ }
+
+ public function close()
+ {
+ $this->detach();
+ }
+
+ public function detach()
+ {
+ $this->detached = true;
+ $this->fields = $this->files = [];
+
+ if ($this->body) {
+ $this->body->close();
+ $this->body = null;
+ }
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function eof()
+ {
+ return $this->getBody()->eof();
+ }
+
+ public function tell()
+ {
+ return $this->body ? $this->body->tell() : 0;
+ }
+
+ public function isSeekable()
+ {
+ return true;
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function getSize()
+ {
+ return $this->getBody()->getSize();
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return $this->getBody()->seek($offset, $whence);
+ }
+
+ public function read($length)
+ {
+ return $this->getBody()->read($length);
+ }
+
+ public function write($string)
+ {
+ return false;
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $key ? null : [];
+ }
+
+ /**
+ * Return a stream object that is built from the POST fields and files.
+ *
+ * If one has already been created, the previously created stream will be
+ * returned.
+ */
+ private function getBody()
+ {
+ if ($this->body) {
+ return $this->body;
+ } elseif ($this->files || $this->forceMultipart) {
+ return $this->body = $this->createMultipart();
+ } elseif ($this->fields) {
+ return $this->body = $this->createUrlEncoded();
+ } else {
+ return $this->body = Stream::factory();
+ }
+ }
+
+ /**
+ * Get the aggregator used to join multi-valued field parameters
+ *
+ * @return callable
+ */
+ final protected function getAggregator()
+ {
+ if (!$this->aggregator) {
+ $this->aggregator = Query::phpAggregator();
+ }
+
+ return $this->aggregator;
+ }
+
+ /**
+ * Creates a multipart/form-data body stream
+ *
+ * @return MultipartBody
+ */
+ private function createMultipart()
+ {
+ // Flatten the nested query string values using the correct aggregator
+ return new MultipartBody(
+ call_user_func($this->getAggregator(), $this->fields),
+ $this->files
+ );
+ }
+
+ /**
+ * Creates an application/x-www-form-urlencoded stream body
+ *
+ * @return StreamInterface
+ */
+ private function createUrlEncoded()
+ {
+ return Stream::factory($this->getFields(true));
+ }
+
+ /**
+ * Get rid of any cached data
+ */
+ private function mutate()
+ {
+ $this->body = null;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php
new file mode 100644
index 0000000..c2ec9a6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostBodyInterface.php
@@ -0,0 +1,109 @@
+<?php
+namespace GuzzleHttp\Post;
+
+use GuzzleHttp\Message\AppliesHeadersInterface;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Represents a POST body that is sent as either a multipart/form-data stream
+ * or application/x-www-urlencoded stream.
+ */
+interface PostBodyInterface extends StreamInterface, \Countable, AppliesHeadersInterface
+{
+ /**
+ * Set a specific field
+ *
+ * @param string $name Name of the field to set
+ * @param string|array $value Value to set
+ */
+ public function setField($name, $value);
+
+ /**
+ * Set the aggregation strategy that will be used to turn multi-valued
+ * fields into a string.
+ *
+ * The aggregation function accepts a deeply nested array of query string
+ * values and returns a flattened associative array of key value pairs.
+ *
+ * @param callable $aggregator
+ */
+ public function setAggregator(callable $aggregator);
+
+ /**
+ * Set to true to force a multipart upload even if there are no files.
+ *
+ * @param bool $force Set to true to force multipart uploads or false to
+ * remove this flag.
+ */
+ public function forceMultipartUpload($force);
+
+ /**
+ * Replace all existing form fields with an array of fields
+ *
+ * @param array $fields Associative array of fields to set
+ */
+ public function replaceFields(array $fields);
+
+ /**
+ * Get a specific field by name
+ *
+ * @param string $name Name of the POST field to retrieve
+ *
+ * @return string|null
+ */
+ public function getField($name);
+
+ /**
+ * Remove a field by name
+ *
+ * @param string $name Name of the field to remove
+ */
+ public function removeField($name);
+
+ /**
+ * Returns an associative array of names to values or a query string.
+ *
+ * @param bool $asString Set to true to retrieve the fields as a query
+ * string.
+ *
+ * @return array|string
+ */
+ public function getFields($asString = false);
+
+ /**
+ * Returns true if a field is set
+ *
+ * @param string $name Name of the field to set
+ *
+ * @return bool
+ */
+ public function hasField($name);
+
+ /**
+ * Get all of the files
+ *
+ * @return array Returns an array of PostFileInterface objects
+ */
+ public function getFiles();
+
+ /**
+ * Get a POST file by name.
+ *
+ * @param string $name Name of the POST file to retrieve
+ *
+ * @return PostFileInterface|null
+ */
+ public function getFile($name);
+
+ /**
+ * Add a file to the POST
+ *
+ * @param PostFileInterface $file File to add
+ */
+ public function addFile(PostFileInterface $file);
+
+ /**
+ * Remove all files from the collection
+ */
+ public function clearFiles();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFile.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFile.php
new file mode 100644
index 0000000..e102c02
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFile.php
@@ -0,0 +1,135 @@
+<?php
+namespace GuzzleHttp\Post;
+
+use GuzzleHttp\Mimetypes;
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Stream\Stream;
+
+/**
+ * Post file upload
+ */
+class PostFile implements PostFileInterface
+{
+ private $name;
+ private $filename;
+ private $content;
+ private $headers = [];
+
+ /**
+ * @param string $name Name of the form field
+ * @param mixed $content Data to send
+ * @param string|null $filename Filename content-disposition attribute
+ * @param array $headers Array of headers to set on the file
+ * (can override any default headers)
+ * @throws \RuntimeException when filename is not passed or can't be determined
+ */
+ public function __construct(
+ $name,
+ $content,
+ $filename = null,
+ array $headers = []
+ ) {
+ $this->headers = $headers;
+ $this->name = $name;
+ $this->prepareContent($content);
+ $this->prepareFilename($filename);
+ $this->prepareDefaultHeaders();
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getFilename()
+ {
+ return $this->filename;
+ }
+
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ /**
+ * Prepares the contents of a POST file.
+ *
+ * @param mixed $content Content of the POST file
+ */
+ private function prepareContent($content)
+ {
+ $this->content = $content;
+
+ if (!($this->content instanceof StreamInterface)) {
+ $this->content = Stream::factory($this->content);
+ } elseif ($this->content instanceof MultipartBody) {
+ if (!$this->hasHeader('Content-Disposition')) {
+ $disposition = 'form-data; name="' . $this->name .'"';
+ $this->headers['Content-Disposition'] = $disposition;
+ }
+
+ if (!$this->hasHeader('Content-Type')) {
+ $this->headers['Content-Type'] = sprintf(
+ "multipart/form-data; boundary=%s",
+ $this->content->getBoundary()
+ );
+ }
+ }
+ }
+
+ /**
+ * Applies a file name to the POST file based on various checks.
+ *
+ * @param string|null $filename Filename to apply (or null to guess)
+ */
+ private function prepareFilename($filename)
+ {
+ $this->filename = $filename;
+
+ if (!$this->filename) {
+ $this->filename = $this->content->getMetadata('uri');
+ }
+
+ if (!$this->filename || substr($this->filename, 0, 6) === 'php://') {
+ $this->filename = $this->name;
+ }
+ }
+
+ /**
+ * Applies default Content-Disposition and Content-Type headers if needed.
+ */
+ private function prepareDefaultHeaders()
+ {
+ // Set a default content-disposition header if one was no provided
+ if (!$this->hasHeader('Content-Disposition')) {
+ $this->headers['Content-Disposition'] = sprintf(
+ 'form-data; name="%s"; filename="%s"',
+ $this->name,
+ basename($this->filename)
+ );
+ }
+
+ // Set a default Content-Type if one was not supplied
+ if (!$this->hasHeader('Content-Type')) {
+ $this->headers['Content-Type'] = Mimetypes::getInstance()
+ ->fromFilename($this->filename) ?: 'text/plain';
+ }
+ }
+
+ /**
+ * Check if a specific header exists on the POST file by name.
+ *
+ * @param string $name Case-insensitive header to check
+ *
+ * @return bool
+ */
+ private function hasHeader($name)
+ {
+ return isset(array_change_key_case($this->headers)[strtolower($name)]);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php
new file mode 100644
index 0000000..2e816c0
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Post/PostFileInterface.php
@@ -0,0 +1,41 @@
+<?php
+namespace GuzzleHttp\Post;
+
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Post file upload interface
+ */
+interface PostFileInterface
+{
+ /**
+ * Get the name of the form field
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Get the full path to the file
+ *
+ * @return string
+ */
+ public function getFilename();
+
+ /**
+ * Get the content
+ *
+ * @return StreamInterface
+ */
+ public function getContent();
+
+ /**
+ * Gets all POST file headers.
+ *
+ * The keys represent the header name as it will be sent over the wire, and
+ * each value is a string.
+ *
+ * @return array Returns an associative array of the file's headers.
+ */
+ public function getHeaders();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Query.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Query.php
new file mode 100644
index 0000000..d053def
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Query.php
@@ -0,0 +1,204 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Manages query string variables and can aggregate them into a string
+ */
+class Query extends Collection
+{
+ const RFC3986 = 'RFC3986';
+ const RFC1738 = 'RFC1738';
+
+ /** @var callable Encoding function */
+ private $encoding = 'rawurlencode';
+ /** @var callable */
+ private $aggregator;
+
+ /**
+ * Parse a query string into a Query object
+ *
+ * $urlEncoding is used to control how the query string is parsed and how
+ * it is ultimately serialized. The value can be set to one of the
+ * following:
+ *
+ * - true: (default) Parse query strings using RFC 3986 while still
+ * converting "+" to " ".
+ * - false: Disables URL decoding of the input string and URL encoding when
+ * the query string is serialized.
+ * - 'RFC3986': Use RFC 3986 URL encoding/decoding
+ * - 'RFC1738': Use RFC 1738 URL encoding/decoding
+ *
+ * @param string $query Query string to parse
+ * @param bool|string $urlEncoding Controls how the input string is decoded
+ * and encoded.
+ * @return self
+ */
+ public static function fromString($query, $urlEncoding = true)
+ {
+ static $qp;
+ if (!$qp) {
+ $qp = new QueryParser();
+ }
+
+ $q = new static();
+
+ if ($urlEncoding !== true) {
+ $q->setEncodingType($urlEncoding);
+ }
+
+ $qp->parseInto($q, $query, $urlEncoding);
+
+ return $q;
+ }
+
+ /**
+ * Convert the query string parameters to a query string string
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ if (!$this->data) {
+ return '';
+ }
+
+ // The default aggregator is statically cached
+ static $defaultAggregator;
+
+ if (!$this->aggregator) {
+ if (!$defaultAggregator) {
+ $defaultAggregator = self::phpAggregator();
+ }
+ $this->aggregator = $defaultAggregator;
+ }
+
+ $result = '';
+ $aggregator = $this->aggregator;
+ $encoder = $this->encoding;
+
+ foreach ($aggregator($this->data) as $key => $values) {
+ foreach ($values as $value) {
+ if ($result) {
+ $result .= '&';
+ }
+ $result .= $encoder($key);
+ if ($value !== null) {
+ $result .= '=' . $encoder($value);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Controls how multi-valued query string parameters are aggregated into a
+ * string.
+ *
+ * $query->setAggregator($query::duplicateAggregator());
+ *
+ * @param callable $aggregator Callable used to convert a deeply nested
+ * array of query string variables into a flattened array of key value
+ * pairs. The callable accepts an array of query data and returns a
+ * flattened array of key value pairs where each value is an array of
+ * strings.
+ */
+ public function setAggregator(callable $aggregator)
+ {
+ $this->aggregator = $aggregator;
+ }
+
+ /**
+ * Specify how values are URL encoded
+ *
+ * @param string|bool $type One of 'RFC1738', 'RFC3986', or false to disable encoding
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setEncodingType($type)
+ {
+ switch ($type) {
+ case self::RFC3986:
+ $this->encoding = 'rawurlencode';
+ break;
+ case self::RFC1738:
+ $this->encoding = 'urlencode';
+ break;
+ case false:
+ $this->encoding = function ($v) { return $v; };
+ break;
+ default:
+ throw new \InvalidArgumentException('Invalid URL encoding type');
+ }
+ }
+
+ /**
+ * Query string aggregator that does not aggregate nested query string
+ * values and allows duplicates in the resulting array.
+ *
+ * Example: http://test.com?q=1&q=2
+ *
+ * @return callable
+ */
+ public static function duplicateAggregator()
+ {
+ return function (array $data) {
+ return self::walkQuery($data, '', function ($key, $prefix) {
+ return is_int($key) ? $prefix : "{$prefix}[{$key}]";
+ });
+ };
+ }
+
+ /**
+ * Aggregates nested query string variables using the same technique as
+ * ``http_build_query()``.
+ *
+ * @param bool $numericIndices Pass false to not include numeric indices
+ * when multi-values query string parameters are present.
+ *
+ * @return callable
+ */
+ public static function phpAggregator($numericIndices = true)
+ {
+ return function (array $data) use ($numericIndices) {
+ return self::walkQuery(
+ $data,
+ '',
+ function ($key, $prefix) use ($numericIndices) {
+ return !$numericIndices && is_int($key)
+ ? "{$prefix}[]"
+ : "{$prefix}[{$key}]";
+ }
+ );
+ };
+ }
+
+ /**
+ * Easily create query aggregation functions by providing a key prefix
+ * function to this query string array walker.
+ *
+ * @param array $query Query string to walk
+ * @param string $keyPrefix Key prefix (start with '')
+ * @param callable $prefixer Function used to create a key prefix
+ *
+ * @return array
+ */
+ public static function walkQuery(array $query, $keyPrefix, callable $prefixer)
+ {
+ $result = [];
+ foreach ($query as $key => $value) {
+ if ($keyPrefix) {
+ $key = $prefixer($key, $keyPrefix);
+ }
+ if (is_array($value)) {
+ $result += self::walkQuery($value, $key, $prefixer);
+ } elseif (isset($result[$key])) {
+ $result[$key][] = $value;
+ } else {
+ $result[$key] = array($value);
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/QueryParser.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/QueryParser.php
new file mode 100644
index 0000000..90727cc
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/QueryParser.php
@@ -0,0 +1,163 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Parses query strings into a Query object.
+ *
+ * While parsing, the parser will attempt to determine the most appropriate
+ * query string aggregator to use when serializing the parsed query string
+ * object back into a string. The hope is that parsing then serializing a
+ * query string should be a lossless operation.
+ *
+ * @internal Use Query::fromString()
+ */
+class QueryParser
+{
+ private $duplicates;
+ private $numericIndices;
+
+ /**
+ * Parse a query string into a Query object.
+ *
+ * @param Query $query Query object to populate
+ * @param string $str Query string to parse
+ * @param bool|string $urlEncoding How the query string is encoded
+ */
+ public function parseInto(Query $query, $str, $urlEncoding = true)
+ {
+ if ($str === '') {
+ return;
+ }
+
+ $result = [];
+ $this->duplicates = false;
+ $this->numericIndices = true;
+ $decoder = self::getDecoder($urlEncoding);
+
+ foreach (explode('&', $str) as $kvp) {
+
+ $parts = explode('=', $kvp, 2);
+ $key = $decoder($parts[0]);
+ $value = isset($parts[1]) ? $decoder($parts[1]) : null;
+
+ // Special handling needs to be taken for PHP nested array syntax
+ if (strpos($key, '[') !== false) {
+ $this->parsePhpValue($key, $value, $result);
+ continue;
+ }
+
+ if (!isset($result[$key])) {
+ $result[$key] = $value;
+ } else {
+ $this->duplicates = true;
+ if (!is_array($result[$key])) {
+ $result[$key] = [$result[$key]];
+ }
+ $result[$key][] = $value;
+ }
+ }
+
+ $query->replace($result);
+
+ if (!$this->numericIndices) {
+ $query->setAggregator(Query::phpAggregator(false));
+ } elseif ($this->duplicates) {
+ $query->setAggregator(Query::duplicateAggregator());
+ }
+ }
+
+ /**
+ * Returns a callable that is used to URL decode query keys and values.
+ *
+ * @param string|bool $type One of true, false, RFC3986, and RFC1738
+ *
+ * @return callable|string
+ */
+ private static function getDecoder($type)
+ {
+ if ($type === true) {
+ return function ($value) {
+ return rawurldecode(str_replace('+', ' ', $value));
+ };
+ } elseif ($type == Query::RFC3986) {
+ return 'rawurldecode';
+ } elseif ($type == Query::RFC1738) {
+ return 'urldecode';
+ } else {
+ return function ($str) { return $str; };
+ }
+ }
+
+ /**
+ * Parses a PHP style key value pair.
+ *
+ * @param string $key Key to parse (e.g., "foo[a][b]")
+ * @param string|null $value Value to set
+ * @param array $result Result to modify by reference
+ */
+ private function parsePhpValue($key, $value, array &$result)
+ {
+ $node =& $result;
+ $keyBuffer = '';
+
+ for ($i = 0, $t = strlen($key); $i < $t; $i++) {
+ switch ($key[$i]) {
+ case '[':
+ if ($keyBuffer) {
+ $this->prepareNode($node, $keyBuffer);
+ $node =& $node[$keyBuffer];
+ $keyBuffer = '';
+ }
+ break;
+ case ']':
+ $k = $this->cleanKey($node, $keyBuffer);
+ $this->prepareNode($node, $k);
+ $node =& $node[$k];
+ $keyBuffer = '';
+ break;
+ default:
+ $keyBuffer .= $key[$i];
+ break;
+ }
+ }
+
+ if (isset($node)) {
+ $this->duplicates = true;
+ $node[] = $value;
+ } else {
+ $node = $value;
+ }
+ }
+
+ /**
+ * Prepares a value in the array at the given key.
+ *
+ * If the key already exists, the key value is converted into an array.
+ *
+ * @param array $node Result node to modify
+ * @param string $key Key to add or modify in the node
+ */
+ private function prepareNode(&$node, $key)
+ {
+ if (!isset($node[$key])) {
+ $node[$key] = null;
+ } elseif (!is_array($node[$key])) {
+ $node[$key] = [$node[$key]];
+ }
+ }
+
+ /**
+ * Returns the appropriate key based on the node and key.
+ */
+ private function cleanKey($node, $key)
+ {
+ if ($key === '') {
+ $key = $node ? (string) count($node) : 0;
+ // Found a [] key, so track this to ensure that we disable numeric
+ // indexing of keys in the resolved query aggregator.
+ $this->numericIndices = false;
+ }
+
+ return $key;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/RequestFsm.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/RequestFsm.php
new file mode 100644
index 0000000..b37c190
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/RequestFsm.php
@@ -0,0 +1,153 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Event\ErrorEvent;
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\EndEvent;
+use GuzzleHttp\Exception\StateException;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\FutureResponse;
+use GuzzleHttp\Message\MessageFactoryInterface;
+use GuzzleHttp\Ring\Future\FutureInterface;
+
+/**
+ * Responsible for transitioning requests through lifecycle events.
+ */
+class RequestFsm
+{
+ private $handler;
+ private $mf;
+ private $maxTransitions;
+
+ public function __construct(
+ callable $handler,
+ MessageFactoryInterface $messageFactory,
+ $maxTransitions = 200
+ ) {
+ $this->mf = $messageFactory;
+ $this->maxTransitions = $maxTransitions;
+ $this->handler = $handler;
+ }
+
+ /**
+ * Runs the state machine until a terminal state is entered or the
+ * optionally supplied $finalState is entered.
+ *
+ * @param Transaction $trans Transaction being transitioned.
+ *
+ * @throws \Exception if a terminal state throws an exception.
+ */
+ public function __invoke(Transaction $trans)
+ {
+ $trans->_transitionCount = 0;
+
+ if (!$trans->state) {
+ $trans->state = 'before';
+ }
+
+ transition:
+
+ if (++$trans->_transitionCount > $this->maxTransitions) {
+ throw new StateException("Too many state transitions were "
+ . "encountered ({$trans->_transitionCount}). This likely "
+ . "means that a combination of event listeners are in an "
+ . "infinite loop.");
+ }
+
+ switch ($trans->state) {
+ case 'before': goto before;
+ case 'complete': goto complete;
+ case 'error': goto error;
+ case 'retry': goto retry;
+ case 'send': goto send;
+ case 'end': goto end;
+ default: throw new StateException("Invalid state: {$trans->state}");
+ }
+
+ before: {
+ try {
+ $trans->request->getEmitter()->emit('before', new BeforeEvent($trans));
+ $trans->state = 'send';
+ if ((bool) $trans->response) {
+ $trans->state = 'complete';
+ }
+ } catch (\Exception $e) {
+ $trans->state = 'error';
+ $trans->exception = $e;
+ }
+ goto transition;
+ }
+
+ complete: {
+ try {
+ if ($trans->response instanceof FutureInterface) {
+ // Futures will have their own end events emitted when
+ // dereferenced.
+ return;
+ }
+ $trans->state = 'end';
+ $trans->response->setEffectiveUrl($trans->request->getUrl());
+ $trans->request->getEmitter()->emit('complete', new CompleteEvent($trans));
+ } catch (\Exception $e) {
+ $trans->state = 'error';
+ $trans->exception = $e;
+ }
+ goto transition;
+ }
+
+ error: {
+ try {
+ // Convert non-request exception to a wrapped exception
+ $trans->exception = RequestException::wrapException(
+ $trans->request, $trans->exception
+ );
+ $trans->state = 'end';
+ $trans->request->getEmitter()->emit('error', new ErrorEvent($trans));
+ // An intercepted request (not retried) transitions to complete
+ if (!$trans->exception && $trans->state !== 'retry') {
+ $trans->state = 'complete';
+ }
+ } catch (\Exception $e) {
+ $trans->state = 'end';
+ $trans->exception = $e;
+ }
+ goto transition;
+ }
+
+ retry: {
+ $trans->retries++;
+ $trans->response = null;
+ $trans->exception = null;
+ $trans->state = 'before';
+ goto transition;
+ }
+
+ send: {
+ $fn = $this->handler;
+ $trans->response = FutureResponse::proxy(
+ $fn(RingBridge::prepareRingRequest($trans)),
+ function ($value) use ($trans) {
+ RingBridge::completeRingResponse($trans, $value, $this->mf, $this);
+ $this($trans);
+ return $trans->response;
+ }
+ );
+ return;
+ }
+
+ end: {
+ $trans->request->getEmitter()->emit('end', new EndEvent($trans));
+ // Throw exceptions in the terminal event if the exception
+ // was not handled by an "end" event listener.
+ if ($trans->exception) {
+ if (!($trans->exception instanceof RequestException)) {
+ $trans->exception = RequestException::wrapException(
+ $trans->request, $trans->exception
+ );
+ }
+ throw $trans->exception;
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/RingBridge.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/RingBridge.php
new file mode 100644
index 0000000..bc6841d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/RingBridge.php
@@ -0,0 +1,165 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Message\MessageFactoryInterface;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Event\ProgressEvent;
+use GuzzleHttp\Message\Request;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Exception\RequestException;
+
+/**
+ * Provides the bridge between Guzzle requests and responses and Guzzle Ring.
+ */
+class RingBridge
+{
+ /**
+ * Creates a Ring request from a request object.
+ *
+ * This function does not hook up the "then" and "progress" events that
+ * would be required for actually sending a Guzzle request through a
+ * RingPHP handler.
+ *
+ * @param RequestInterface $request Request to convert.
+ *
+ * @return array Converted Guzzle Ring request.
+ */
+ public static function createRingRequest(RequestInterface $request)
+ {
+ $options = $request->getConfig()->toArray();
+ $url = $request->getUrl();
+ // No need to calculate the query string twice (in URL and query).
+ $qs = ($pos = strpos($url, '?')) ? substr($url, $pos + 1) : null;
+
+ return [
+ 'scheme' => $request->getScheme(),
+ 'http_method' => $request->getMethod(),
+ 'url' => $url,
+ 'uri' => $request->getPath(),
+ 'headers' => $request->getHeaders(),
+ 'body' => $request->getBody(),
+ 'version' => $request->getProtocolVersion(),
+ 'client' => $options,
+ 'query_string' => $qs,
+ 'future' => isset($options['future']) ? $options['future'] : false
+ ];
+ }
+
+ /**
+ * Creates a Ring request from a request object AND prepares the callbacks.
+ *
+ * @param Transaction $trans Transaction to update.
+ *
+ * @return array Converted Guzzle Ring request.
+ */
+ public static function prepareRingRequest(Transaction $trans)
+ {
+ // Clear out the transaction state when initiating.
+ $trans->exception = null;
+ $request = self::createRingRequest($trans->request);
+
+ // Emit progress events if any progress listeners are registered.
+ if ($trans->request->getEmitter()->hasListeners('progress')) {
+ $emitter = $trans->request->getEmitter();
+ $request['client']['progress'] = function ($a, $b, $c, $d) use ($trans, $emitter) {
+ $emitter->emit('progress', new ProgressEvent($trans, $a, $b, $c, $d));
+ };
+ }
+
+ return $request;
+ }
+
+ /**
+ * Handles the process of processing a response received from a ring
+ * handler. The created response is added to the transaction, and the
+ * transaction stat is set appropriately.
+ *
+ * @param Transaction $trans Owns request and response.
+ * @param array $response Ring response array
+ * @param MessageFactoryInterface $messageFactory Creates response objects.
+ */
+ public static function completeRingResponse(
+ Transaction $trans,
+ array $response,
+ MessageFactoryInterface $messageFactory
+ ) {
+ $trans->state = 'complete';
+ $trans->transferInfo = isset($response['transfer_stats'])
+ ? $response['transfer_stats'] : [];
+
+ if (!empty($response['status'])) {
+ $options = [];
+ if (isset($response['version'])) {
+ $options['protocol_version'] = $response['version'];
+ }
+ if (isset($response['reason'])) {
+ $options['reason_phrase'] = $response['reason'];
+ }
+ $trans->response = $messageFactory->createResponse(
+ $response['status'],
+ isset($response['headers']) ? $response['headers'] : [],
+ isset($response['body']) ? $response['body'] : null,
+ $options
+ );
+ if (isset($response['effective_url'])) {
+ $trans->response->setEffectiveUrl($response['effective_url']);
+ }
+ } elseif (empty($response['error'])) {
+ // When nothing was returned, then we need to add an error.
+ $response['error'] = self::getNoRingResponseException($trans->request);
+ }
+
+ if (isset($response['error'])) {
+ $trans->state = 'error';
+ $trans->exception = $response['error'];
+ }
+ }
+
+ /**
+ * Creates a Guzzle request object using a ring request array.
+ *
+ * @param array $request Ring request
+ *
+ * @return Request
+ * @throws \InvalidArgumentException for incomplete requests.
+ */
+ public static function fromRingRequest(array $request)
+ {
+ $options = [];
+ if (isset($request['version'])) {
+ $options['protocol_version'] = $request['version'];
+ }
+
+ if (!isset($request['http_method'])) {
+ throw new \InvalidArgumentException('No http_method');
+ }
+
+ return new Request(
+ $request['http_method'],
+ Core::url($request),
+ isset($request['headers']) ? $request['headers'] : [],
+ isset($request['body']) ? Stream::factory($request['body']) : null,
+ $options
+ );
+ }
+
+ /**
+ * Get an exception that can be used when a RingPHP handler does not
+ * populate a response.
+ *
+ * @param RequestInterface $request
+ *
+ * @return RequestException
+ */
+ public static function getNoRingResponseException(RequestInterface $request)
+ {
+ $message = <<<EOT
+Sending the request did not return a response, exception, or populate the
+transaction with a response. This is most likely due to an incorrectly
+implemented RingPHP handler. If you are simply trying to mock responses,
+then it is recommended to use the GuzzleHttp\Ring\Client\MockHandler.
+EOT;
+ return new RequestException($message, $request);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php
new file mode 100644
index 0000000..cacabb6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Cookie.php
@@ -0,0 +1,58 @@
+<?php
+namespace GuzzleHttp\Subscriber;
+
+use GuzzleHttp\Cookie\CookieJar;
+use GuzzleHttp\Cookie\CookieJarInterface;
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+
+/**
+ * Adds, extracts, and persists cookies between HTTP requests
+ */
+class Cookie implements SubscriberInterface
+{
+ /** @var CookieJarInterface */
+ private $cookieJar;
+
+ /**
+ * @param CookieJarInterface $cookieJar Cookie jar used to hold cookies
+ */
+ public function __construct(CookieJarInterface $cookieJar = null)
+ {
+ $this->cookieJar = $cookieJar ?: new CookieJar();
+ }
+
+ public function getEvents()
+ {
+ // Fire the cookie plugin complete event before redirecting
+ return [
+ 'before' => ['onBefore'],
+ 'complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE + 10]
+ ];
+ }
+
+ /**
+ * Get the cookie cookieJar
+ *
+ * @return CookieJarInterface
+ */
+ public function getCookieJar()
+ {
+ return $this->cookieJar;
+ }
+
+ public function onBefore(BeforeEvent $event)
+ {
+ $this->cookieJar->addCookieHeader($event->getRequest());
+ }
+
+ public function onComplete(CompleteEvent $event)
+ {
+ $this->cookieJar->extractCookies(
+ $event->getRequest(),
+ $event->getResponse()
+ );
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/History.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/History.php
new file mode 100644
index 0000000..5cf0611
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/History.php
@@ -0,0 +1,172 @@
+<?php
+namespace GuzzleHttp\Subscriber;
+
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\ErrorEvent;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Maintains a list of requests and responses sent using a request or client
+ */
+class History implements SubscriberInterface, \IteratorAggregate, \Countable
+{
+ /** @var int The maximum number of requests to maintain in the history */
+ private $limit;
+
+ /** @var array Requests and responses that have passed through the plugin */
+ private $transactions = [];
+
+ public function __construct($limit = 10)
+ {
+ $this->limit = $limit;
+ }
+
+ public function getEvents()
+ {
+ return [
+ 'complete' => ['onComplete', RequestEvents::EARLY],
+ 'error' => ['onError', RequestEvents::EARLY],
+ ];
+ }
+
+ /**
+ * Convert to a string that contains all request and response headers
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $lines = array();
+ foreach ($this->transactions as $entry) {
+ $response = isset($entry['response']) ? $entry['response'] : '';
+ $lines[] = '> ' . trim($entry['sent_request'])
+ . "\n\n< " . trim($response) . "\n";
+ }
+
+ return implode("\n", $lines);
+ }
+
+ public function onComplete(CompleteEvent $event)
+ {
+ $this->add($event->getRequest(), $event->getResponse());
+ }
+
+ public function onError(ErrorEvent $event)
+ {
+ // Only track when no response is present, meaning this didn't ever
+ // emit a complete event
+ if (!$event->getResponse()) {
+ $this->add($event->getRequest());
+ }
+ }
+
+ /**
+ * Returns an Iterator that yields associative array values where each
+ * associative array contains the following key value pairs:
+ *
+ * - request: Representing the actual request that was received.
+ * - sent_request: A clone of the request that will not be mutated.
+ * - response: The response that was received (if available).
+ *
+ * @return \Iterator
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->transactions);
+ }
+
+ /**
+ * Get all of the requests sent through the plugin.
+ *
+ * Requests can be modified after they are logged by the history
+ * subscriber. By default this method will return the actual request
+ * instances that were received. Pass true to this method if you wish to
+ * get copies of the requests that represent the request state when it was
+ * initially logged by the history subscriber.
+ *
+ * @param bool $asSent Set to true to get clones of the requests that have
+ * not been mutated since the request was received by
+ * the history subscriber.
+ *
+ * @return RequestInterface[]
+ */
+ public function getRequests($asSent = false)
+ {
+ return array_map(function ($t) use ($asSent) {
+ return $asSent ? $t['sent_request'] : $t['request'];
+ }, $this->transactions);
+ }
+
+ /**
+ * Get the number of requests in the history
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->transactions);
+ }
+
+ /**
+ * Get the last request sent.
+ *
+ * Requests can be modified after they are logged by the history
+ * subscriber. By default this method will return the actual request
+ * instance that was received. Pass true to this method if you wish to get
+ * a copy of the request that represents the request state when it was
+ * initially logged by the history subscriber.
+ *
+ * @param bool $asSent Set to true to get a clone of the last request that
+ * has not been mutated since the request was received
+ * by the history subscriber.
+ *
+ * @return RequestInterface
+ */
+ public function getLastRequest($asSent = false)
+ {
+ return $asSent
+ ? end($this->transactions)['sent_request']
+ : end($this->transactions)['request'];
+ }
+
+ /**
+ * Get the last response in the history
+ *
+ * @return ResponseInterface|null
+ */
+ public function getLastResponse()
+ {
+ return end($this->transactions)['response'];
+ }
+
+ /**
+ * Clears the history
+ */
+ public function clear()
+ {
+ $this->transactions = array();
+ }
+
+ /**
+ * Add a request to the history
+ *
+ * @param RequestInterface $request Request to add
+ * @param ResponseInterface $response Response of the request
+ */
+ private function add(
+ RequestInterface $request,
+ ResponseInterface $response = null
+ ) {
+ $this->transactions[] = [
+ 'request' => $request,
+ 'sent_request' => clone $request,
+ 'response' => $response
+ ];
+ if (count($this->transactions) > $this->limit) {
+ array_shift($this->transactions);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php
new file mode 100644
index 0000000..ed9de5b
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/HttpError.php
@@ -0,0 +1,36 @@
+<?php
+namespace GuzzleHttp\Subscriber;
+
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Exception\RequestException;
+
+/**
+ * Throws exceptions when a 4xx or 5xx response is received
+ */
+class HttpError implements SubscriberInterface
+{
+ public function getEvents()
+ {
+ return ['complete' => ['onComplete', RequestEvents::VERIFY_RESPONSE]];
+ }
+
+ /**
+ * Throw a RequestException on an HTTP protocol error
+ *
+ * @param CompleteEvent $event Emitted event
+ * @throws RequestException
+ */
+ public function onComplete(CompleteEvent $event)
+ {
+ $code = (string) $event->getResponse()->getStatusCode();
+ // Throw an exception for an unsuccessful response
+ if ($code[0] >= 4) {
+ throw RequestException::create(
+ $event->getRequest(),
+ $event->getResponse()
+ );
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php
new file mode 100644
index 0000000..2af4d37
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Mock.php
@@ -0,0 +1,147 @@
+<?php
+namespace GuzzleHttp\Subscriber;
+
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\MessageFactory;
+use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Queues mock responses or exceptions and delivers mock responses or
+ * exceptions in a fifo order.
+ */
+class Mock implements SubscriberInterface, \Countable
+{
+ /** @var array Array of mock responses / exceptions */
+ private $queue = [];
+
+ /** @var bool Whether or not to consume an entity body when mocking */
+ private $readBodies;
+
+ /** @var MessageFactory */
+ private $factory;
+
+ /**
+ * @param array $items Array of responses or exceptions to queue
+ * @param bool $readBodies Set to false to not consume the entity body of
+ * a request when a mock is served.
+ */
+ public function __construct(array $items = [], $readBodies = true)
+ {
+ $this->factory = new MessageFactory();
+ $this->readBodies = $readBodies;
+ $this->addMultiple($items);
+ }
+
+ public function getEvents()
+ {
+ // Fire the event last, after signing
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST - 10]];
+ }
+
+ /**
+ * @throws \OutOfBoundsException|\Exception
+ */
+ public function onBefore(BeforeEvent $event)
+ {
+ if (!$item = array_shift($this->queue)) {
+ throw new \OutOfBoundsException('Mock queue is empty');
+ } elseif ($item instanceof RequestException) {
+ throw $item;
+ }
+
+ // Emulate reading a response body
+ $request = $event->getRequest();
+ if ($this->readBodies && $request->getBody()) {
+ while (!$request->getBody()->eof()) {
+ $request->getBody()->read(8096);
+ }
+ }
+
+ $saveTo = $event->getRequest()->getConfig()->get('save_to');
+
+ if (null !== $saveTo) {
+ $body = $item->getBody();
+
+ if (is_resource($saveTo)) {
+ fwrite($saveTo, $body);
+ } elseif (is_string($saveTo)) {
+ file_put_contents($saveTo, $body);
+ } elseif ($saveTo instanceof StreamInterface) {
+ $saveTo->write($body);
+ }
+ }
+
+ $event->intercept($item);
+ }
+
+ public function count()
+ {
+ return count($this->queue);
+ }
+
+ /**
+ * Add a response to the end of the queue
+ *
+ * @param string|ResponseInterface $response Response or path to response file
+ *
+ * @return self
+ * @throws \InvalidArgumentException if a string or Response is not passed
+ */
+ public function addResponse($response)
+ {
+ if (is_string($response)) {
+ $response = file_exists($response)
+ ? $this->factory->fromMessage(file_get_contents($response))
+ : $this->factory->fromMessage($response);
+ } elseif (!($response instanceof ResponseInterface)) {
+ throw new \InvalidArgumentException('Response must a message '
+ . 'string, response object, or path to a file');
+ }
+
+ $this->queue[] = $response;
+
+ return $this;
+ }
+
+ /**
+ * Add an exception to the end of the queue
+ *
+ * @param RequestException $e Exception to throw when the request is executed
+ *
+ * @return self
+ */
+ public function addException(RequestException $e)
+ {
+ $this->queue[] = $e;
+
+ return $this;
+ }
+
+ /**
+ * Add multiple items to the queue
+ *
+ * @param array $items Items to add
+ */
+ public function addMultiple(array $items)
+ {
+ foreach ($items as $item) {
+ if ($item instanceof RequestException) {
+ $this->addException($item);
+ } else {
+ $this->addResponse($item);
+ }
+ }
+ }
+
+ /**
+ * Clear the queue
+ */
+ public function clearQueue()
+ {
+ $this->queue = [];
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php
new file mode 100644
index 0000000..b5ed4e2
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php
@@ -0,0 +1,130 @@
+<?php
+namespace GuzzleHttp\Subscriber;
+
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Message\AppliesHeadersInterface;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Mimetypes;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Prepares requests with a body before sending
+ *
+ * **Request Options**
+ *
+ * - expect: Set to true to enable the "Expect: 100-Continue" header for a
+ * request that send a body. Set to false to disable "Expect: 100-Continue".
+ * Set to a number so that the size of the payload must be greater than the
+ * number in order to send the Expect header. Setting to a number will send
+ * the Expect header for all requests in which the size of the payload cannot
+ * be determined or where the body is not rewindable.
+ */
+class Prepare implements SubscriberInterface
+{
+ public function getEvents()
+ {
+ return ['before' => ['onBefore', RequestEvents::PREPARE_REQUEST]];
+ }
+
+ public function onBefore(BeforeEvent $event)
+ {
+ $request = $event->getRequest();
+
+ // Set the appropriate Content-Type for a request if one is not set and
+ // there are form fields
+ if (!($body = $request->getBody())) {
+ return;
+ }
+
+ $this->addContentLength($request, $body);
+
+ if ($body instanceof AppliesHeadersInterface) {
+ // Synchronize the body with the request headers
+ $body->applyRequestHeaders($request);
+ } elseif (!$request->hasHeader('Content-Type')) {
+ $this->addContentType($request, $body);
+ }
+
+ $this->addExpectHeader($request, $body);
+ }
+
+ private function addContentType(
+ RequestInterface $request,
+ StreamInterface $body
+ ) {
+ if (!($uri = $body->getMetadata('uri'))) {
+ return;
+ }
+
+ // Guess the content-type based on the stream's "uri" metadata value.
+ // The file extension is used to determine the appropriate mime-type.
+ if ($contentType = Mimetypes::getInstance()->fromFilename($uri)) {
+ $request->setHeader('Content-Type', $contentType);
+ }
+ }
+
+ private function addContentLength(
+ RequestInterface $request,
+ StreamInterface $body
+ ) {
+ // Set the Content-Length header if it can be determined, and never
+ // send a Transfer-Encoding: chunked and Content-Length header in
+ // the same request.
+ if ($request->hasHeader('Content-Length')) {
+ // Remove transfer-encoding if content-length is set.
+ $request->removeHeader('Transfer-Encoding');
+ return;
+ }
+
+ if ($request->hasHeader('Transfer-Encoding')) {
+ return;
+ }
+
+ if (null !== ($size = $body->getSize())) {
+ $request->setHeader('Content-Length', $size);
+ $request->removeHeader('Transfer-Encoding');
+ } elseif ('1.1' == $request->getProtocolVersion()) {
+ // Use chunked Transfer-Encoding if there is no determinable
+ // content-length header and we're using HTTP/1.1.
+ $request->setHeader('Transfer-Encoding', 'chunked');
+ $request->removeHeader('Content-Length');
+ }
+ }
+
+ private function addExpectHeader(
+ RequestInterface $request,
+ StreamInterface $body
+ ) {
+ // Determine if the Expect header should be used
+ if ($request->hasHeader('Expect')) {
+ return;
+ }
+
+ $expect = $request->getConfig()['expect'];
+
+ // Return if disabled or if you're not using HTTP/1.1
+ if ($expect === false || $request->getProtocolVersion() !== '1.1') {
+ return;
+ }
+
+ // The expect header is unconditionally enabled
+ if ($expect === true) {
+ $request->setHeader('Expect', '100-Continue');
+ return;
+ }
+
+ // By default, send the expect header when the payload is > 1mb
+ if ($expect === null) {
+ $expect = 1048576;
+ }
+
+ // Always add if the body cannot be rewound, the size cannot be
+ // determined, or the size is greater than the cutoff threshold
+ $size = $body->getSize();
+ if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
+ $request->setHeader('Expect', '100-Continue');
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php
new file mode 100644
index 0000000..ff99226
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Redirect.php
@@ -0,0 +1,176 @@
+<?php
+namespace GuzzleHttp\Subscriber;
+
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Exception\BadResponseException;
+use GuzzleHttp\Exception\CouldNotRewindStreamException;
+use GuzzleHttp\Exception\TooManyRedirectsException;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\Url;
+
+/**
+ * Subscriber used to implement HTTP redirects.
+ *
+ * **Request options**
+ *
+ * - redirect: Associative array containing the 'max', 'strict', and 'referer'
+ * keys.
+ *
+ * - max: Maximum number of redirects allowed per-request
+ * - strict: You can use strict redirects by setting this value to ``true``.
+ * Strict redirects adhere to strict RFC compliant redirection (e.g.,
+ * redirect POST with POST) vs doing what most clients do (e.g., redirect
+ * POST request with a GET request).
+ * - referer: Set to true to automatically add the "Referer" header when a
+ * redirect request is sent.
+ * - protocols: Array of allowed protocols. Defaults to 'http' and 'https'.
+ * When a redirect attempts to utilize a protocol that is not white listed,
+ * an exception is thrown.
+ */
+class Redirect implements SubscriberInterface
+{
+ public function getEvents()
+ {
+ return ['complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE]];
+ }
+
+ /**
+ * Rewind the entity body of the request if needed
+ *
+ * @param RequestInterface $redirectRequest
+ * @throws CouldNotRewindStreamException
+ */
+ public static function rewindEntityBody(RequestInterface $redirectRequest)
+ {
+ // Rewind the entity body of the request if needed
+ if ($body = $redirectRequest->getBody()) {
+ // Only rewind the body if some of it has been read already, and
+ // throw an exception if the rewind fails
+ if ($body->tell() && !$body->seek(0)) {
+ throw new CouldNotRewindStreamException(
+ 'Unable to rewind the non-seekable request body after redirecting',
+ $redirectRequest
+ );
+ }
+ }
+ }
+
+ /**
+ * Called when a request receives a redirect response
+ *
+ * @param CompleteEvent $event Event emitted
+ * @throws TooManyRedirectsException
+ */
+ public function onComplete(CompleteEvent $event)
+ {
+ $response = $event->getResponse();
+
+ if (substr($response->getStatusCode(), 0, 1) != '3'
+ || !$response->hasHeader('Location')
+ ) {
+ return;
+ }
+
+ $request = $event->getRequest();
+ $config = $request->getConfig();
+
+ // Increment the redirect and initialize the redirect state.
+ if ($redirectCount = $config['redirect_count']) {
+ $config['redirect_count'] = ++$redirectCount;
+ } else {
+ $config['redirect_scheme'] = $request->getScheme();
+ $config['redirect_count'] = $redirectCount = 1;
+ }
+
+ $max = $config->getPath('redirect/max') ?: 5;
+
+ if ($redirectCount > $max) {
+ throw new TooManyRedirectsException(
+ "Will not follow more than {$redirectCount} redirects",
+ $request
+ );
+ }
+
+ $this->modifyRedirectRequest($request, $response);
+ $event->retry();
+ }
+
+ private function modifyRedirectRequest(
+ RequestInterface $request,
+ ResponseInterface $response
+ ) {
+ $config = $request->getConfig();
+ $protocols = $config->getPath('redirect/protocols') ?: ['http', 'https'];
+
+ // Use a GET request if this is an entity enclosing request and we are
+ // not forcing RFC compliance, but rather emulating what all browsers
+ // would do.
+ $statusCode = $response->getStatusCode();
+ if ($statusCode == 303 ||
+ ($statusCode <= 302 && $request->getBody() && !$config->getPath('redirect/strict'))
+ ) {
+ $request->setMethod('GET');
+ $request->setBody(null);
+ }
+
+ $previousUrl = $request->getUrl();
+ $this->setRedirectUrl($request, $response, $protocols);
+ $this->rewindEntityBody($request);
+
+ // Add the Referer header if it is told to do so and only
+ // add the header if we are not redirecting from https to http.
+ if ($config->getPath('redirect/referer')
+ && ($request->getScheme() == 'https' || $request->getScheme() == $config['redirect_scheme'])
+ ) {
+ $url = Url::fromString($previousUrl);
+ $url->setUsername(null);
+ $url->setPassword(null);
+ $request->setHeader('Referer', (string) $url);
+ } else {
+ $request->removeHeader('Referer');
+ }
+ }
+
+ /**
+ * Set the appropriate URL on the request based on the location header
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @param array $protocols
+ */
+ private function setRedirectUrl(
+ RequestInterface $request,
+ ResponseInterface $response,
+ array $protocols
+ ) {
+ $location = $response->getHeader('Location');
+ $location = Url::fromString($location);
+
+ // Combine location with the original URL if it is not absolute.
+ if (!$location->isAbsolute()) {
+ $originalUrl = Url::fromString($request->getUrl());
+ // Remove query string parameters and just take what is present on
+ // the redirect Location header
+ $originalUrl->getQuery()->clear();
+ $location = $originalUrl->combine($location);
+ }
+
+ // Ensure that the redirect URL is allowed based on the protocols.
+ if (!in_array($location->getScheme(), $protocols)) {
+ throw new BadResponseException(
+ sprintf(
+ 'Redirect URL, %s, does not use one of the allowed redirect protocols: %s',
+ $location,
+ implode(', ', $protocols)
+ ),
+ $request,
+ $response
+ );
+ }
+
+ $request->setUrl($location);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/ToArrayInterface.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/ToArrayInterface.php
new file mode 100644
index 0000000..d57c022
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/ToArrayInterface.php
@@ -0,0 +1,15 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * An object that can be represented as an array
+ */
+interface ToArrayInterface
+{
+ /**
+ * Get the array representation of an object
+ *
+ * @return array
+ */
+ public function toArray();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Transaction.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Transaction.php
new file mode 100644
index 0000000..30a3f94
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Transaction.php
@@ -0,0 +1,103 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Represents the relationship between a client, request, and response.
+ *
+ * You can access the request, response, and client using their corresponding
+ * public properties.
+ */
+class Transaction
+{
+ /**
+ * HTTP client used to transfer the request.
+ *
+ * @var ClientInterface
+ */
+ public $client;
+
+ /**
+ * The request that is being sent.
+ *
+ * @var RequestInterface
+ */
+ public $request;
+
+ /**
+ * The response associated with the transaction. A response will not be
+ * present when a networking error occurs or an error occurs before sending
+ * the request.
+ *
+ * @var ResponseInterface|null
+ */
+ public $response;
+
+ /**
+ * Exception associated with the transaction. If this exception is present
+ * when processing synchronous or future commands, then it is thrown. When
+ * intercepting a failed transaction, you MUST set this value to null in
+ * order to prevent the exception from being thrown.
+ *
+ * @var \Exception
+ */
+ public $exception;
+
+ /**
+ * Associative array of handler specific transfer statistics and custom
+ * key value pair information. When providing similar information, handlers
+ * should follow the same key value pair naming conventions as PHP's
+ * curl_getinfo() (http://php.net/manual/en/function.curl-getinfo.php).
+ *
+ * @var array
+ */
+ public $transferInfo = [];
+
+ /**
+ * The number of transaction retries.
+ *
+ * @var int
+ */
+ public $retries = 0;
+
+ /**
+ * The transaction's current state.
+ *
+ * @var string
+ */
+ public $state;
+
+ /**
+ * Whether or not this is a future transaction. This value should not be
+ * changed after the future is constructed.
+ *
+ * @var bool
+ */
+ public $future;
+
+ /**
+ * The number of state transitions that this transaction has been through.
+ *
+ * @var int
+ * @internal This is for internal use only. If you modify this, then you
+ * are asking for trouble.
+ */
+ public $_transitionCount = 0;
+
+ /**
+ * @param ClientInterface $client Client that is used to send the requests
+ * @param RequestInterface $request Request to send
+ * @param bool $future Whether or not this is a future request.
+ */
+ public function __construct(
+ ClientInterface $client,
+ RequestInterface $request,
+ $future = false
+ ) {
+ $this->client = $client;
+ $this->request = $request;
+ $this->_future = $future;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/UriTemplate.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/UriTemplate.php
new file mode 100644
index 0000000..55dfeb5
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/UriTemplate.php
@@ -0,0 +1,241 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Expands URI templates. Userland implementation of PECL uri_template.
+ *
+ * @link http://tools.ietf.org/html/rfc6570
+ */
+class UriTemplate
+{
+ /** @var string URI template */
+ private $template;
+
+ /** @var array Variables to use in the template expansion */
+ private $variables;
+
+ /** @var array Hash for quick operator lookups */
+ private static $operatorHash = array(
+ '' => array('prefix' => '', 'joiner' => ',', 'query' => false),
+ '+' => array('prefix' => '', 'joiner' => ',', 'query' => false),
+ '#' => array('prefix' => '#', 'joiner' => ',', 'query' => false),
+ '.' => array('prefix' => '.', 'joiner' => '.', 'query' => false),
+ '/' => array('prefix' => '/', 'joiner' => '/', 'query' => false),
+ ';' => array('prefix' => ';', 'joiner' => ';', 'query' => true),
+ '?' => array('prefix' => '?', 'joiner' => '&', 'query' => true),
+ '&' => array('prefix' => '&', 'joiner' => '&', 'query' => true)
+ );
+
+ /** @var array Delimiters */
+ private static $delims = array(':', '/', '?', '#', '[', ']', '@', '!', '$',
+ '&', '\'', '(', ')', '*', '+', ',', ';', '=');
+
+ /** @var array Percent encoded delimiters */
+ private static $delimsPct = array('%3A', '%2F', '%3F', '%23', '%5B', '%5D',
+ '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
+ '%3B', '%3D');
+
+ public function expand($template, array $variables)
+ {
+ if (false === strpos($template, '{')) {
+ return $template;
+ }
+
+ $this->template = $template;
+ $this->variables = $variables;
+
+ return preg_replace_callback(
+ '/\{([^\}]+)\}/',
+ [$this, 'expandMatch'],
+ $this->template
+ );
+ }
+
+ /**
+ * Parse an expression into parts
+ *
+ * @param string $expression Expression to parse
+ *
+ * @return array Returns an associative array of parts
+ */
+ private function parseExpression($expression)
+ {
+ $result = array();
+
+ if (isset(self::$operatorHash[$expression[0]])) {
+ $result['operator'] = $expression[0];
+ $expression = substr($expression, 1);
+ } else {
+ $result['operator'] = '';
+ }
+
+ foreach (explode(',', $expression) as $value) {
+ $value = trim($value);
+ $varspec = array();
+ if ($colonPos = strpos($value, ':')) {
+ $varspec['value'] = substr($value, 0, $colonPos);
+ $varspec['modifier'] = ':';
+ $varspec['position'] = (int) substr($value, $colonPos + 1);
+ } elseif (substr($value, -1) == '*') {
+ $varspec['modifier'] = '*';
+ $varspec['value'] = substr($value, 0, -1);
+ } else {
+ $varspec['value'] = (string) $value;
+ $varspec['modifier'] = '';
+ }
+ $result['values'][] = $varspec;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Process an expansion
+ *
+ * @param array $matches Matches met in the preg_replace_callback
+ *
+ * @return string Returns the replacement string
+ */
+ private function expandMatch(array $matches)
+ {
+ static $rfc1738to3986 = array('+' => '%20', '%7e' => '~');
+
+ $replacements = array();
+ $parsed = self::parseExpression($matches[1]);
+ $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
+ $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
+ $useQuery = self::$operatorHash[$parsed['operator']]['query'];
+
+ foreach ($parsed['values'] as $value) {
+
+ if (!isset($this->variables[$value['value']])) {
+ continue;
+ }
+
+ $variable = $this->variables[$value['value']];
+ $actuallyUseQuery = $useQuery;
+ $expanded = '';
+
+ if (is_array($variable)) {
+
+ $isAssoc = $this->isAssoc($variable);
+ $kvp = array();
+ foreach ($variable as $key => $var) {
+
+ if ($isAssoc) {
+ $key = rawurlencode($key);
+ $isNestedArray = is_array($var);
+ } else {
+ $isNestedArray = false;
+ }
+
+ if (!$isNestedArray) {
+ $var = rawurlencode($var);
+ if ($parsed['operator'] == '+' ||
+ $parsed['operator'] == '#'
+ ) {
+ $var = $this->decodeReserved($var);
+ }
+ }
+
+ if ($value['modifier'] == '*') {
+ if ($isAssoc) {
+ if ($isNestedArray) {
+ // Nested arrays must allow for deeply nested
+ // structures.
+ $var = strtr(
+ http_build_query([$key => $var]),
+ $rfc1738to3986
+ );
+ } else {
+ $var = $key . '=' . $var;
+ }
+ } elseif ($key > 0 && $actuallyUseQuery) {
+ $var = $value['value'] . '=' . $var;
+ }
+ }
+
+ $kvp[$key] = $var;
+ }
+
+ if (empty($variable)) {
+ $actuallyUseQuery = false;
+ } elseif ($value['modifier'] == '*') {
+ $expanded = implode($joiner, $kvp);
+ if ($isAssoc) {
+ // Don't prepend the value name when using the explode
+ // modifier with an associative array.
+ $actuallyUseQuery = false;
+ }
+ } else {
+ if ($isAssoc) {
+ // When an associative array is encountered and the
+ // explode modifier is not set, then the result must be
+ // a comma separated list of keys followed by their
+ // respective values.
+ foreach ($kvp as $k => &$v) {
+ $v = $k . ',' . $v;
+ }
+ }
+ $expanded = implode(',', $kvp);
+ }
+
+ } else {
+ if ($value['modifier'] == ':') {
+ $variable = substr($variable, 0, $value['position']);
+ }
+ $expanded = rawurlencode($variable);
+ if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
+ $expanded = $this->decodeReserved($expanded);
+ }
+ }
+
+ if ($actuallyUseQuery) {
+ if (!$expanded && $joiner != '&') {
+ $expanded = $value['value'];
+ } else {
+ $expanded = $value['value'] . '=' . $expanded;
+ }
+ }
+
+ $replacements[] = $expanded;
+ }
+
+ $ret = implode($joiner, $replacements);
+ if ($ret && $prefix) {
+ return $prefix . $ret;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Determines if an array is associative.
+ *
+ * This makes the assumption that input arrays are sequences or hashes.
+ * This assumption is a tradeoff for accuracy in favor of speed, but it
+ * should work in almost every case where input is supplied for a URI
+ * template.
+ *
+ * @param array $array Array to check
+ *
+ * @return bool
+ */
+ private function isAssoc(array $array)
+ {
+ return $array && array_keys($array)[0] !== 0;
+ }
+
+ /**
+ * Removes percent encoding on reserved characters (used with + and #
+ * modifiers).
+ *
+ * @param string $string String to fix
+ *
+ * @return string
+ */
+ private function decodeReserved($string)
+ {
+ return str_replace(self::$delimsPct, self::$delims, $string);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Url.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Url.php
new file mode 100644
index 0000000..637f60c
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Url.php
@@ -0,0 +1,595 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Ring\Core;
+
+/**
+ * Parses and generates URLs based on URL parts
+ */
+class Url
+{
+ private $scheme;
+ private $host;
+ private $port;
+ private $username;
+ private $password;
+ private $path = '';
+ private $fragment;
+ private static $defaultPorts = ['http' => 80, 'https' => 443, 'ftp' => 21];
+ private static $pathPattern = '/[^a-zA-Z0-9\-\._~!\$&\'\(\)\*\+,;=%:@\/]+|%(?![A-Fa-f0-9]{2})/';
+ private static $queryPattern = '/[^a-zA-Z0-9\-\._~!\$\'\(\)\*\+,;%:@\/\?=&]+|%(?![A-Fa-f0-9]{2})/';
+ /** @var Query|string Query part of the URL */
+ private $query;
+
+ /**
+ * Factory method to create a new URL from a URL string
+ *
+ * @param string $url Full URL used to create a Url object
+ *
+ * @return Url
+ * @throws \InvalidArgumentException
+ */
+ public static function fromString($url)
+ {
+ static $defaults = ['scheme' => null, 'host' => null,
+ 'path' => null, 'port' => null, 'query' => null,
+ 'user' => null, 'pass' => null, 'fragment' => null];
+
+ if (false === ($parts = parse_url($url))) {
+ throw new \InvalidArgumentException('Unable to parse malformed '
+ . 'url: ' . $url);
+ }
+
+ $parts += $defaults;
+
+ // Convert the query string into a Query object
+ if ($parts['query'] || 0 !== strlen($parts['query'])) {
+ $parts['query'] = Query::fromString($parts['query']);
+ }
+
+ return new static($parts['scheme'], $parts['host'], $parts['user'],
+ $parts['pass'], $parts['port'], $parts['path'], $parts['query'],
+ $parts['fragment']);
+ }
+
+ /**
+ * Build a URL from parse_url parts. The generated URL will be a relative
+ * URL if a scheme or host are not provided.
+ *
+ * @param array $parts Array of parse_url parts
+ *
+ * @return string
+ */
+ public static function buildUrl(array $parts)
+ {
+ $url = $scheme = '';
+
+ if (!empty($parts['scheme'])) {
+ $scheme = $parts['scheme'];
+ $url .= $scheme . ':';
+ }
+
+ if (!empty($parts['host'])) {
+ $url .= '//';
+ if (isset($parts['user'])) {
+ $url .= $parts['user'];
+ if (isset($parts['pass'])) {
+ $url .= ':' . $parts['pass'];
+ }
+ $url .= '@';
+ }
+
+ $url .= $parts['host'];
+
+ // Only include the port if it is not the default port of the scheme
+ if (isset($parts['port']) &&
+ (!isset(self::$defaultPorts[$scheme]) ||
+ $parts['port'] != self::$defaultPorts[$scheme])
+ ) {
+ $url .= ':' . $parts['port'];
+ }
+ }
+
+ // Add the path component if present
+ if (isset($parts['path']) && strlen($parts['path'])) {
+ // Always ensure that the path begins with '/' if set and something
+ // is before the path
+ if (!empty($parts['host']) && $parts['path'][0] != '/') {
+ $url .= '/';
+ }
+ $url .= $parts['path'];
+ }
+
+ // Add the query string if present
+ if (isset($parts['query'])) {
+ $queryStr = (string) $parts['query'];
+ if ($queryStr || $queryStr === '0') {
+ $url .= '?' . $queryStr;
+ }
+ }
+
+ // Ensure that # is only added to the url if fragment contains anything.
+ if (isset($parts['fragment'])) {
+ $url .= '#' . $parts['fragment'];
+ }
+
+ return $url;
+ }
+
+ /**
+ * Create a new URL from URL parts
+ *
+ * @param string $scheme Scheme of the URL
+ * @param string $host Host of the URL
+ * @param string $username Username of the URL
+ * @param string $password Password of the URL
+ * @param int $port Port of the URL
+ * @param string $path Path of the URL
+ * @param Query|array|string $query Query string of the URL
+ * @param string $fragment Fragment of the URL
+ */
+ public function __construct(
+ $scheme,
+ $host,
+ $username = null,
+ $password = null,
+ $port = null,
+ $path = null,
+ $query = null,
+ $fragment = null
+ ) {
+ $this->scheme = strtolower($scheme);
+ $this->host = $host;
+ $this->port = $port;
+ $this->username = $username;
+ $this->password = $password;
+ $this->fragment = $fragment;
+
+ if ($query) {
+ $this->setQuery($query);
+ }
+
+ $this->setPath($path);
+ }
+
+ /**
+ * Clone the URL
+ */
+ public function __clone()
+ {
+ if ($this->query instanceof Query) {
+ $this->query = clone $this->query;
+ }
+ }
+
+ /**
+ * Returns the URL as a URL string
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return static::buildUrl($this->getParts());
+ }
+
+ /**
+ * Get the parts of the URL as an array
+ *
+ * @return array
+ */
+ public function getParts()
+ {
+ return array(
+ 'scheme' => $this->scheme,
+ 'user' => $this->username,
+ 'pass' => $this->password,
+ 'host' => $this->host,
+ 'port' => $this->port,
+ 'path' => $this->path,
+ 'query' => $this->query,
+ 'fragment' => $this->fragment,
+ );
+ }
+
+ /**
+ * Set the host of the request.
+ *
+ * @param string $host Host to set (e.g. www.yahoo.com, yahoo.com)
+ *
+ * @return Url
+ */
+ public function setHost($host)
+ {
+ if (strpos($host, ':') === false) {
+ $this->host = $host;
+ } else {
+ list($host, $port) = explode(':', $host);
+ $this->host = $host;
+ $this->setPort($port);
+ }
+ }
+
+ /**
+ * Get the host part of the URL
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->host;
+ }
+
+ /**
+ * Set the scheme part of the URL (http, https, ftp, etc.)
+ *
+ * @param string $scheme Scheme to set
+ */
+ public function setScheme($scheme)
+ {
+ // Remove the default port if one is specified
+ if ($this->port
+ && isset(self::$defaultPorts[$this->scheme])
+ && self::$defaultPorts[$this->scheme] == $this->port
+ ) {
+ $this->port = null;
+ }
+
+ $this->scheme = strtolower($scheme);
+ }
+
+ /**
+ * Get the scheme part of the URL
+ *
+ * @return string
+ */
+ public function getScheme()
+ {
+ return $this->scheme;
+ }
+
+ /**
+ * Set the port part of the URL
+ *
+ * @param int $port Port to set
+ */
+ public function setPort($port)
+ {
+ $this->port = $port;
+ }
+
+ /**
+ * Get the port part of the URl.
+ *
+ * If no port was set, this method will return the default port for the
+ * scheme of the URI.
+ *
+ * @return int|null
+ */
+ public function getPort()
+ {
+ if ($this->port) {
+ return $this->port;
+ } elseif (isset(self::$defaultPorts[$this->scheme])) {
+ return self::$defaultPorts[$this->scheme];
+ }
+
+ return null;
+ }
+
+ /**
+ * Set the path part of the URL.
+ *
+ * The provided URL is URL encoded as necessary.
+ *
+ * @param string $path Path string to set
+ */
+ public function setPath($path)
+ {
+ $this->path = self::encodePath($path);
+ }
+
+ /**
+ * Removes dot segments from a URL
+ * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
+ */
+ public function removeDotSegments()
+ {
+ static $noopPaths = ['' => true, '/' => true, '*' => true];
+ static $ignoreSegments = ['.' => true, '..' => true];
+
+ if (isset($noopPaths[$this->path])) {
+ return;
+ }
+
+ $results = [];
+ $segments = $this->getPathSegments();
+ foreach ($segments as $segment) {
+ if ($segment == '..') {
+ array_pop($results);
+ } elseif (!isset($ignoreSegments[$segment])) {
+ $results[] = $segment;
+ }
+ }
+
+ $newPath = implode('/', $results);
+
+ // Add the leading slash if necessary
+ if (substr($this->path, 0, 1) === '/' &&
+ substr($newPath, 0, 1) !== '/'
+ ) {
+ $newPath = '/' . $newPath;
+ }
+
+ // Add the trailing slash if necessary
+ if ($newPath != '/' && isset($ignoreSegments[end($segments)])) {
+ $newPath .= '/';
+ }
+
+ $this->path = $newPath;
+ }
+
+ /**
+ * Add a relative path to the currently set path.
+ *
+ * @param string $relativePath Relative path to add
+ */
+ public function addPath($relativePath)
+ {
+ if ($relativePath != '/' &&
+ is_string($relativePath) &&
+ strlen($relativePath) > 0
+ ) {
+ // Add a leading slash if needed
+ if ($relativePath[0] !== '/' &&
+ substr($this->path, -1, 1) !== '/'
+ ) {
+ $relativePath = '/' . $relativePath;
+ }
+
+ $this->setPath($this->path . $relativePath);
+ }
+ }
+
+ /**
+ * Get the path part of the URL
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->path;
+ }
+
+ /**
+ * Get the path segments of the URL as an array
+ *
+ * @return array
+ */
+ public function getPathSegments()
+ {
+ return explode('/', $this->path);
+ }
+
+ /**
+ * Set the password part of the URL
+ *
+ * @param string $password Password to set
+ */
+ public function setPassword($password)
+ {
+ $this->password = $password;
+ }
+
+ /**
+ * Get the password part of the URL
+ *
+ * @return null|string
+ */
+ public function getPassword()
+ {
+ return $this->password;
+ }
+
+ /**
+ * Set the username part of the URL
+ *
+ * @param string $username Username to set
+ */
+ public function setUsername($username)
+ {
+ $this->username = $username;
+ }
+
+ /**
+ * Get the username part of the URl
+ *
+ * @return null|string
+ */
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ /**
+ * Get the query part of the URL as a Query object
+ *
+ * @return Query
+ */
+ public function getQuery()
+ {
+ // Convert the query string to a query object if not already done.
+ if (!$this->query instanceof Query) {
+ $this->query = $this->query === null
+ ? new Query()
+ : Query::fromString($this->query);
+ }
+
+ return $this->query;
+ }
+
+ /**
+ * Set the query part of the URL.
+ *
+ * You may provide a query string as a string and pass $rawString as true
+ * to provide a query string that is not parsed until a call to getQuery()
+ * is made. Setting a raw query string will still encode invalid characters
+ * in a query string.
+ *
+ * @param Query|string|array $query Query string value to set. Can
+ * be a string that will be parsed into a Query object, an array
+ * of key value pairs, or a Query object.
+ * @param bool $rawString Set to true when providing a raw query string.
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setQuery($query, $rawString = false)
+ {
+ if ($query instanceof Query) {
+ $this->query = $query;
+ } elseif (is_string($query)) {
+ if (!$rawString) {
+ $this->query = Query::fromString($query);
+ } else {
+ // Ensure the query does not have illegal characters.
+ $this->query = preg_replace_callback(
+ self::$queryPattern,
+ [__CLASS__, 'encodeMatch'],
+ $query
+ );
+ }
+
+ } elseif (is_array($query)) {
+ $this->query = new Query($query);
+ } else {
+ throw new \InvalidArgumentException('Query must be a Query, '
+ . 'array, or string. Got ' . Core::describeType($query));
+ }
+ }
+
+ /**
+ * Get the fragment part of the URL
+ *
+ * @return null|string
+ */
+ public function getFragment()
+ {
+ return $this->fragment;
+ }
+
+ /**
+ * Set the fragment part of the URL
+ *
+ * @param string $fragment Fragment to set
+ */
+ public function setFragment($fragment)
+ {
+ $this->fragment = $fragment;
+ }
+
+ /**
+ * Check if this is an absolute URL
+ *
+ * @return bool
+ */
+ public function isAbsolute()
+ {
+ return $this->scheme && $this->host;
+ }
+
+ /**
+ * Combine the URL with another URL and return a new URL instance.
+ *
+ * Follows the rules specific in RFC 3986 section 5.4.
+ *
+ * @param string $url Relative URL to combine with
+ *
+ * @return Url
+ * @throws \InvalidArgumentException
+ * @link http://tools.ietf.org/html/rfc3986#section-5.4
+ */
+ public function combine($url)
+ {
+ $url = static::fromString($url);
+
+ // Use the more absolute URL as the base URL
+ if (!$this->isAbsolute() && $url->isAbsolute()) {
+ $url = $url->combine($this);
+ }
+
+ $parts = $url->getParts();
+
+ // Passing a URL with a scheme overrides everything
+ if ($parts['scheme']) {
+ return clone $url;
+ }
+
+ // Setting a host overrides the entire rest of the URL
+ if ($parts['host']) {
+ return new static(
+ $this->scheme,
+ $parts['host'],
+ $parts['user'],
+ $parts['pass'],
+ $parts['port'],
+ $parts['path'],
+ $parts['query'] instanceof Query
+ ? clone $parts['query']
+ : $parts['query'],
+ $parts['fragment']
+ );
+ }
+
+ if (!$parts['path'] && $parts['path'] !== '0') {
+ // The relative URL has no path, so check if it is just a query
+ $path = $this->path ?: '';
+ $query = $parts['query'] ?: $this->query;
+ } else {
+ $query = $parts['query'];
+ if ($parts['path'][0] == '/' || !$this->path) {
+ // Overwrite the existing path if the rel path starts with "/"
+ $path = $parts['path'];
+ } else {
+ // If the relative URL does not have a path or the base URL
+ // path does not end in a "/" then overwrite the existing path
+ // up to the last "/"
+ $path = substr($this->path, 0, strrpos($this->path, '/') + 1) . $parts['path'];
+ }
+ }
+
+ $result = new self(
+ $this->scheme,
+ $this->host,
+ $this->username,
+ $this->password,
+ $this->port,
+ $path,
+ $query instanceof Query ? clone $query : $query,
+ $parts['fragment']
+ );
+
+ if ($path) {
+ $result->removeDotSegments();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Encodes the path part of a URL without double-encoding percent-encoded
+ * key value pairs.
+ *
+ * @param string $path Path to encode
+ *
+ * @return string
+ */
+ public static function encodePath($path)
+ {
+ static $cb = [__CLASS__, 'encodeMatch'];
+ return preg_replace_callback(self::$pathPattern, $cb, $path);
+ }
+
+ private static function encodeMatch(array $match)
+ {
+ return rawurlencode($match[0]);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/guzzle/src/Utils.php b/public/system/storage/vendor/guzzlehttp/guzzle/src/Utils.php
new file mode 100644
index 0000000..1754719
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/guzzle/src/Utils.php
@@ -0,0 +1,215 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Ring\Client\CurlHandler;
+use GuzzleHttp\Ring\Client\CurlMultiHandler;
+use GuzzleHttp\Ring\Client\StreamHandler;
+use GuzzleHttp\Ring\Client\Middleware;
+
+/**
+ * Utility methods used throughout Guzzle.
+ */
+final class Utils
+{
+ /**
+ * Gets a value from an array using a path syntax to retrieve nested data.
+ *
+ * This method does not allow for keys that contain "/". You must traverse
+ * the array manually or using something more advanced like JMESPath to
+ * work with keys that contain "/".
+ *
+ * // Get the bar key of a set of nested arrays.
+ * // This is equivalent to $collection['foo']['baz']['bar'] but won't
+ * // throw warnings for missing keys.
+ * GuzzleHttp\get_path($data, 'foo/baz/bar');
+ *
+ * @param array $data Data to retrieve values from
+ * @param string $path Path to traverse and retrieve a value from
+ *
+ * @return mixed|null
+ */
+ public static function getPath($data, $path)
+ {
+ $path = explode('/', $path);
+
+ while (null !== ($part = array_shift($path))) {
+ if (!is_array($data) || !isset($data[$part])) {
+ return null;
+ }
+ $data = $data[$part];
+ }
+
+ return $data;
+ }
+
+ /**
+ * Set a value in a nested array key. Keys will be created as needed to set
+ * the value.
+ *
+ * This function does not support keys that contain "/" or "[]" characters
+ * because these are special tokens used when traversing the data structure.
+ * A value may be prepended to an existing array by using "[]" as the final
+ * key of a path.
+ *
+ * GuzzleHttp\get_path($data, 'foo/baz'); // null
+ * GuzzleHttp\set_path($data, 'foo/baz/[]', 'a');
+ * GuzzleHttp\set_path($data, 'foo/baz/[]', 'b');
+ * GuzzleHttp\get_path($data, 'foo/baz');
+ * // Returns ['a', 'b']
+ *
+ * @param array $data Data to modify by reference
+ * @param string $path Path to set
+ * @param mixed $value Value to set at the key
+ *
+ * @throws \RuntimeException when trying to setPath using a nested path
+ * that travels through a scalar value.
+ */
+ public static function setPath(&$data, $path, $value)
+ {
+ $queue = explode('/', $path);
+ // Optimization for simple sets.
+ if (count($queue) === 1) {
+ $data[$path] = $value;
+ return;
+ }
+
+ $current =& $data;
+ while (null !== ($key = array_shift($queue))) {
+ if (!is_array($current)) {
+ throw new \RuntimeException("Trying to setPath {$path}, but "
+ . "{$key} is set and is not an array");
+ } elseif (!$queue) {
+ if ($key == '[]') {
+ $current[] = $value;
+ } else {
+ $current[$key] = $value;
+ }
+ } elseif (isset($current[$key])) {
+ $current =& $current[$key];
+ } else {
+ $current[$key] = [];
+ $current =& $current[$key];
+ }
+ }
+ }
+
+ /**
+ * Expands a URI template
+ *
+ * @param string $template URI template
+ * @param array $variables Template variables
+ *
+ * @return string
+ */
+ public static function uriTemplate($template, array $variables)
+ {
+ if (function_exists('\\uri_template')) {
+ return \uri_template($template, $variables);
+ }
+
+ static $uriTemplate;
+ if (!$uriTemplate) {
+ $uriTemplate = new UriTemplate();
+ }
+
+ return $uriTemplate->expand($template, $variables);
+ }
+
+ /**
+ * Wrapper for JSON decode that implements error detection with helpful
+ * error messages.
+ *
+ * @param string $json JSON data to parse
+ * @param bool $assoc When true, returned objects will be converted
+ * into associative arrays.
+ * @param int $depth User specified recursion depth.
+ * @param int $options Bitmask of JSON decode options.
+ *
+ * @return mixed
+ * @throws \InvalidArgumentException if the JSON cannot be parsed.
+ * @link http://www.php.net/manual/en/function.json-decode.php
+ */
+ public static function jsonDecode($json, $assoc = false, $depth = 512, $options = 0)
+ {
+ if ($json === '' || $json === null) {
+ return null;
+ }
+
+ static $jsonErrors = [
+ JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded',
+ JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH - Underflow or the modes mismatch',
+ JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR - Unexpected control character found',
+ JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX - Syntax error, malformed JSON',
+ JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8 - Malformed UTF-8 characters, possibly incorrectly encoded'
+ ];
+
+ $data = \json_decode($json, $assoc, $depth, $options);
+
+ if (JSON_ERROR_NONE !== json_last_error()) {
+ $last = json_last_error();
+ throw new \InvalidArgumentException(
+ 'Unable to parse JSON data: '
+ . (isset($jsonErrors[$last])
+ ? $jsonErrors[$last]
+ : 'Unknown error')
+ );
+ }
+
+ return $data;
+ }
+
+ /**
+ * Get the default User-Agent string to use with Guzzle
+ *
+ * @return string
+ */
+ public static function getDefaultUserAgent()
+ {
+ static $defaultAgent = '';
+ if (!$defaultAgent) {
+ $defaultAgent = 'Guzzle/' . ClientInterface::VERSION;
+ if (extension_loaded('curl')) {
+ $defaultAgent .= ' curl/' . curl_version()['version'];
+ }
+ $defaultAgent .= ' PHP/' . PHP_VERSION;
+ }
+
+ return $defaultAgent;
+ }
+
+ /**
+ * Create a default handler to use based on the environment
+ *
+ * @throws \RuntimeException if no viable Handler is available.
+ */
+ public static function getDefaultHandler()
+ {
+ $default = $future = null;
+
+ if (extension_loaded('curl')) {
+ $config = [
+ 'select_timeout' => getenv('GUZZLE_CURL_SELECT_TIMEOUT') ?: 1
+ ];
+ if ($maxHandles = getenv('GUZZLE_CURL_MAX_HANDLES')) {
+ $config['max_handles'] = $maxHandles;
+ }
+ if (function_exists('curl_reset')) {
+ $default = new CurlHandler();
+ $future = new CurlMultiHandler($config);
+ } else {
+ $default = new CurlMultiHandler($config);
+ }
+ }
+
+ if (ini_get('allow_url_fopen')) {
+ $default = !$default
+ ? new StreamHandler()
+ : Middleware::wrapStreaming($default, new StreamHandler());
+ } elseif (!$default) {
+ throw new \RuntimeException('Guzzle requires cURL, the '
+ . 'allow_url_fopen ini setting, or a custom HTTP handler.');
+ }
+
+ return $future ? Middleware::wrapFuture($default, $future) : $default;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/.gitignore b/public/system/storage/vendor/guzzlehttp/log-subscriber/.gitignore
new file mode 100644
index 0000000..c33d396
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/.gitignore
@@ -0,0 +1,6 @@
+.idea
+.DS_STORE
+coverage
+phpunit.xml
+composer.lock
+vendor/
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/.travis.yml b/public/system/storage/vendor/guzzlehttp/log-subscriber/.travis.yml
new file mode 100644
index 0000000..4355f26
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/.travis.yml
@@ -0,0 +1,13 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+before_script:
+ - composer self-update
+ - composer install --no-interaction --prefer-source --dev
+
+script: vendor/bin/phpunit
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/LICENSE b/public/system/storage/vendor/guzzlehttp/log-subscriber/LICENSE
new file mode 100644
index 0000000..71d3b78
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/README.rst b/public/system/storage/vendor/guzzlehttp/log-subscriber/README.rst
new file mode 100644
index 0000000..df7f8a0
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/README.rst
@@ -0,0 +1,151 @@
+=====================
+Guzzle Log Subscriber
+=====================
+
+The LogSubscriber logs HTTP requests and responses to a
+`PSR-3 logger <https://github.com/php-fig/log>`_, callable, resource returned
+by ``fopen()``, or by calling ``echo()``.
+
+Here's the simplest example of how it's used:
+
+.. code-block:: php
+
+ use GuzzleHttp\Client;
+ use GuzzleHttp\Subscriber\Log\LogSubscriber;
+
+ $client = new Client();
+ $client->getEmitter()->attach(new LogSubscriber());
+ $client->get('http://httpbin.org');
+
+Running the above example will echo a message using the
+`Apache Common Log Format (CLF) <http://httpd.apache.org/docs/1.3/logs.html#common>`_.
+
+::
+
+ [info] hostname Guzzle/5.0 curl/7.21.4 PHP/5.5.7 - [2014-03-01T22:48:13+00:00] "GET / HTTP/1.1" 200 7641
+
+.. note::
+
+ Because no logger is provided, the subscriber simply logs messages with
+ ``echo()``. This is the method used for logging if ``null`` is provided.
+
+Installing
+----------
+
+This project can be installed using Composer. Add the following to your
+composer.json:
+
+.. code-block:: javascript
+
+ {
+ "require": {
+ "guzzlehttp/log-subscriber": "~1.0"
+ }
+ }
+
+Using PSR-3 Loggers
+-------------------
+
+You can provide a PSR-3 logger to the constructor as well. The following
+example shows how the LogSubscriber can be combined with
+`Monolog <https://github.com/Seldaek/monolog>`_.
+
+.. code-block:: php
+
+ use GuzzleHttp\Client;
+ use GuzzleHttp\Subscriber\Log\LogSubscriber;
+ use Monolog\Logger;
+ use Monolog\Handler\StreamHandler;
+
+ // create a log channel
+ $log = new Logger('name');
+ $log->pushHandler(new StreamHandler('/path/to/your.log', Logger::WARNING));
+
+ $client = new Client();
+ $subscriber = new LogSubscriber($log);
+ $client->getEmitter()->attach($subscriber);
+
+Logging with a custom message format
+------------------------------------
+
+The LogSubscriber's constructor accepts a logger as the first argument and a
+message format string or a message formatter as the second argument. You could
+log the full HTTP request and Response message using the debug format via
+``GuzzleHttp\Subscriber\Log\Formatter::DEBUG``.
+
+.. code-block:: php
+
+ use GuzzleHttp\Subscriber\Log\LogSubscriber;
+ use GuzzleHttp\Subscriber\Log\Formatter;
+
+ // Log the full request and response messages using echo() calls.
+ $subscriber = new LogSubscriber(null, Formatter::DEBUG);
+
+Message Formatter
+~~~~~~~~~~~~~~~~~
+
+Included in this repository is a *message formatter*. The message formatter is
+used to format log messages for both requests and responses using a log
+template that uses variable substitution for string enclosed in braces
+(``{}``).
+
+The following variables are available in message formatter templates:
+
+{request}
+ Full HTTP request message
+
+{response}
+ Full HTTP response message
+
+{ts}
+ Timestamp
+
+{host}
+ Host of the request
+
+{method}
+ Method of the request
+
+{url}
+ URL of the request
+
+{protocol}
+ Request protocol
+
+{version}
+ Protocol version
+
+{resource}
+ Resource of the request (path + query + fragment)
+
+{hostname}
+ Hostname of the machine that sent the request
+
+{code}
+ Status code of the response (if available)
+
+{phrase}
+ Reason phrase of the response (if available)
+
+{error}
+ Any error messages (if available)
+
+{req_header_*}
+ Replace ``*`` with the lowercased name of a request header to add to the
+ message.
+
+{res_header_*}
+ Replace ``*`` with the lowercased name of a response header to add to the
+ message
+
+{req_headers}
+ Request headers as a string.
+
+{res_headers}
+ Response headers as a string.
+
+{req_body}
+ Request body as a string.
+
+{res_body}
+ Response body as a string.
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/composer.json b/public/system/storage/vendor/guzzlehttp/log-subscriber/composer.json
new file mode 100644
index 0000000..7bd183a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/composer.json
@@ -0,0 +1,30 @@
+{
+ "name": "guzzlehttp/log-subscriber",
+ "description": "Logs HTTP requests and responses as they are sent over the wire (Guzzle 4+)",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": ["plugin", "log", "guzzle"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "guzzlehttp/guzzle": "~4.0 | ~5.0",
+ "psr/log": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "autoload": {
+ "psr-4": { "GuzzleHttp\\Subscriber\\Log\\": "src/" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/phpunit.xml.dist b/public/system/storage/vendor/guzzlehttp/log-subscriber/phpunit.xml.dist
new file mode 100644
index 0000000..994e158
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/phpunit.xml.dist
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./vendor/autoload.php"
+ colors="true">
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/src/Formatter.php b/public/system/storage/vendor/guzzlehttp/log-subscriber/src/Formatter.php
new file mode 100644
index 0000000..610e4b1
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/src/Formatter.php
@@ -0,0 +1,179 @@
+<?php
+namespace GuzzleHttp\Subscriber\Log;
+
+use GuzzleHttp\Message\MessageInterface;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * Formats log messages using variable substitutions for requests, responses,
+ * and other transactional data.
+ *
+ * The following variable substitutions are supported:
+ *
+ * - {request}: Full HTTP request message
+ * - {response}: Full HTTP response message
+ * - {ts}: Timestamp
+ * - {host}: Host of the request
+ * - {method}: Method of the request
+ * - {url}: URL of the request
+ * - {host}: Host of the request
+ * - {protocol}: Request protocol
+ * - {version}: Protocol version
+ * - {resource}: Resource of the request (path + query + fragment)
+ * - {hostname}: Hostname of the machine that sent the request
+ * - {code}: Status code of the response (if available)
+ * - {phrase}: Reason phrase of the response (if available)
+ * - {error}: Any error messages (if available)
+ * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
+ * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
+ * - {req_headers}: Request headers
+ * - {res_headers}: Response headers
+ * - {req_body}: Request body
+ * - {res_body}: Response body
+ */
+class Formatter
+{
+ /**
+ * Apache Common Log Format.
+ * @link http://httpd.apache.org/docs/1.3/logs.html#common
+ * @var string
+ */
+ const CLF = "{hostname} {req_header_User-Agent} - [{ts}] \"{method} {resource} {protocol}/{version}\" {code} {res_header_Content-Length}";
+ const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
+ const SHORT = '[{ts}] "{method} {resource} {protocol}/{version}" {code}';
+
+ /** @var string Template used to format log messages */
+ private $template;
+
+ /**
+ * @param string $template Log message template
+ */
+ public function __construct($template = self::CLF)
+ {
+ $this->template = $template ?: self::CLF;
+ }
+
+ /**
+ * Returns a formatted message
+ *
+ * @param RequestInterface $request Request that was sent
+ * @param ResponseInterface $response Response that was received
+ * @param \Exception $error Exception that was received
+ * @param array $customData Associative array of custom template data
+ *
+ * @return string
+ */
+ public function format(
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ \Exception $error = null,
+ array $customData = []
+ ) {
+ $cache = $customData;
+
+ return preg_replace_callback(
+ '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
+ function (array $matches) use ($request, $response, $error, &$cache) {
+
+ if (isset($cache[$matches[1]])) {
+ return $cache[$matches[1]];
+ }
+
+ $result = '';
+ switch ($matches[1]) {
+ case 'request':
+ $result = $request;
+ break;
+ case 'response':
+ $result = $response;
+ break;
+ case 'req_headers':
+ $result = trim($request->getMethod() . ' '
+ . $request->getResource()) . ' HTTP/'
+ . $request->getProtocolVersion() . "\r\n"
+ . $this->headers($request);
+ break;
+ case 'res_headers':
+ $result = $response ?
+ sprintf(
+ 'HTTP/%s %d %s',
+ $response->getProtocolVersion(),
+ $response->getStatusCode(),
+ $response->getReasonPhrase()
+ ) . "\r\n" . $this->headers($response)
+ : 'NULL';
+ break;
+ case 'req_body':
+ $result = $request->getBody();
+ break;
+ case 'res_body':
+ $result = $response ? $response->getBody() : 'NULL';
+ break;
+ case 'ts':
+ $result = gmdate('c');
+ break;
+ case 'method':
+ $result = $request->getMethod();
+ break;
+ case 'url':
+ $result = $request->getUrl();
+ break;
+ case 'resource':
+ $result = $request->getResource();
+ break;
+ case 'req_version':
+ $result = $request->getProtocolVersion();
+ break;
+ case 'res_version':
+ $result = $response
+ ? $response->getProtocolVersion()
+ : 'NULL';
+ break;
+ case 'host':
+ $result = $request->getHost();
+ break;
+ case 'hostname':
+ $result = gethostname();
+ break;
+ case 'code':
+ $result = $response
+ ? $response->getStatusCode()
+ : 'NULL';
+ break;
+ case 'phrase':
+ $result = $response
+ ? $response->getReasonPhrase()
+ : 'NULL';
+ break;
+ case 'error':
+ $result = $error ? $error->getMessage() : 'NULL';
+ break;
+ default:
+ // handle prefixed dynamic headers
+ if (strpos($matches[1], 'req_header_') === 0) {
+ $result = $request->getHeader(substr($matches[1], 11));
+ } elseif (strpos($matches[1], 'res_header_') === 0) {
+ $result = $response
+ ? $response->getHeader(substr($matches[1], 11))
+ : 'NULL';
+ }
+ }
+
+ $cache[$matches[1]] = $result;
+ return $result;
+ },
+ $this->template
+ );
+ }
+
+ private function headers(MessageInterface $message)
+ {
+ $result = '';
+ foreach ($message->getHeaders() as $name => $values) {
+ $result .= $name . ': ' . implode(', ', $values) . "\r\n";
+ }
+
+ return trim($result);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/src/LogSubscriber.php b/public/system/storage/vendor/guzzlehttp/log-subscriber/src/LogSubscriber.php
new file mode 100644
index 0000000..cded5ad
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/src/LogSubscriber.php
@@ -0,0 +1,89 @@
+<?php
+namespace GuzzleHttp\Subscriber\Log;
+
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\ErrorEvent;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * Plugin class that will add request and response logging to an HTTP request.
+ *
+ * The log plugin uses a message formatter that allows custom messages via
+ * template variable substitution.
+ *
+ * @see MessageLogger for a list of available template variable substitutions
+ */
+class LogSubscriber implements SubscriberInterface
+{
+ /** @var LoggerInterface */
+ private $logger;
+
+ /** @var Formatter Formatter used to format log messages */
+ private $formatter;
+
+ /**
+ * @param LoggerInterface|callable|resource|null $logger Logger used to log
+ * messages. Pass a LoggerInterface to use a PSR-3 logger. Pass a
+ * callable to log messages to a function that accepts a string of
+ * data. Pass a resource returned from ``fopen()`` to log to an open
+ * resource. Pass null or leave empty to write log messages using
+ * ``echo()``.
+ * @param string|Formatter $formatter Formatter used to format log
+ * messages or a string representing a message formatter template.
+ */
+ public function __construct($logger = null, $formatter = null)
+ {
+ $this->logger = $logger instanceof LoggerInterface
+ ? $logger
+ : new SimpleLogger($logger);
+
+ $this->formatter = $formatter instanceof Formatter
+ ? $formatter
+ : new Formatter($formatter);
+ }
+
+ public function getEvents()
+ {
+ return [
+ // Fire after responses are verified (which trigger error events).
+ 'complete' => ['onComplete', RequestEvents::VERIFY_RESPONSE - 10],
+ 'error' => ['onError', RequestEvents::EARLY]
+ ];
+ }
+
+ public function onComplete(CompleteEvent $event)
+ {
+ $this->logger->log(
+ substr($event->getResponse()->getStatusCode(), 0, 1) == '2'
+ ? LogLevel::INFO
+ : LogLevel::WARNING,
+ $this->formatter->format(
+ $event->getRequest(),
+ $event->getResponse()
+ ), [
+ 'request' => $event->getRequest(),
+ 'response' => $event->getResponse()
+ ]
+ );
+ }
+
+ public function onError(ErrorEvent $event)
+ {
+ $ex = $event->getException();
+ $this->logger->log(
+ LogLevel::CRITICAL,
+ $this->formatter->format(
+ $event->getRequest(),
+ $event->getResponse(),
+ $ex
+ ), [
+ 'request' => $event->getRequest(),
+ 'response' => $event->getResponse(),
+ 'exception' => $ex
+ ]
+ );
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/src/SimpleLogger.php b/public/system/storage/vendor/guzzlehttp/log-subscriber/src/SimpleLogger.php
new file mode 100644
index 0000000..9ad25cf
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/src/SimpleLogger.php
@@ -0,0 +1,32 @@
+<?php
+namespace GuzzleHttp\Subscriber\Log;
+
+use Psr\Log\LoggerTrait;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Simple logger implementation that can write to a function, resource, or
+ * uses echo() if nothing is provided.
+ */
+class SimpleLogger implements LoggerInterface
+{
+ use LoggerTrait;
+
+ private $writeTo;
+
+ public function __construct($writeTo = null)
+ {
+ $this->writeTo = $writeTo;
+ }
+
+ public function log($level, $message, array $context = array())
+ {
+ if (is_resource($this->writeTo)) {
+ fwrite($this->writeTo, "[{$level}] {$message}\n");
+ } elseif (is_callable($this->writeTo)) {
+ call_user_func($this->writeTo, "[{$level}] {$message}\n");
+ } else {
+ echo "[{$level}] {$message}\n";
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/FormatterTest.php b/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/FormatterTest.php
new file mode 100644
index 0000000..a239255
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/FormatterTest.php
@@ -0,0 +1,90 @@
+<?php
+namespace GuzzleHttp\Tests\Subscriber\LogSubscriber;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Message\Request;
+use GuzzleHttp\Message\Response;
+use GuzzleHttp\Subscriber\Log\Formatter;
+
+/**
+ * @covers GuzzleHttp\Subscriber\Log\Formatter
+ */
+class FormatterTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCreatesWithClfByDefault()
+ {
+ $f = new Formatter();
+ $this->assertEquals(Formatter::CLF, $this->readAttribute($f, 'template'));
+ $f = new Formatter(null);
+ $this->assertEquals(Formatter::CLF, $this->readAttribute($f, 'template'));
+ }
+
+ public function testFormatsMessagesWithCustomData()
+ {
+ $f = new Formatter('{foo} - {method} - {code}');
+ $request = new Request('GET', '/');
+ $response = new Response(200);
+ $result = $f->format($request, $response, null, ['foo' => 'bar']);
+ $this->assertEquals('bar - GET - 200', $result);
+ }
+
+ public function testFormatsTimestamps()
+ {
+ $f = new Formatter('{ts}');
+ $request = new Request('GET', '/');
+ $result = $f->format($request);
+ // Ensure it matches this format: '2014-03-02T00:18:41+00:00';
+ $this->assertEquals(1, preg_match('/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}/', $result));
+ }
+
+ public function formatProvider()
+ {
+ $request = new Request('PUT', '/', ['x-test' => 'abc'], Stream::factory('foo'));
+ $response = new Response(200, ['X-Baz' => 'Bar'], Stream::factory('baz'));
+ $err = new RequestException('Test', $request, $response);
+
+ return [
+ ['{request}', [$request], (string) $request],
+ ['{response}', [$request, $response], (string) $response],
+ ['{request} {response}', [$request, $response], $request . ' ' . $response],
+ // Empty response yields no value
+ ['{request} {response}', [$request], $request . ' '],
+ ['{req_headers}', [$request], "PUT / HTTP/1.1\r\nx-test: abc"],
+ ['{res_headers}', [$request, $response], "HTTP/1.1 200 OK\r\nX-Baz: Bar"],
+ ['{res_headers}', [$request], 'NULL'],
+ ['{req_body}', [$request], 'foo'],
+ ['{res_body}', [$request, $response], 'baz'],
+ ['{res_body}', [$request], 'NULL'],
+ ['{method}', [$request], $request->getMethod()],
+ ['{url}', [$request], $request->getUrl()],
+ ['{resource}', [$request], $request->getResource()],
+ ['{req_version}', [$request], $request->getProtocolVersion()],
+ ['{res_version}', [$request, $response], $response->getProtocolVersion()],
+ ['{res_version}', [$request], 'NULL'],
+ ['{host}', [$request], $request->getHost()],
+ ['{hostname}', [$request, $response], gethostname()],
+ ['{hostname}{hostname}', [$request, $response], gethostname() . gethostname()],
+ ['{code}', [$request, $response], $response->getStatusCode()],
+ ['{code}', [$request], 'NULL'],
+ ['{phrase}', [$request, $response], $response->getReasonPhrase()],
+ ['{phrase}', [$request], 'NULL'],
+ ['{error}', [$request, $response, $err], 'Test'],
+ ['{error}', [$request], 'NULL'],
+ ['{req_header_x-test}', [$request], 'abc'],
+ ['{req_header_x-not}', [$request], ''],
+ ['{res_header_X-Baz}', [$request, $response], 'Bar'],
+ ['{res_header_x-not}', [$request, $response], ''],
+ ['{res_header_X-Baz}', [$request], 'NULL'],
+ ];
+ }
+
+ /**
+ * @dataProvider formatProvider
+ */
+ public function testFormatsMessages($template, $args, $result)
+ {
+ $f = new Formatter($template);
+ $this->assertEquals((string) $result, call_user_func_array(array($f, 'format'), $args));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/LogSubscriberTest.php b/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/LogSubscriberTest.php
new file mode 100644
index 0000000..618dfcc
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/LogSubscriberTest.php
@@ -0,0 +1,76 @@
+<?php
+namespace GuzzleHttp\Tests\Subscriber\LogSubscriber;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Subscriber\Log\Formatter;
+use GuzzleHttp\Subscriber\Log\LogSubscriber;
+use GuzzleHttp\Subscriber\Log\SimpleLogger;
+use GuzzleHttp\Subscriber\Mock;
+use GuzzleHttp\Message\Response;
+
+/**
+ * @covers GuzzleHttp\Subscriber\Log\LogSubscriber
+ */
+class LogSubscriberTest extends \PHPUnit_Framework_TestCase
+{
+ public function testUsesSimpleLogger()
+ {
+ $s = new LogSubscriber();
+ $this->assertInstanceOf('GuzzleHttp\\Subscriber\\Log\\SimpleLogger', $this->readAttribute($s, 'logger'));
+ $s = new LogSubscriber(function () {});
+ $this->assertInstanceOf('GuzzleHttp\\Subscriber\\Log\\SimpleLogger', $this->readAttribute($s, 'logger'));
+ $r = fopen('php://temp', 'r+');
+ $s = new LogSubscriber($r);
+ $this->assertInstanceOf('GuzzleHttp\\Subscriber\\Log\\SimpleLogger', $this->readAttribute($s, 'logger'));
+ fclose($r);
+ }
+
+ public function testUsesLogger()
+ {
+ $logger = new SimpleLogger();
+ $log = new LogSubscriber($logger);
+ $this->assertSame($logger, $this->readAttribute($log, 'logger'));
+ }
+
+ public function testUsesFormatString()
+ {
+ $log = new LogSubscriber(null, '{test}');
+ $formatter = $this->readAttribute($log, 'formatter');
+ $this->assertEquals('{test}', $this->readAttribute($formatter, 'template'));
+ }
+
+ public function testUsesFormatter()
+ {
+ $formatter = new Formatter();
+ $log = new LogSubscriber(null, $formatter);
+ $this->assertSame($formatter, $this->readAttribute($log, 'formatter'));
+ }
+
+ public function testLogsAfterSending()
+ {
+ $resource = fopen('php://temp', 'r+');
+ $logger = new LogSubscriber($resource, '{code}');
+ $client = new Client();
+ $client->getEmitter()->attach($logger);
+ $client->getEmitter()->attach(new Mock([new Response(200)]));
+ $client->get('http://httbin.org/get');
+ rewind($resource);
+ $this->assertEquals("[info] 200\n", stream_get_contents($resource));
+ fclose($resource);
+ }
+
+ public function testLogsAfterError()
+ {
+ $resource = fopen('php://temp', 'r+');
+ $logger = new LogSubscriber($resource, '{code}');
+ $client = new Client();
+ $client->getEmitter()->attach($logger);
+ $client->getEmitter()->attach(new Mock([new Response(500)]));
+ try {
+ $client->get('http://httbin.org/get');
+ } catch (\Exception $e) {}
+ rewind($resource);
+ $this->assertEquals("[critical] 500\n", stream_get_contents($resource));
+ fclose($resource);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/SimpleLoggerTest.php b/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/SimpleLoggerTest.php
new file mode 100644
index 0000000..300687e
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/log-subscriber/tests/SimpleLoggerTest.php
@@ -0,0 +1,41 @@
+<?php
+namespace GuzzleHttp\Tests\Subscriber\LogSubscriber;
+
+use GuzzleHttp\Subscriber\Log\SimpleLogger;
+
+/**
+ * @covers GuzzleHttp\Subscriber\Log\SimpleLogger
+ */
+class SimpleLoggerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLogsToFopen()
+ {
+ $resource = fopen('php://temp', 'r+');
+ $logger = new SimpleLogger($resource);
+ $logger->log('WARN', 'Test');
+ rewind($resource);
+ $this->assertEquals("[WARN] Test\n", stream_get_contents($resource));
+ fclose($resource);
+ }
+
+ public function testLogsToCallable()
+ {
+ $called = false;
+ $c = function ($message) use (&$called) {
+ $this->assertEquals("[WARN] Test\n", $message);
+ $called = true;
+ };
+ $logger = new SimpleLogger($c);
+ $logger->log('WARN', 'Test');
+ $this->assertTrue($called);
+ }
+
+ public function testLogsWithEcho()
+ {
+ ob_start();
+ $logger = new SimpleLogger();
+ $logger->log('WARN', 'Test');
+ $result = ob_get_clean();
+ $this->assertEquals("[WARN] Test\n", $result);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/.gitignore b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/.gitignore
new file mode 100644
index 0000000..c33d396
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/.gitignore
@@ -0,0 +1,6 @@
+.idea
+.DS_STORE
+coverage
+phpunit.xml
+composer.lock
+vendor/
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/.travis.yml b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/.travis.yml
new file mode 100644
index 0000000..4355f26
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/.travis.yml
@@ -0,0 +1,13 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+before_script:
+ - composer self-update
+ - composer install --no-interaction --prefer-source --dev
+
+script: vendor/bin/phpunit
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/LICENSE b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/LICENSE
new file mode 100644
index 0000000..71d3b78
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/README.rst b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/README.rst
new file mode 100644
index 0000000..e6f2e60
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/README.rst
@@ -0,0 +1,68 @@
+=======================
+Guzzle OAuth Subscriber
+=======================
+
+Signs HTTP requests using OAuth 1.0. Requests are signed using a consumer key,
+consumer secret, OAuth token, and OAuth secret.
+
+Installing
+==========
+
+This project can be installed using Composer. Add the following to your
+composer.json:
+
+.. code-block:: javascript
+
+ {
+ "require": {
+ "guzzlehttp/oauth-subscriber": "0.1.*"
+ }
+ }
+
+
+
+Using the Subscriber
+====================
+
+Here's an example showing how to send an authenticated request to the Twitter
+REST API:
+
+.. code-block:: php
+
+ use GuzzleHttp\Client;
+ use GuzzleHttp\Subscriber\Oauth\Oauth1;
+
+ $client = new Client(['base_url' => 'https://api.twitter.com/1.1/']);
+
+ $oauth = new Oauth1([
+ 'consumer_key' => 'my_key',
+ 'consumer_secret' => 'my_secret',
+ 'token' => 'my_token',
+ 'token_secret' => 'my_token_secret'
+ ]);
+
+ $client->getEmitter()->attach($oauth);
+
+ // Set the "auth" request option to "oauth" to sign using oauth
+ $res = $client->get('statuses/home_timeline.json', ['auth' => 'oauth']);
+
+You can set the ``auth`` request option to ``oauth`` for all requests sent by
+the client using the client's ``defaults`` constructor option.
+
+.. code-block:: php
+
+ use GuzzleHttp\Client;
+
+ $client = new Client([
+ 'base_url' => 'https://api.twitter.com/1.1/',
+ 'defaults' => ['auth' => 'oauth']
+ ]);
+
+ $client->getEmitter()->attach($oauth);
+
+ // Now you don't need to add the auth parameter
+ $res = $client->get('statuses/home_timeline.json');
+
+.. note::
+
+ You can omit the token and token_secret options to use two-legged OAuth.
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/composer.json b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/composer.json
new file mode 100644
index 0000000..a7c0814
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "guzzlehttp/oauth-subscriber",
+ "description": "Guzzle OAuth 1.0 subscriber",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": ["oauth", "guzzle"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "guzzlehttp/guzzle": "~4.0|~5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "autoload": {
+ "psr-4": { "GuzzleHttp\\Subscriber\\Oauth\\": "src" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/phpunit.xml.dist b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/phpunit.xml.dist
new file mode 100644
index 0000000..36f5598
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/phpunit.xml.dist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./vendor/autoload.php"
+ colors="true">
+ <php>
+ <!-- Specify your twitter OAuth credentials -->
+ <server name="OAUTH_CONSUMER_KEY" value="" />
+ <server name="OAUTH_CONSUMER_SECRET" value="" />
+ <server name="OAUTH_TOKEN" value="" />
+ <server name="OAUTH_TOKEN_SECRET" value="" />
+ </php>
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/src/Oauth1.php b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/src/Oauth1.php
new file mode 100644
index 0000000..504be40
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/src/Oauth1.php
@@ -0,0 +1,308 @@
+<?php
+
+namespace GuzzleHttp\Subscriber\Oauth;
+
+use GuzzleHttp\Collection;
+use GuzzleHttp\Event\RequestEvents;
+use GuzzleHttp\Event\SubscriberInterface;
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Post\PostBodyInterface;
+use GuzzleHttp\Query;
+use GuzzleHttp\Url;
+
+/**
+ * OAuth 1.0 signature plugin.
+ *
+ * Portions of this code comes from HWIOAuthBundle and a Guzzle 3 pull request:
+ * @author Alexander <iam.asm89@gmail.com>
+ * @author Joseph Bielawski <stloyd@gmail.com>
+ * @author Francisco Facioni <fran6co@gmail.com>
+ * @link https://github.com/hwi/HWIOAuthBundle
+ * @link https://github.com/guzzle/guzzle/pull/563 Original Guzzle 3 pull req.
+ *
+ * @link http://oauth.net/core/1.0/#rfc.section.9.1.1 OAuth specification
+ */
+class Oauth1 implements SubscriberInterface
+{
+ /**
+ * Consumer request method constants. See http://oauth.net/core/1.0/#consumer_req_param
+ */
+ const REQUEST_METHOD_HEADER = 'header';
+ const REQUEST_METHOD_QUERY = 'query';
+
+ const SIGNATURE_METHOD_HMAC = 'HMAC-SHA1';
+ const SIGNATURE_METHOD_RSA = 'RSA-SHA1';
+ const SIGNATURE_METHOD_PLAINTEXT = 'PLAINTEXT';
+
+ /** @var Collection Configuration settings */
+ private $config;
+
+ /**
+ * Create a new OAuth 1.0 plugin.
+ *
+ * The configuration array accepts the following options:
+ *
+ * - request_method: Consumer request method. One of 'header' or 'query'.
+ * Defaults to 'header'.
+ * - callback: OAuth callback
+ * - consumer_key: Consumer key string. Defaults to "anonymous".
+ * - consumer_secret: Consumer secret. Defaults to "anonymous".
+ * - token: Client token
+ * - token_secret: Client secret token
+ * - verifier: OAuth verifier.
+ * - version: OAuth version. Defaults to '1.0'.
+ * - realm: OAuth realm.
+ * - signature_method: Signature method. One of 'HMAC-SHA1', 'RSA-SHA1', or
+ * 'PLAINTEXT'. Defaults to 'HMAC-SHA1'.
+ *
+ * @param array $config Configuration array.
+ */
+ public function __construct($config)
+ {
+ $this->config = Collection::fromConfig($config, [
+ 'version' => '1.0',
+ 'request_method' => self::REQUEST_METHOD_HEADER,
+ 'consumer_key' => 'anonymous',
+ 'consumer_secret' => 'anonymous',
+ 'signature_method' => self::SIGNATURE_METHOD_HMAC,
+ ], ['signature_method', 'version', 'consumer_key', 'consumer_secret']);
+ }
+
+ public function getEvents()
+ {
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
+ }
+
+ public function onBefore(BeforeEvent $event)
+ {
+ $request = $event->getRequest();
+
+ // Only sign requests using "auth"="oauth"
+ if ($request->getConfig()['auth'] != 'oauth') {
+ return;
+ }
+
+ $params = $this->getOauthParams(
+ $this->generateNonce($request),
+ $this->config
+ );
+
+ $params['oauth_signature'] = $this->getSignature($request, $params);
+ uksort($params, 'strcmp');
+
+ switch ($this->config['request_method']) {
+ case self::REQUEST_METHOD_HEADER:
+ list($header, $value) = $this->buildAuthorizationHeader($params);
+ $request->setHeader($header, $value);
+ break;
+ case self::REQUEST_METHOD_QUERY:
+ $request->getQuery()->overwriteWith($params);
+ break;
+ default:
+ throw new \InvalidArgumentException(sprintf(
+ 'Invalid consumer method "%s"',
+ $this->config['request_method']
+ ));
+ }
+ }
+
+ /**
+ * Calculate signature for request
+ *
+ * @param RequestInterface $request Request to generate a signature for
+ * @param array $params Oauth parameters.
+ *
+ * @return string
+ *
+ * @throws \RuntimeException
+ */
+ public function getSignature(RequestInterface $request, array $params)
+ {
+ // Remove oauth_signature if present
+ // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
+ unset($params['oauth_signature']);
+
+ // Add POST fields if the request uses POST fields and no files
+ $body = $request->getBody();
+ if ($body instanceof PostBodyInterface && !$body->getFiles()) {
+ $query = Query::fromString($body->getFields(true));
+ $params += $query->toArray();
+ }
+
+ // Parse & add query string parameters as base string parameters
+ $query = Query::fromString((string) $request->getQuery());
+ $query->setEncodingType(Query::RFC1738);
+ $params += $query->toArray();
+
+ $baseString = $this->createBaseString(
+ $request,
+ $this->prepareParameters($params)
+ );
+
+ // Implements double-dispatch to sign requests
+ $meth = [$this, 'sign_' . str_replace(
+ '-', '_', $this->config['signature_method']
+ )];
+
+ if (!is_callable($meth)) {
+ throw new \RuntimeException('Unknown signature method: '
+ . $this->config['signature_method']);
+ }
+
+ return base64_encode(call_user_func($meth, $baseString, $this->config));
+ }
+
+ /**
+ * Returns a Nonce Based on the unique id and URL.
+ *
+ * This will allow for multiple requests in parallel with the same exact
+ * timestamp to use separate nonce's.
+ *
+ * @param RequestInterface $request Request to generate a nonce for
+ *
+ * @return string
+ */
+ public function generateNonce(RequestInterface $request)
+ {
+ return sha1(uniqid('', true) . $request->getUrl());
+ }
+
+ /**
+ * Creates the Signature Base String.
+ *
+ * The Signature Base String is a consistent reproducible concatenation of
+ * the request elements into a single string. The string is used as an
+ * input in hashing or signing algorithms.
+ *
+ * @param RequestInterface $request Request being signed
+ * @param array $params Associative array of OAuth parameters
+ *
+ * @return string Returns the base string
+ * @link http://oauth.net/core/1.0/#sig_base_example
+ */
+ protected function createBaseString(RequestInterface $request, array $params)
+ {
+ // Remove query params from URL. Ref: Spec: 9.1.2.
+ $url = Url::fromString($request->getUrl());
+ $url->setQuery('');
+ $query = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
+
+ return strtoupper($request->getMethod())
+ . '&' . rawurlencode($url)
+ . '&' . rawurlencode($query);
+ }
+
+ /**
+ * Convert booleans to strings, removed unset parameters, and sorts the array
+ *
+ * @param array $data Data array
+ *
+ * @return array
+ */
+ private function prepareParameters($data)
+ {
+ // Parameters are sorted by name, using lexicographical byte value
+ // ordering. Ref: Spec: 9.1.1 (1).
+ uksort($data, 'strcmp');
+
+ foreach ($data as $key => $value) {
+ if ($value === null) {
+ unset($data[$key]);
+ }
+ }
+
+ return $data;
+ }
+
+ private function sign_HMAC_SHA1($baseString)
+ {
+ $key = rawurlencode($this->config['consumer_secret'])
+ . '&' . rawurlencode($this->config['token_secret']);
+
+ return hash_hmac('sha1', $baseString, $key, true);
+ }
+
+ private function sign_RSA_SHA1($baseString)
+ {
+ if (!function_exists('openssl_pkey_get_private')) {
+ throw new \RuntimeException('RSA-SHA1 signature method '
+ . 'requires the OpenSSL extension.');
+ }
+
+ $privateKey = openssl_pkey_get_private(
+ file_get_contents($this->config['consumer_secret']),
+ $this->config['consumer_secret']
+ );
+
+ $signature = false;
+ openssl_sign($baseString, $signature, $privateKey);
+ openssl_free_key($privateKey);
+
+ return $signature;
+ }
+
+ private function sign_PLAINTEXT($baseString)
+ {
+ return $baseString;
+ }
+
+ /**
+ * Builds the Authorization header for a request
+ *
+ * @param array $params Associative array of authorization parameters.
+ *
+ * @return array
+ */
+ private function buildAuthorizationHeader(array $params)
+ {
+ foreach ($params as $key => $value) {
+ $params[$key] = $key . '="' . rawurlencode($value) . '"';
+ }
+
+ if ($this->config['realm']) {
+ array_unshift(
+ $params,
+ 'realm="' . rawurlencode($this->config['realm']) . '"'
+ );
+ }
+
+ return ['Authorization', 'OAuth ' . implode(', ', $params)];
+ }
+
+ /**
+ * Get the oauth parameters as named by the oauth spec
+ *
+ * @param string $nonce Unique nonce
+ * @param Collection $config Configuration options of the plugin.
+ *
+ * @return array
+ */
+ private function getOauthParams($nonce, Collection $config)
+ {
+ $params = [
+ 'oauth_consumer_key' => $config['consumer_key'],
+ 'oauth_nonce' => $nonce,
+ 'oauth_signature_method' => $config['signature_method'],
+ 'oauth_timestamp' => time(),
+ ];
+
+ // Optional parameters should not be set if they have not been set in
+ // the config as the parameter may be considered invalid by the Oauth
+ // service.
+ $optionalParams = [
+ 'callback' => 'oauth_callback',
+ 'token' => 'oauth_token',
+ 'verifier' => 'oauth_verifier',
+ 'version' => 'oauth_version'
+ ];
+
+ foreach ($optionalParams as $optionName => $oauthName) {
+ if (isset($config[$optionName])) {
+ $params[$oauthName] = $config[$optionName];
+ }
+ }
+
+ return $params;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/oauth-subscriber/tests/Oauth1Test.php b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/tests/Oauth1Test.php
new file mode 100644
index 0000000..064608f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/oauth-subscriber/tests/Oauth1Test.php
@@ -0,0 +1,282 @@
+<?php
+
+namespace GuzzleHttp\Tests\Oauth1;
+
+use GuzzleHttp\Transaction;
+use GuzzleHttp\Client;
+use GuzzleHttp\Event\BeforeEvent;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Message\Request;
+use GuzzleHttp\Post\PostBody;
+use GuzzleHttp\Subscriber\Oauth\Oauth1;
+
+class Oauth1Test extends \PHPUnit_Framework_TestCase
+{
+ const TIMESTAMP = '1327274290';
+ const NONCE = 'e7aa11195ca58349bec8b5ebe351d3497eb9e603';
+
+ private $config = [
+ 'consumer_key' => 'foo',
+ 'consumer_secret' => 'bar',
+ 'token' => 'count',
+ 'token_secret' => 'dracula'
+ ];
+
+ protected function getRequest()
+ {
+ $body = new PostBody();
+ $body->setField('e', 'f');
+
+ return new Request('POST', 'http://www.test.com/path?a=b&c=d', [], $body);
+ }
+
+ public function testSubscribesToEvents()
+ {
+ $events = (new Oauth1([]))->getEvents();
+ $this->assertArrayHasKey('before', $events);
+ }
+
+ public function testAcceptsConfigurationData()
+ {
+ $p = new Oauth1($this->config);
+
+ // Access the config object
+ $class = new \ReflectionClass($p);
+ $property = $class->getProperty('config');
+ $property->setAccessible(true);
+ $config = $property->getValue($p);
+
+ $this->assertEquals('foo', $config['consumer_key']);
+ $this->assertEquals('bar', $config['consumer_secret']);
+ $this->assertEquals('count', $config['token']);
+ $this->assertEquals('dracula', $config['token_secret']);
+ $this->assertEquals('1.0', $config['version']);
+ $this->assertEquals('HMAC-SHA1', $config['signature_method']);
+ $this->assertEquals('header', $config['request_method']);
+ }
+
+ public function testCreatesStringToSignFromPostRequest()
+ {
+ $s = new Oauth1($this->config);
+ $client = new Client();
+ $request = $client->createRequest('POST', 'http://httpbin.org', [
+ 'auth' => 'oauth',
+ 'body' => [
+ 'foo' => [
+ 'baz' => ['bar'],
+ 'bam' => [null, true, false]
+ ]
+ ]
+ ]);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertTrue($request->hasHeader('Authorization'));
+ }
+
+ public function testSignsPlainText()
+ {
+ $config = $this->config;
+ $config['signature_method'] = Oauth1::SIGNATURE_METHOD_PLAINTEXT;
+ $s = new Oauth1($config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth']);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertTrue($request->hasHeader('Authorization'));
+ $this->assertContains('oauth_signature_method="PLAINTEXT"', $request->getHeader('Authorization'));
+ $this->assertContains('oauth_signature="', $request->getHeader('Authorization'));
+ }
+
+ public function testSignsOauthRequestsInHeader()
+ {
+ $s = new Oauth1($this->config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth']);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertTrue($request->hasHeader('Authorization'));
+ $this->assertCount(0, $request->getQuery());
+ $check = ['oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
+ 'oauth_signature_method', 'oauth_timestamp', 'oauth_token',
+ 'oauth_version'];
+ foreach ($check as $name) {
+ $this->assertContains($name . '=', $request->getHeader('Authorization'));
+ }
+ }
+
+ public function testSignsOauthQueryStringRequest()
+ {
+ $config = $this->config;
+ $config['request_method'] = Oauth1::REQUEST_METHOD_QUERY;
+ $s = new Oauth1($config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth']);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertFalse($request->hasHeader('Authorization'));
+ $check = ['oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
+ 'oauth_signature_method', 'oauth_timestamp', 'oauth_token',
+ 'oauth_version'];
+ foreach ($check as $name) {
+ $this->assertNotEmpty($request->getQuery()[$name]);
+ }
+ // Ensure that no extra keys were added
+ $keys = $request->getQuery()->getKeys();
+ sort($keys);
+ $this->assertSame($keys, $check);
+ }
+
+ public function testOnlyTouchesWhenAuthConfigIsOauth()
+ {
+ $s = new Oauth1($this->config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org');
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertCount(0, $request->getQuery());
+ $this->assertEmpty($request->getHeader('Authorization'));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesRequestMethod()
+ {
+ $config = $this->config;
+ $config['request_method'] = 'Foo';
+ $s = new Oauth1($config);
+ $client = new Client();
+ $before = new BeforeEvent(new Transaction(
+ $client,
+ $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth'])
+ ));
+ $s->onBefore($before);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testExceptionOnSignatureError()
+ {
+ $config = $this->config;
+ $config['signature_method'] = 'Foo';
+ $s = new Oauth1($config);
+ $client = new Client();
+ $before = new BeforeEvent(new Transaction(
+ $client,
+ $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth'])
+ ));
+ $s->onBefore($before);
+ }
+
+ public function testDoesNotAddEmptyValuesToAuthorization()
+ {
+ $config = $this->config;
+ unset($config['token']);
+ $s = new Oauth1($config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth']);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertTrue($request->hasHeader('Authorization'));
+ $this->assertNotContains('oauth_token=', $request->getHeader('Authorization'));
+ }
+
+ public function testRandomParametersAreNotAutomaticallyAdded()
+ {
+ $config = $this->config;
+ $config['foo'] = 'bar';
+ $s = new Oauth1($config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth']);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertTrue($request->hasHeader('Authorization'));
+ $this->assertNotContains('foo=bar', $request->getHeader('Authorization'));
+ }
+
+ public function testAllowsRealm()
+ {
+ $config = $this->config;
+ $config['realm'] = 'foo';
+ $s = new Oauth1($config);
+ $client = new Client();
+ $request = $client->createRequest('GET', 'http://httpbin.org', ['auth' => 'oauth']);
+ $before = new BeforeEvent(new Transaction($client, $request));
+ $s->onBefore($before);
+ $this->assertTrue($request->hasHeader('Authorization'));
+ $this->assertContains('OAuth realm="foo",', $request->getHeader('Authorization'));
+ }
+
+ public function testTwitterIntegration()
+ {
+ if (empty($_SERVER['OAUTH_CONSUMER_SECRET'])) {
+ $this->markTestSkipped('No OAUTH_CONSUMER_SECRET provided in phpunit.xml');
+ return;
+ }
+
+ $client = new Client([
+ 'base_url' => 'https://api.twitter.com/1.1/',
+ 'defaults' => ['auth' => 'oauth']
+ ]);
+
+ $oauth = new Oauth1([
+ 'consumer_key' => $_SERVER['OAUTH_CONSUMER_KEY'],
+ 'consumer_secret' => $_SERVER['OAUTH_CONSUMER_SECRET'],
+ 'token' => $_SERVER['OAUTH_TOKEN'],
+ 'token_secret' => $_SERVER['OAUTH_TOKEN_SECRET']
+ ]);
+
+ $client->getEmitter()->attach($oauth);
+
+ try {
+ $client->get('account/settings.json');
+ } catch (ClientException $e) {
+ if ($e->getResponse()->getStatusCode() == 429) {
+ $this->markTestIncomplete('You are being throttled');
+ } else {
+ throw $e;
+ }
+ }
+ }
+
+ public function testTwitterStreamingIntegration()
+ {
+ if (empty($_SERVER['OAUTH_CONSUMER_SECRET'])) {
+ $this->markTestSkipped('No OAUTH_CONSUMER_SECRET provided in phpunit.xml');
+ return;
+ }
+
+ $client = new Client([
+ 'base_url' => 'https://stream.twitter.com/1.1/',
+ 'defaults' => ['auth' => 'oauth']
+ ]);
+
+ $oauth = new Oauth1([
+ 'consumer_key' => $_SERVER['OAUTH_CONSUMER_KEY'],
+ 'consumer_secret' => $_SERVER['OAUTH_CONSUMER_SECRET'],
+ 'token' => $_SERVER['OAUTH_TOKEN'],
+ 'token_secret' => $_SERVER['OAUTH_TOKEN_SECRET']
+ ]);
+
+ $client->getEmitter()->attach($oauth);
+
+ try {
+ $response = $client->post('statuses/filter.json', [
+ 'body' => ['track' => 'bieber'],
+ 'stream' => true
+ ]);
+ $body = $response->getBody();
+ $data = $body::readLine($body);
+ $this->assertContains('bieber', strtolower($data));
+ $this->assertNotEmpty(json_decode($data, true));
+ $body->close();
+ } catch (ClientException $e) {
+ if ($e->getResponse()->getStatusCode() == 429) {
+ $this->markTestIncomplete('You are being throttled');
+ } else {
+ throw $e;
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/.editorconfig b/public/system/storage/vendor/guzzlehttp/ringphp/.editorconfig
new file mode 100644
index 0000000..70dabca
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[{Makefile,*.mk}]
+indent_style = tab
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/.gitignore b/public/system/storage/vendor/guzzlehttp/ringphp/.gitignore
new file mode 100644
index 0000000..290a945
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/.gitignore
@@ -0,0 +1,4 @@
+vendor
+build/artifacts/
+composer.lock
+docs/_build/
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/.travis.yml b/public/system/storage/vendor/guzzlehttp/ringphp/.travis.yml
new file mode 100644
index 0000000..18562e4
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/.travis.yml
@@ -0,0 +1,43 @@
+language: php
+
+cache:
+ directories:
+ - $HOME/.composer/cache/files
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+ - 7.2
+ - hhvm
+ - nightly
+
+env:
+ global:
+ - TEST_COMMAND="composer test"
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ - php: nightly
+ fast_finish: true
+ include:
+ - php: 5.4
+ env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest"
+
+before_install:
+ - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
+
+install:
+ # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
+ - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
+ - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
+
+before_script:
+ - ~/.nvm/nvm.sh install v0.6.14
+ - ~/.nvm/nvm.sh run v0.6.14
+
+script:
+ - $TEST_COMMAND
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/CHANGELOG.md b/public/system/storage/vendor/guzzlehttp/ringphp/CHANGELOG.md
new file mode 100644
index 0000000..8e12bf3
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/CHANGELOG.md
@@ -0,0 +1,118 @@
+# Changelog
+
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+
+## [Unreleased]
+
+
+## [1.1.1] - 2018-07-31
+
+### Fixed
+
+- `continue` keyword usage on PHP 7.3
+
+
+## [1.1.0] - 2015-05-19
+
+### Added
+
+- Added `CURL_HTTP_VERSION_2_0`
+
+### Changed
+
+- The PHP stream wrapper handler now sets `allow_self_signed` to `false` to
+ match the cURL handler when `verify` is set to `true` or a certificate file.
+- Ensuring that a directory exists before using the `save_to` option.
+- Response protocol version is now correctly extracted from a response.
+
+### Fixed
+
+- Fixed a bug in which the result of `CurlFactory::retryFailedRewind` did not
+ return an array.
+
+
+## [1.0.7] - 2015-03-29
+
+### Fixed
+
+- PHP 7 fixes.
+
+
+## [1.0.6] - 2015-02-26
+
+### Changed
+
+- The multi handle of the CurlMultiHandler is now created lazily.
+
+### Fixed
+
+- Bug fix: futures now extend from React's PromiseInterface to ensure that they
+ are properly forwarded down the promise chain.
+
+
+## [1.0.5] - 2014-12-10
+
+### Added
+
+- Adding more error information to PHP stream wrapper exceptions.
+- Added digest auth integration test support to test server.
+
+
+## [1.0.4] - 2014-12-01
+
+### Added
+
+- Added support for older versions of cURL that do not have CURLOPT_TIMEOUT_MS.
+- Added a fix to the StreamHandler to return a `FutureArrayInterface` when an
+
+### Changed
+
+- Setting debug to `false` does not enable debug output. error occurs.
+
+
+## [1.0.3] - 2014-11-03
+
+### Fixed
+
+- Setting the `header` stream option as a string to be compatible with GAE.
+- Header parsing now ensures that header order is maintained in the parsed
+ message.
+
+
+## [1.0.2] - 2014-10-28
+
+### Fixed
+
+- Now correctly honoring a `version` option is supplied in a request.
+ See https://github.com/guzzle/RingPHP/pull/8
+
+
+## [1.0.1] - 2014-10-26
+
+### Fixed
+
+- Fixed a header parsing issue with the `CurlHandler` and `CurlMultiHandler`
+ that caused cURL requests with multiple responses to merge repsonses together
+ (e.g., requests with digest authentication).
+
+
+## 1.0.0 - 2014-10-12
+
+- Initial release
+
+
+[Unreleased]: https://github.com/guzzle/RingPHP/compare/1.1.1...HEAD
+[1.1.1]: https://github.com/guzzle/RingPHP/compare/1.1.0...1.1.1
+[1.1.0]: https://github.com/guzzle/RingPHP/compare/1.0.7...1.1.0
+[1.0.7]: https://github.com/guzzle/RingPHP/compare/1.0.6...1.0.7
+[1.0.6]: https://github.com/guzzle/RingPHP/compare/1.0.5...1.0.6
+[1.0.5]: https://github.com/guzzle/RingPHP/compare/1.0.4...1.0.5
+[1.0.4]: https://github.com/guzzle/RingPHP/compare/1.0.3...1.0.4
+[1.0.3]: https://github.com/guzzle/RingPHP/compare/1.0.2...1.0.3
+[1.0.2]: https://github.com/guzzle/RingPHP/compare/1.0.1...1.0.2
+[1.0.1]: https://github.com/guzzle/RingPHP/compare/1.0.0...1.0.1
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/LICENSE b/public/system/storage/vendor/guzzlehttp/ringphp/LICENSE
new file mode 100644
index 0000000..71d3b78
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/Makefile b/public/system/storage/vendor/guzzlehttp/ringphp/Makefile
new file mode 100644
index 0000000..21c812e
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/Makefile
@@ -0,0 +1,46 @@
+all: clean coverage docs
+
+docs:
+ cd docs && make html
+
+view-docs:
+ open docs/_build/html/index.html
+
+start-server: stop-server
+ node tests/Client/server.js &> /dev/null &
+
+stop-server:
+ @PID=$(shell ps axo pid,command \
+ | grep 'tests/Client/server.js' \
+ | grep -v grep \
+ | cut -f 1 -d " "\
+ ) && [ -n "$$PID" ] && kill $$PID || true
+
+test: start-server
+ vendor/bin/phpunit $(TEST)
+ $(MAKE) stop-server
+
+coverage: start-server
+ vendor/bin/phpunit --coverage-html=build/artifacts/coverage $(TEST)
+ $(MAKE) stop-server
+
+view-coverage:
+ open build/artifacts/coverage/index.html
+
+clean:
+ rm -rf build/artifacts/*
+ cd docs && make clean
+
+tag:
+ $(if $(TAG),,$(error TAG is not defined. Pass via "make tag TAG=4.2.1"))
+ @echo Tagging $(TAG)
+ chag update -m '$(TAG) ()'
+ git add -A
+ git commit -m '$(TAG) release'
+ chag tag
+
+perf: start-server
+ php tests/perf.php
+ $(MAKE) stop-server
+
+.PHONY: docs
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/README.rst b/public/system/storage/vendor/guzzlehttp/ringphp/README.rst
new file mode 100644
index 0000000..10374e8
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/README.rst
@@ -0,0 +1,46 @@
+=======
+RingPHP
+=======
+
+Provides a simple API and specification that abstracts away the details of HTTP
+into a single PHP function. RingPHP be used to power HTTP clients and servers
+through a PHP function that accepts a request hash and returns a response hash
+that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
+allowing RingPHP to support both synchronous and asynchronous workflows.
+
+By abstracting the implementation details of different HTTP clients and
+servers, RingPHP allows you to utilize pluggable HTTP clients and servers
+without tying your application to a specific implementation.
+
+.. code-block:: php
+
+ <?php
+ require 'vendor/autoload.php';
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => [
+ 'host' => ['www.google.com'],
+ 'x-foo' => ['baz']
+ ]
+ ]);
+
+ $response->then(function (array $response) {
+ echo $response['status'];
+ });
+
+ $response->wait();
+
+RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
+which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
+utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
+HTTP requests.
+
+Documentation
+-------------
+
+See http://ringphp.readthedocs.org/ for the full online documentation.
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/composer.json b/public/system/storage/vendor/guzzlehttp/ringphp/composer.json
new file mode 100644
index 0000000..8df60ec
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/composer.json
@@ -0,0 +1,43 @@
+{
+ "name": "guzzlehttp/ringphp",
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "guzzlehttp/streams": "~3.0",
+ "react/promise": "~2.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0"
+ },
+ "suggest": {
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Ring\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "GuzzleHttp\\Tests\\Ring\\": "tests/"
+ }
+ },
+ "scripts": {
+ "test": "make test",
+ "test-ci": "make coverage"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/Makefile b/public/system/storage/vendor/guzzlehttp/ringphp/docs/Makefile
new file mode 100644
index 0000000..51270aa
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GuzzleRing.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GuzzleRing.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/GuzzleRing"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GuzzleRing"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/client_handlers.rst b/public/system/storage/vendor/guzzlehttp/ringphp/docs/client_handlers.rst
new file mode 100644
index 0000000..3151f00
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/client_handlers.rst
@@ -0,0 +1,173 @@
+===============
+Client Handlers
+===============
+
+Client handlers accept a request array and return a future response array that
+can be used synchronously as an array or asynchronously using a promise.
+
+Built-In Handlers
+-----------------
+
+RingPHP comes with three built-in client handlers.
+
+Stream Handler
+~~~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\StreamHandler`` uses PHP's
+`http stream wrapper <http://php.net/manual/en/wrappers.http.php>`_ to send
+requests.
+
+.. note::
+
+ This handler cannot send requests concurrently.
+
+You can provide an associative array of custom stream context options to the
+StreamHandler using the ``stream_context`` key of the ``client`` request
+option.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\StreamHandler;
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['httpbin.org']],
+ 'client' => [
+ 'stream_context' => [
+ 'http' => [
+ 'request_fulluri' => true,
+ 'method' => 'HEAD'
+ ],
+ 'socket' => [
+ 'bindto' => '127.0.0.1:0'
+ ],
+ 'ssl' => [
+ 'verify_peer' => false
+ ]
+ ]
+ ]
+ ]);
+
+ // Even though it's already completed, you can still use a promise
+ $response->then(function ($response) {
+ echo $response['status']; // 200
+ });
+
+ // Or access the response using the future interface
+ echo $response['status']; // 200
+
+cURL Handler
+~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\CurlHandler`` can be used with PHP 5.5+ to send
+requests using cURL easy handles. This handler is great for sending requests
+one at a time because the execute and select loop is implemented in C code
+which executes faster and consumes less memory than using PHP's
+``curl_multi_*`` interface.
+
+.. note::
+
+ This handler cannot send requests concurrently.
+
+When using the CurlHandler, custom curl options can be specified as an
+associative array of `cURL option constants <http://php.net/manual/en/curl.constants.php>`_
+mapping to values in the ``client`` option of a requst using the **curl** key.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]]
+ ];
+
+ $response = $handler($request);
+
+ // The response can be used directly as an array.
+ echo $response['status']; // 200
+
+ // Or, it can be used as a promise (that has already fulfilled).
+ $response->then(function ($response) {
+ echo $response['status']; // 200
+ });
+
+cURL Multi Handler
+~~~~~~~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\CurlMultiHandler`` transfers requests using
+cURL's `multi API <http://curl.haxx.se/libcurl/c/libcurl-multi.html>`_. The
+``CurlMultiHandler`` is great for sending requests concurrently.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $handler = new CurlMultiHandler();
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]]
+ ];
+
+ // this call returns a future array immediately.
+ $response = $handler($request);
+
+ // Ideally, you should use the promise API to not block.
+ $response
+ ->then(function ($response) {
+ // Got the response at some point in the future
+ echo $response['status']; // 200
+ // Don't break the chain
+ return $response;
+ })->then(function ($response) {
+ // ...
+ });
+
+ // If you really need to block, then you can use the response as an
+ // associative array. This will block until it has completed.
+ echo $response['status']; // 200
+
+Just like the ``CurlHandler``, the ``CurlMultiHandler`` accepts custom curl
+option in the ``curl`` key of the ``client`` request option.
+
+Mock Handler
+~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\MockHandler`` is used to return mock responses.
+When constructed, the handler can be configured to return the same response
+array over and over, a future response, or a the evaluation of a callback
+function.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\MockHandler;
+
+ // Return a canned response.
+ $mock = new MockHandler(['status' => 200]);
+ $response = $mock([]);
+ assert(200 == $response['status']);
+ assert([] == $response['headers']);
+
+Implementing Handlers
+---------------------
+
+Client handlers are just PHP callables (functions or classes that have the
+``__invoke`` magic method). The callable accepts a request array and MUST
+return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface`` so that
+the response can be used by both blocking and non-blocking consumers.
+
+Handlers need to follow a few simple rules:
+
+1. Do not throw exceptions. If an error is encountered, return an array that
+ contains the ``error`` key that maps to an ``\Exception`` value.
+2. If the request has a ``delay`` client option, then the handler should only
+ send the request after the specified delay time in seconds. Blocking
+ handlers may find it convenient to just let the
+ ``GuzzleHttp\Ring\Core::doSleep($request)`` function handle this for them.
+3. Always return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface``.
+4. Complete any outstanding requests when the handler is destructed.
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/client_middleware.rst b/public/system/storage/vendor/guzzlehttp/ringphp/docs/client_middleware.rst
new file mode 100644
index 0000000..5a2c1a8
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/client_middleware.rst
@@ -0,0 +1,165 @@
+=================
+Client Middleware
+=================
+
+Middleware intercepts requests before they are sent over the wire and can be
+used to add functionality to handlers.
+
+Modifying Requests
+------------------
+
+Let's say you wanted to modify requests before they are sent over the wire
+so that they always add specific headers. This can be accomplished by creating
+a function that accepts a handler and returns a new function that adds the
+composed behavior.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+
+ $addHeaderHandler = function (callable $handler, array $headers = []) {
+ return function (array $request) use ($handler, $headers) {
+ // Add our custom headers
+ foreach ($headers as $key => $value) {
+ $request['headers'][$key] = $value;
+ }
+
+ // Send the request using the handler and return the response.
+ return $handler($request);
+ }
+ };
+
+ // Create a new handler that adds headers to each request.
+ $handler = $addHeaderHandler($handler, [
+ 'X-AddMe' => 'hello',
+ 'Authorization' => 'Basic xyz'
+ ]);
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['httpbin.org']]
+ ]);
+
+Modifying Responses
+-------------------
+
+You can change a response as it's returned from a middleware. Remember that
+responses returned from an handler (including middleware) must implement
+``GuzzleHttp\Ring\Future\FutureArrayInterface``. In order to be a good citizen,
+you should not expect that the responses returned through your middleware will
+be completed synchronously. Instead, you should use the
+``GuzzleHttp\Ring\Core::proxy()`` function to modify the response when the
+underlying promise is resolved. This function is a helper function that makes it
+easy to create a new instance of ``FutureArrayInterface`` that wraps an existing
+``FutureArrayInterface`` object.
+
+Let's say you wanted to add headers to a response as they are returned from
+your middleware, but you want to make sure you aren't causing future
+responses to be dereferenced right away. You can achieve this by modifying the
+incoming request and using the ``Core::proxy`` function.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Core;
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+
+ $responseHeaderHandler = function (callable $handler, array $headers) {
+ return function (array $request) use ($handler, $headers) {
+ // Send the request using the wrapped handler.
+ return Core::proxy($handler($request), function ($response) use ($headers) {
+ // Add the headers to the response when it is available.
+ foreach ($headers as $key => $value) {
+ $response['headers'][$key] = (array) $value;
+ }
+ // Note that you can return a regular response array when using
+ // the proxy method.
+ return $response;
+ });
+ }
+ };
+
+ // Create a new handler that adds headers to each response.
+ $handler = $responseHeaderHandler($handler, ['X-Header' => 'hello!']);
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['httpbin.org']]
+ ]);
+
+ assert($response['headers']['X-Header'] == 'hello!');
+
+Built-In Middleware
+-------------------
+
+RingPHP comes with a few basic client middlewares that modify requests
+and responses.
+
+Streaming Middleware
+~~~~~~~~~~~~~~~~~~~~
+
+If you want to send all requests with the ``streaming`` option to a specific
+handler but other requests to a different handler, then use the streaming
+middleware.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+ use GuzzleHttp\Ring\Client\StreamHandler;
+ use GuzzleHttp\Ring\Client\Middleware;
+
+ $defaultHandler = new CurlHandler();
+ $streamingHandler = new StreamHandler();
+ $streamingHandler = Middleware::wrapStreaming(
+ $defaultHandler,
+ $streamingHandler
+ );
+
+ // Send the request using the streaming handler.
+ $response = $streamingHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']],
+ 'stream' => true
+ ]);
+
+ // Send the request using the default handler.
+ $response = $streamingHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']]
+ ]);
+
+Future Middleware
+~~~~~~~~~~~~~~~~~
+
+If you want to send all requests with the ``future`` option to a specific
+handler but other requests to a different handler, then use the future
+middleware.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+ use GuzzleHttp\Ring\Client\Middleware;
+
+ $defaultHandler = new CurlHandler();
+ $futureHandler = new CurlMultiHandler();
+ $futureHandler = Middleware::wrapFuture(
+ $defaultHandler,
+ $futureHandler
+ );
+
+ // Send the request using the blocking CurlHandler.
+ $response = $futureHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']]
+ ]);
+
+ // Send the request using the non-blocking CurlMultiHandler.
+ $response = $futureHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']],
+ 'future' => true
+ ]);
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/conf.py b/public/system/storage/vendor/guzzlehttp/ringphp/docs/conf.py
new file mode 100644
index 0000000..c6404aa
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/conf.py
@@ -0,0 +1,23 @@
+import sys, os
+import sphinx_rtd_theme
+from sphinx.highlighting import lexers
+from pygments.lexers.web import PhpLexer
+
+
+lexers['php'] = PhpLexer(startinline=True, linenos=1)
+lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
+primary_domain = 'php'
+
+extensions = []
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = u'RingPHP'
+copyright = u'2014, Michael Dowling'
+version = '1.0.0-alpha'
+exclude_patterns = ['_build']
+
+html_title = "RingPHP"
+html_short_title = "RingPHP"
+html_theme = "sphinx_rtd_theme"
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/futures.rst b/public/system/storage/vendor/guzzlehttp/ringphp/docs/futures.rst
new file mode 100644
index 0000000..af29cb3
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/futures.rst
@@ -0,0 +1,164 @@
+=======
+Futures
+=======
+
+Futures represent a computation that may have not yet completed. RingPHP
+uses hybrid of futures and promises to provide a consistent API that can be
+used for both blocking and non-blocking consumers.
+
+Promises
+--------
+
+You can get the result of a future when it is ready using the promise interface
+of a future. Futures expose a promise API via a ``then()`` method that utilizes
+`React's promise library <https://github.com/reactphp/promise>`_. You should
+use this API when you do not wish to block.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $request = [
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['httpbin.org']]
+ ];
+
+ $response = $handler($request);
+
+ // Use the then() method to use the promise API of the future.
+ $response->then(function ($response) {
+ echo $response['status'];
+ });
+
+You can get the promise used by a future, an instance of
+``React\Promise\PromiseInterface``, by calling the ``promise()`` method.
+
+.. code-block:: php
+
+ $response = $handler($request);
+ $promise = $response->promise();
+ $promise->then(function ($response) {
+ echo $response['status'];
+ });
+
+This promise value can be used with React's
+`aggregate promise functions <https://github.com/reactphp/promise#functions>`_.
+
+Waiting
+-------
+
+You can wait on a future to complete and retrieve the value, or *dereference*
+the future, using the ``wait()`` method. Calling the ``wait()`` method of a
+future will block until the result is available. The result is then returned or
+an exception is thrown if and exception was encountered while waiting on the
+the result. Subsequent calls to dereference a future will return the previously
+completed result or throw the previously encountered exception. Futures can be
+cancelled, which stops the computation if possible.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['httpbin.org']]
+ ]);
+
+ // You can explicitly call block to wait on a result.
+ $realizedResponse = $response->wait();
+
+ // Future responses can be used like a regular PHP array.
+ echo $response['status'];
+
+In addition to explicitly calling the ``wait()`` function, using a future like
+a normal value will implicitly trigger the ``wait()`` function.
+
+Future Responses
+----------------
+
+RingPHP uses futures to return asynchronous responses immediately. Client
+handlers always return future responses that implement
+``GuzzleHttp\Ring\Future\ArrayFutureInterface``. These future responses act
+just like normal PHP associative arrays for blocking access and provide a
+promise interface for non-blocking access.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $handler = new CurlMultiHandler();
+
+ $request = [
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['Host' => ['www.google.com']]
+ ];
+
+ $response = $handler($request);
+
+ // Use the promise API for non-blocking access to the response. The actual
+ // response value will be delivered to the promise.
+ $response->then(function ($response) {
+ echo $response['status'];
+ });
+
+ // You can wait (block) until the future is completed.
+ $response->wait();
+
+ // This will implicitly call wait(), and will block too!
+ $response['status'];
+
+.. important::
+
+ Futures that are not completed by the time the underlying handler is
+ destructed will be completed when the handler is shutting down.
+
+Cancelling
+----------
+
+Futures can be cancelled if they have not already been dereferenced.
+
+RingPHP futures are typically implemented with the
+``GuzzleHttp\Ring\Future\BaseFutureTrait``. This trait provides the cancellation
+functionality that should be common to most implementations. Cancelling a
+future response will try to prevent the request from sending over the wire.
+
+When a future is cancelled, the cancellation function is invoked and performs
+the actual work needed to cancel the request from sending if possible
+(e.g., telling an event loop to stop sending a request or to close a socket).
+If no cancellation function is provided, then a request cannot be cancelled. If
+a cancel function is provided, then it should accept the future as an argument
+and return true if the future was successfully cancelled or false if it could
+not be cancelled.
+
+Wrapping an existing Promise
+----------------------------
+
+You can easily create a future from any existing promise using the
+``GuzzleHttp\Ring\Future\FutureValue`` class. This class's constructor
+accepts a promise as the first argument, a wait function as the second
+argument, and a cancellation function as the third argument. The dereference
+function is used to force the promise to resolve (for example, manually ticking
+an event loop). The cancel function is optional and is used to tell the thing
+that created the promise that it can stop computing the result (for example,
+telling an event loop to stop transferring a request).
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Future\FutureValue;
+ use React\Promise\Deferred;
+
+ $deferred = new Deferred();
+ $promise = $deferred->promise();
+
+ $f = new FutureValue(
+ $promise,
+ function () use ($deferred) {
+ // This function is responsible for blocking and resolving the
+ // promise. Here we pass in a reference to the deferred so that
+ // it can be resolved or rejected.
+ $deferred->resolve('foo');
+ }
+ );
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/index.rst b/public/system/storage/vendor/guzzlehttp/ringphp/docs/index.rst
new file mode 100644
index 0000000..4bbce63
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/index.rst
@@ -0,0 +1,50 @@
+=======
+RingPHP
+=======
+
+Provides a simple API and specification that abstracts away the details of HTTP
+into a single PHP function. RingPHP be used to power HTTP clients and servers
+through a PHP function that accepts a request hash and returns a response hash
+that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
+allowing RingPHP to support both synchronous and asynchronous workflows.
+
+By abstracting the implementation details of different HTTP clients and
+servers, RingPHP allows you to utilize pluggable HTTP clients and servers
+without tying your application to a specific implementation.
+
+.. toctree::
+ :maxdepth: 2
+
+ spec
+ futures
+ client_middleware
+ client_handlers
+ testing
+
+.. code-block:: php
+
+ <?php
+ require 'vendor/autoload.php';
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => [
+ 'host' => ['www.google.com'],
+ 'x-foo' => ['baz']
+ ]
+ ]);
+
+ $response->then(function (array $response) {
+ echo $response['status'];
+ });
+
+ $response->wait();
+
+RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
+which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
+utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
+HTTP requests.
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/requirements.txt b/public/system/storage/vendor/guzzlehttp/ringphp/docs/requirements.txt
new file mode 100644
index 0000000..483a4e9
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/requirements.txt
@@ -0,0 +1 @@
+sphinx_rtd_theme
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/spec.rst b/public/system/storage/vendor/guzzlehttp/ringphp/docs/spec.rst
new file mode 100644
index 0000000..bc91078
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/spec.rst
@@ -0,0 +1,311 @@
+=============
+Specification
+=============
+
+RingPHP applications consist of handlers, requests, responses, and
+middleware.
+
+Handlers
+--------
+
+Handlers are implemented as a PHP ``callable`` that accept a request array
+and return a response array (``GuzzleHttp\Ring\Future\FutureArrayInterface``).
+
+For example:
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
+
+ $mockHandler = function (array $request) {
+ return new CompletedFutureArray([
+ 'status' => 200,
+ 'headers' => ['X-Foo' => ['Bar']],
+ 'body' => 'Hello!'
+ ]);
+ };
+
+This handler returns the same response each time it is invoked. All RingPHP
+handlers must return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. Use
+``GuzzleHttp\Ring\Future\CompletedFutureArray`` when returning a response that
+has already completed.
+
+Requests
+--------
+
+A request array is a PHP associative array that contains the configuration
+settings need to send a request.
+
+.. code-block:: php
+
+ $request = [
+ 'http_method' => 'GET',
+ 'scheme' => 'http',
+ 'uri' => '/',
+ 'body' => 'hello!',
+ 'client' => ['timeout' => 1.0],
+ 'headers' => [
+ 'host' => ['httpbin.org'],
+ 'X-Foo' => ['baz', 'bar']
+ ]
+ ];
+
+The request array contains the following key value pairs:
+
+request_method
+ (string, required) The HTTP request method, must be all caps corresponding
+ to a HTTP request method, such as ``GET`` or ``POST``.
+
+scheme
+ (string) The transport protocol, must be one of ``http`` or ``https``.
+ Defaults to ``http``.
+
+uri
+ (string, required) The request URI excluding the query string. Must
+ start with "/".
+
+query_string
+ (string) The query string, if present (e.g., ``foo=bar``).
+
+version
+ (string) HTTP protocol version. Defaults to ``1.1``.
+
+headers
+ (required, array) Associative array of headers. Each key represents the
+ header name. Each value contains an array of strings where each entry of
+ the array SHOULD be sent over the wire on a separate header line.
+
+body
+ (string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
+ The body of the request, if present. Can be a string, resource returned
+ from fopen, an ``Iterator`` that yields chunks of data, an object that
+ implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
+
+future
+ (bool, string) Controls the asynchronous behavior of a response.
+
+ Set to ``true`` or omit the ``future`` option to *request* that a request
+ will be completed asynchronously. Keep in mind that your request might not
+ necessarily be completed asynchronously based on the handler you are using.
+ Set the ``future`` option to ``false`` to request that a synchronous
+ response be provided.
+
+ You can provide a string value to specify fine-tuned future behaviors that
+ may be specific to the underlying handlers you are using. There are,
+ however, some common future options that handlers should implement if
+ possible.
+
+ lazy
+ Requests that the handler does not open and send the request
+ immediately, but rather only opens and sends the request once the
+ future is dereferenced. This option is often useful for sending a large
+ number of requests concurrently to allow handlers to take better
+ advantage of non-blocking transfers by first building up a pool of
+ requests.
+
+ If an handler does not implement or understand a provided string value,
+ then the request MUST be treated as if the user provided ``true`` rather
+ than the string value.
+
+ Future responses created by asynchronous handlers MUST attempt to complete
+ any outstanding future responses when they are destructed. Asynchronous
+ handlers MAY choose to automatically complete responses when the number
+ of outstanding requests reaches an handler-specific threshold.
+
+Client Specific Options
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The following options are only used in ring client handlers.
+
+.. _client-options:
+
+client
+ (array) Associative array of client specific transfer options. The
+ ``client`` request key value pair can contain the following keys:
+
+ cert
+ (string, array) Set to a string to specify the path to a file
+ containing a PEM formatted SSL client side certificate. If a password
+ is required, then set ``cert`` to an array containing the path to the
+ PEM file in the first array element followed by the certificate
+ password in the second array element.
+
+ connect_timeout
+ (float) Float describing the number of seconds to wait while trying to
+ connect to a server. Use ``0`` to wait indefinitely (the default
+ behavior).
+
+ debug
+ (bool, fopen() resource) Set to true or set to a PHP stream returned by
+ fopen() to enable debug output with the handler used to send a request.
+ If set to ``true``, the output is written to PHP's STDOUT. If a PHP
+ ``fopen`` resource handle is provided, the output is written to the
+ stream.
+
+ "Debug output" is handler specific: different handlers will yield
+ different output and various various level of detail. For example, when
+ using cURL to transfer requests, cURL's `CURLOPT_VERBOSE <http://curl.haxx.se/libcurl/c/CURLOPT_VERBOSE.html>`_
+ will be used. When using the PHP stream wrapper, `stream notifications <http://php.net/manual/en/function.stream-notification-callback.php>`_
+ will be emitted.
+
+ decode_content
+ (bool) Specify whether or not ``Content-Encoding`` responses
+ (gzip, deflate, etc.) are automatically decoded. Set to ``true`` to
+ automatically decode encoded responses. Set to ``false`` to not decode
+ responses. By default, content is *not* decoded automatically.
+
+ delay
+ (int) The number of milliseconds to delay before sending the request.
+ This is often used for delaying before retrying a request. Handlers
+ SHOULD implement this if possible, but it is not a strict requirement.
+
+ progress
+ (function) Defines a function to invoke when transfer progress is made.
+ The function accepts the following arguments:
+
+ 1. The total number of bytes expected to be downloaded
+ 2. The number of bytes downloaded so far
+ 3. The number of bytes expected to be uploaded
+ 4. The number of bytes uploaded so far
+
+ proxy
+ (string, array) Pass a string to specify an HTTP proxy, or an
+ associative array to specify different proxies for different protocols
+ where the scheme is the key and the value is the proxy address.
+
+ .. code-block:: php
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['httpbin.org']],
+ 'client' => [
+ // Use different proxies for different URI schemes.
+ 'proxy' => [
+ 'http' => 'http://proxy.example.com:5100',
+ 'https' => 'https://proxy.example.com:6100'
+ ]
+ ]
+ ];
+
+ ssl_key
+ (string, array) Specify the path to a file containing a private SSL key
+ in PEM format. If a password is required, then set to an array
+ containing the path to the SSL key in the first array element followed
+ by the password required for the certificate in the second element.
+
+ save_to
+ (string, fopen resource, ``GuzzleHttp\Stream\StreamInterface``)
+ Specifies where the body of the response is downloaded. Pass a string to
+ open a local file on disk and save the output to the file. Pass an fopen
+ resource to save the output to a PHP stream resource. Pass a
+ ``GuzzleHttp\Stream\StreamInterface`` to save the output to a Guzzle
+ StreamInterface. Omitting this option will typically save the body of a
+ response to a PHP temp stream.
+
+ stream
+ (bool) Set to true to stream a response rather than download it all
+ up-front. This option will only be utilized when the corresponding
+ handler supports it.
+
+ timeout
+ (float) Float describing the timeout of the request in seconds. Use 0 to
+ wait indefinitely (the default behavior).
+
+ verify
+ (bool, string) Describes the SSL certificate verification behavior of a
+ request. Set to true to enable SSL certificate verification using the
+ system CA bundle when available (the default). Set to false to disable
+ certificate verification (this is insecure!). Set to a string to provide
+ the path to a CA bundle on disk to enable verification using a custom
+ certificate.
+
+ version
+ (string) HTTP protocol version to use with the request.
+
+Server Specific Options
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The following options are only used in ring server handlers.
+
+server_port
+ (integer) The port on which the request is being handled. This is only
+ used with ring servers, and is required.
+
+server_name
+ (string) The resolved server name, or the server IP address. Required when
+ using a Ring server.
+
+remote_addr
+ (string) The IP address of the client or the last proxy that sent the
+ request. Required when using a Ring server.
+
+Responses
+---------
+
+A response is an array-like object that implements
+``GuzzleHttp\Ring\Future\FutureArrayInterface``. Responses contain the
+following key value pairs:
+
+body
+ (string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
+ The body of the response, if present. Can be a string, resource returned
+ from fopen, an ``Iterator`` that yields chunks of data, an object that
+ implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
+
+effective_url
+ (string) The URL that returned the resulting response.
+
+error
+ (``\Exception``) Contains an exception describing any errors that were
+ encountered during the transfer.
+
+headers
+ (Required, array) Associative array of headers. Each key represents the
+ header name. Each value contains an array of strings where each entry of
+ the array is a header line. The headers array MAY be an empty array in the
+ event an error occurred before a response was received.
+
+reason
+ (string) Optional reason phrase. This option should be provided when the
+ reason phrase does not match the typical reason phrase associated with the
+ ``status`` code. See `RFC 7231 <http://tools.ietf.org/html/rfc7231#section-6.1>`_
+ for a list of HTTP reason phrases mapped to status codes.
+
+status
+ (Required, integer) The HTTP status code. The status code MAY be set to
+ ``null`` in the event an error occurred before a response was received
+ (e.g., a networking error).
+
+transfer_stats
+ (array) Provides an associative array of arbitrary transfer statistics if
+ provided by the underlying handler.
+
+version
+ (string) HTTP protocol version. Defaults to ``1.1``.
+
+Middleware
+----------
+
+Ring middleware augments the functionality of handlers by invoking them in the
+process of generating responses. Middleware is typically implemented as a
+higher-order function that takes one or more handlers as arguments followed by
+an optional associative array of options as the last argument, returning a new
+handler with the desired compound behavior.
+
+Here's an example of a middleware that adds a Content-Type header to each
+request.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+ use GuzzleHttp\Ring\Core;
+
+ $contentTypeHandler = function(callable $handler, $contentType) {
+ return function (array $request) use ($handler, $contentType) {
+ return $handler(Core::setHeader('Content-Type', $contentType));
+ };
+ };
+
+ $baseHandler = new CurlHandler();
+ $wrappedHandler = $contentTypeHandler($baseHandler, 'text/html');
+ $response = $wrappedHandler([/** request hash **/]);
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/docs/testing.rst b/public/system/storage/vendor/guzzlehttp/ringphp/docs/testing.rst
new file mode 100644
index 0000000..9df2562
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/docs/testing.rst
@@ -0,0 +1,74 @@
+=======
+Testing
+=======
+
+RingPHP tests client handlers using `PHPUnit <https://phpunit.de/>`_ and a
+built-in node.js web server.
+
+Running Tests
+-------------
+
+First, install the dependencies using `Composer <https://getcomposer.org>`_.
+
+ composer.phar install
+
+Next, run the unit tests using ``Make``.
+
+ make test
+
+The tests are also run on Travis-CI on each commit: https://travis-ci.org/guzzle/guzzle-ring
+
+Test Server
+-----------
+
+Testing client handlers usually involves actually sending HTTP requests.
+RingPHP provides a node.js web server that returns canned responses and
+keep a list of the requests that have been received. The server can then
+be queried to get a list of the requests that were sent by the client so that
+you can ensure that the client serialized and transferred requests as intended.
+
+The server keeps a list of queued responses and returns responses that are
+popped off of the queue as HTTP requests are received. When there are not
+more responses to serve, the server returns a 500 error response.
+
+The test server uses the ``GuzzleHttp\Tests\Ring\Client\Server`` class to
+control the server.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\StreamHandler;
+ use GuzzleHttp\Tests\Ring\Client\Server;
+
+ // First return a 200 followed by a 404 response.
+ Server::enqueue([
+ ['status' => 200],
+ ['status' => 404]
+ ]);
+
+ $handler = new StreamHandler();
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/'
+ ]);
+
+ assert(200 == $response['status']);
+
+ $response = $handler([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/'
+ ]);
+
+ assert(404 == $response['status']);
+
+After requests have been sent, you can get a list of the requests as they
+were sent over the wire to ensure they were sent correctly.
+
+.. code-block:: php
+
+ $received = Server::received();
+
+ assert('GET' == $received[0]['http_method']);
+ assert('HEAD' == $received[1]['http_method']);
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/phpunit.xml.dist b/public/system/storage/vendor/guzzlehttp/ringphp/phpunit.xml.dist
new file mode 100644
index 0000000..1d19290
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/phpunit.xml.dist
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./tests/bootstrap.php"
+ colors="true">
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php
new file mode 100644
index 0000000..27d5fe7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php
@@ -0,0 +1,74 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+/**
+ * Client specific utility functions.
+ */
+class ClientUtils
+{
+ /**
+ * Returns the default cacert bundle for the current system.
+ *
+ * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
+ * If those settings are not configured, then the common locations for
+ * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
+ * and Windows are checked. If any of these file locations are found on
+ * disk, they will be utilized.
+ *
+ * Note: the result of this function is cached for subsequent calls.
+ *
+ * @return string
+ * @throws \RuntimeException if no bundle can be found.
+ */
+ public static function getDefaultCaBundle()
+ {
+ static $cached = null;
+ static $cafiles = [
+ // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
+ '/etc/pki/tls/certs/ca-bundle.crt',
+ // Ubuntu, Debian (provided by the ca-certificates package)
+ '/etc/ssl/certs/ca-certificates.crt',
+ // FreeBSD (provided by the ca_root_nss package)
+ '/usr/local/share/certs/ca-root-nss.crt',
+ // OS X provided by homebrew (using the default path)
+ '/usr/local/etc/openssl/cert.pem',
+ // Windows?
+ 'C:\\windows\\system32\\curl-ca-bundle.crt',
+ 'C:\\windows\\curl-ca-bundle.crt',
+ ];
+
+ if ($cached) {
+ return $cached;
+ }
+
+ if ($ca = ini_get('openssl.cafile')) {
+ return $cached = $ca;
+ }
+
+ if ($ca = ini_get('curl.cainfo')) {
+ return $cached = $ca;
+ }
+
+ foreach ($cafiles as $filename) {
+ if (file_exists($filename)) {
+ return $cached = $filename;
+ }
+ }
+
+ throw new \RuntimeException(self::CA_ERR);
+ }
+
+ const CA_ERR = "
+No system CA bundle could be found in any of the the common system locations.
+PHP versions earlier than 5.6 are not properly configured to use the system's
+CA bundle by default. In order to verify peer certificates, you will need to
+supply the path on disk to a certificate bundle to the 'verify' request
+option: http://docs.guzzlephp.org/en/5.3/clients.html#verify. If you do not
+need a specific certificate bundle, then Mozilla provides a commonly used CA
+bundle which can be downloaded here (provided by the maintainer of cURL):
+https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
+you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
+ini setting to point to the path to the file, allowing you to omit the 'verify'
+request option. See http://curl.haxx.se/docs/sslcerts.html for more
+information.";
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php
new file mode 100644
index 0000000..2c9eb68
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php
@@ -0,0 +1,560 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Exception\ConnectException;
+use GuzzleHttp\Ring\Exception\RingException;
+use GuzzleHttp\Stream\LazyOpenStream;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Creates curl resources from a request
+ */
+class CurlFactory
+{
+ /**
+ * Creates a cURL handle, header resource, and body resource based on a
+ * transaction.
+ *
+ * @param array $request Request hash
+ * @param null|resource $handle Optionally provide a curl handle to modify
+ *
+ * @return array Returns an array of the curl handle, headers array, and
+ * response body handle.
+ * @throws \RuntimeException when an option cannot be applied
+ */
+ public function __invoke(array $request, $handle = null)
+ {
+ $headers = [];
+ $options = $this->getDefaultOptions($request, $headers);
+ $this->applyMethod($request, $options);
+
+ if (isset($request['client'])) {
+ $this->applyHandlerOptions($request, $options);
+ }
+
+ $this->applyHeaders($request, $options);
+ unset($options['_headers']);
+
+ // Add handler options from the request's configuration options
+ if (isset($request['client']['curl'])) {
+ $options = $this->applyCustomCurlOptions(
+ $request['client']['curl'],
+ $options
+ );
+ }
+
+ if (!$handle) {
+ $handle = curl_init();
+ }
+
+ $body = $this->getOutputBody($request, $options);
+ curl_setopt_array($handle, $options);
+
+ return [$handle, &$headers, $body];
+ }
+
+ /**
+ * Creates a response hash from a cURL result.
+ *
+ * @param callable $handler Handler that was used.
+ * @param array $request Request that sent.
+ * @param array $response Response hash to update.
+ * @param array $headers Headers received during transfer.
+ * @param resource $body Body fopen response.
+ *
+ * @return array
+ */
+ public static function createResponse(
+ callable $handler,
+ array $request,
+ array $response,
+ array $headers,
+ $body
+ ) {
+ if (isset($response['transfer_stats']['url'])) {
+ $response['effective_url'] = $response['transfer_stats']['url'];
+ }
+
+ if (!empty($headers)) {
+ $startLine = explode(' ', array_shift($headers), 3);
+ $headerList = Core::headersFromLines($headers);
+ $response['headers'] = $headerList;
+ $response['version'] = isset($startLine[0]) ? substr($startLine[0], 5) : null;
+ $response['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
+ $response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
+ $response['body'] = $body;
+ Core::rewindBody($response);
+ }
+
+ return !empty($response['curl']['errno']) || !isset($response['status'])
+ ? self::createErrorResponse($handler, $request, $response)
+ : $response;
+ }
+
+ private static function createErrorResponse(
+ callable $handler,
+ array $request,
+ array $response
+ ) {
+ static $connectionErrors = [
+ CURLE_OPERATION_TIMEOUTED => true,
+ CURLE_COULDNT_RESOLVE_HOST => true,
+ CURLE_COULDNT_CONNECT => true,
+ CURLE_SSL_CONNECT_ERROR => true,
+ CURLE_GOT_NOTHING => true,
+ ];
+
+ // Retry when nothing is present or when curl failed to rewind.
+ if (!isset($response['err_message'])
+ && (empty($response['curl']['errno'])
+ || $response['curl']['errno'] == 65)
+ ) {
+ return self::retryFailedRewind($handler, $request, $response);
+ }
+
+ $message = isset($response['err_message'])
+ ? $response['err_message']
+ : sprintf('cURL error %s: %s',
+ $response['curl']['errno'],
+ isset($response['curl']['error'])
+ ? $response['curl']['error']
+ : 'See http://curl.haxx.se/libcurl/c/libcurl-errors.html');
+
+ $error = isset($response['curl']['errno'])
+ && isset($connectionErrors[$response['curl']['errno']])
+ ? new ConnectException($message)
+ : new RingException($message);
+
+ return $response + [
+ 'status' => null,
+ 'reason' => null,
+ 'body' => null,
+ 'headers' => [],
+ 'error' => $error,
+ ];
+ }
+
+ private function getOutputBody(array $request, array &$options)
+ {
+ // Determine where the body of the response (if any) will be streamed.
+ if (isset($options[CURLOPT_WRITEFUNCTION])) {
+ return $request['client']['save_to'];
+ }
+
+ if (isset($options[CURLOPT_FILE])) {
+ return $options[CURLOPT_FILE];
+ }
+
+ if ($request['http_method'] != 'HEAD') {
+ // Create a default body if one was not provided
+ return $options[CURLOPT_FILE] = fopen('php://temp', 'w+');
+ }
+
+ return null;
+ }
+
+ private function getDefaultOptions(array $request, array &$headers)
+ {
+ $url = Core::url($request);
+ $startingResponse = false;
+
+ $options = [
+ '_headers' => $request['headers'],
+ CURLOPT_CUSTOMREQUEST => $request['http_method'],
+ CURLOPT_URL => $url,
+ CURLOPT_RETURNTRANSFER => false,
+ CURLOPT_HEADER => false,
+ CURLOPT_CONNECTTIMEOUT => 150,
+ CURLOPT_HEADERFUNCTION => function ($ch, $h) use (&$headers, &$startingResponse) {
+ $value = trim($h);
+ if ($value === '') {
+ $startingResponse = true;
+ } elseif ($startingResponse) {
+ $startingResponse = false;
+ $headers = [$value];
+ } else {
+ $headers[] = $value;
+ }
+ return strlen($h);
+ },
+ ];
+
+ if (isset($request['version'])) {
+ if ($request['version'] == 2.0) {
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
+ } else if ($request['version'] == 1.1) {
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
+ } else {
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
+ }
+ }
+
+ if (defined('CURLOPT_PROTOCOLS')) {
+ $options[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
+ }
+
+ return $options;
+ }
+
+ private function applyMethod(array $request, array &$options)
+ {
+ if (isset($request['body'])) {
+ $this->applyBody($request, $options);
+ return;
+ }
+
+ switch ($request['http_method']) {
+ case 'PUT':
+ case 'POST':
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
+ if (!Core::hasHeader($request, 'Content-Length')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
+ }
+ break;
+ case 'HEAD':
+ $options[CURLOPT_NOBODY] = true;
+ unset(
+ $options[CURLOPT_WRITEFUNCTION],
+ $options[CURLOPT_READFUNCTION],
+ $options[CURLOPT_FILE],
+ $options[CURLOPT_INFILE]
+ );
+ }
+ }
+
+ private function applyBody(array $request, array &$options)
+ {
+ $contentLength = Core::firstHeader($request, 'Content-Length');
+ $size = $contentLength !== null ? (int) $contentLength : null;
+
+ // Send the body as a string if the size is less than 1MB OR if the
+ // [client][curl][body_as_string] request value is set.
+ if (($size !== null && $size < 1000000) ||
+ isset($request['client']['curl']['body_as_string']) ||
+ is_string($request['body'])
+ ) {
+ $options[CURLOPT_POSTFIELDS] = Core::body($request);
+ // Don't duplicate the Content-Length header
+ $this->removeHeader('Content-Length', $options);
+ $this->removeHeader('Transfer-Encoding', $options);
+ } else {
+ $options[CURLOPT_UPLOAD] = true;
+ if ($size !== null) {
+ // Let cURL handle setting the Content-Length header
+ $options[CURLOPT_INFILESIZE] = $size;
+ $this->removeHeader('Content-Length', $options);
+ }
+ $this->addStreamingBody($request, $options);
+ }
+
+ // If the Expect header is not present, prevent curl from adding it
+ if (!Core::hasHeader($request, 'Expect')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Expect:';
+ }
+
+ // cURL sometimes adds a content-type by default. Prevent this.
+ if (!Core::hasHeader($request, 'Content-Type')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Type:';
+ }
+ }
+
+ private function addStreamingBody(array $request, array &$options)
+ {
+ $body = $request['body'];
+
+ if ($body instanceof StreamInterface) {
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
+ return (string) $body->read($length);
+ };
+ if (!isset($options[CURLOPT_INFILESIZE])) {
+ if ($size = $body->getSize()) {
+ $options[CURLOPT_INFILESIZE] = $size;
+ }
+ }
+ } elseif (is_resource($body)) {
+ $options[CURLOPT_INFILE] = $body;
+ } elseif ($body instanceof \Iterator) {
+ $buf = '';
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body, &$buf) {
+ if ($body->valid()) {
+ $buf .= $body->current();
+ $body->next();
+ }
+ $result = (string) substr($buf, 0, $length);
+ $buf = substr($buf, $length);
+ return $result;
+ };
+ } else {
+ throw new \InvalidArgumentException('Invalid request body provided');
+ }
+ }
+
+ private function applyHeaders(array $request, array &$options)
+ {
+ foreach ($options['_headers'] as $name => $values) {
+ foreach ($values as $value) {
+ $options[CURLOPT_HTTPHEADER][] = "$name: $value";
+ }
+ }
+
+ // Remove the Accept header if one was not set
+ if (!Core::hasHeader($request, 'Accept')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Accept:';
+ }
+ }
+
+ /**
+ * Takes an array of curl options specified in the 'curl' option of a
+ * request's configuration array and maps them to CURLOPT_* options.
+ *
+ * This method is only called when a request has a 'curl' config setting.
+ *
+ * @param array $config Configuration array of custom curl option
+ * @param array $options Array of existing curl options
+ *
+ * @return array Returns a new array of curl options
+ */
+ private function applyCustomCurlOptions(array $config, array $options)
+ {
+ $curlOptions = [];
+ foreach ($config as $key => $value) {
+ if (is_int($key)) {
+ $curlOptions[$key] = $value;
+ }
+ }
+
+ return $curlOptions + $options;
+ }
+
+ /**
+ * Remove a header from the options array.
+ *
+ * @param string $name Case-insensitive header to remove
+ * @param array $options Array of options to modify
+ */
+ private function removeHeader($name, array &$options)
+ {
+ foreach (array_keys($options['_headers']) as $key) {
+ if (!strcasecmp($key, $name)) {
+ unset($options['_headers'][$key]);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Applies an array of request client options to a the options array.
+ *
+ * This method uses a large switch rather than double-dispatch to save on
+ * high overhead of calling functions in PHP.
+ */
+ private function applyHandlerOptions(array $request, array &$options)
+ {
+ foreach ($request['client'] as $key => $value) {
+ switch ($key) {
+ // Violating PSR-4 to provide more room.
+ case 'verify':
+
+ if ($value === false) {
+ unset($options[CURLOPT_CAINFO]);
+ $options[CURLOPT_SSL_VERIFYHOST] = 0;
+ $options[CURLOPT_SSL_VERIFYPEER] = false;
+ continue 2;
+ }
+
+ $options[CURLOPT_SSL_VERIFYHOST] = 2;
+ $options[CURLOPT_SSL_VERIFYPEER] = true;
+
+ if (is_string($value)) {
+ $options[CURLOPT_CAINFO] = $value;
+ if (!file_exists($value)) {
+ throw new \InvalidArgumentException(
+ "SSL CA bundle not found: $value"
+ );
+ }
+ }
+ break;
+
+ case 'decode_content':
+
+ if ($value === false) {
+ continue 2;
+ }
+
+ $accept = Core::firstHeader($request, 'Accept-Encoding');
+ if ($accept) {
+ $options[CURLOPT_ENCODING] = $accept;
+ } else {
+ $options[CURLOPT_ENCODING] = '';
+ // Don't let curl send the header over the wire
+ $options[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
+ }
+ break;
+
+ case 'save_to':
+
+ if (is_string($value)) {
+ if (!is_dir(dirname($value))) {
+ throw new \RuntimeException(sprintf(
+ 'Directory %s does not exist for save_to value of %s',
+ dirname($value),
+ $value
+ ));
+ }
+ $value = new LazyOpenStream($value, 'w+');
+ }
+
+ if ($value instanceof StreamInterface) {
+ $options[CURLOPT_WRITEFUNCTION] =
+ function ($ch, $write) use ($value) {
+ return $value->write($write);
+ };
+ } elseif (is_resource($value)) {
+ $options[CURLOPT_FILE] = $value;
+ } else {
+ throw new \InvalidArgumentException('save_to must be a '
+ . 'GuzzleHttp\Stream\StreamInterface or resource');
+ }
+ break;
+
+ case 'timeout':
+
+ if (defined('CURLOPT_TIMEOUT_MS')) {
+ $options[CURLOPT_TIMEOUT_MS] = $value * 1000;
+ } else {
+ $options[CURLOPT_TIMEOUT] = $value;
+ }
+ break;
+
+ case 'connect_timeout':
+
+ if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
+ $options[CURLOPT_CONNECTTIMEOUT_MS] = $value * 1000;
+ } else {
+ $options[CURLOPT_CONNECTTIMEOUT] = $value;
+ }
+ break;
+
+ case 'proxy':
+
+ if (!is_array($value)) {
+ $options[CURLOPT_PROXY] = $value;
+ } elseif (isset($request['scheme'])) {
+ $scheme = $request['scheme'];
+ if (isset($value[$scheme])) {
+ $options[CURLOPT_PROXY] = $value[$scheme];
+ }
+ }
+ break;
+
+ case 'cert':
+
+ if (is_array($value)) {
+ $options[CURLOPT_SSLCERTPASSWD] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new \InvalidArgumentException(
+ "SSL certificate not found: {$value}"
+ );
+ }
+
+ $options[CURLOPT_SSLCERT] = $value;
+ break;
+
+ case 'ssl_key':
+
+ if (is_array($value)) {
+ $options[CURLOPT_SSLKEYPASSWD] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new \InvalidArgumentException(
+ "SSL private key not found: {$value}"
+ );
+ }
+
+ $options[CURLOPT_SSLKEY] = $value;
+ break;
+
+ case 'progress':
+
+ if (!is_callable($value)) {
+ throw new \InvalidArgumentException(
+ 'progress client option must be callable'
+ );
+ }
+
+ $options[CURLOPT_NOPROGRESS] = false;
+ $options[CURLOPT_PROGRESSFUNCTION] =
+ function () use ($value) {
+ $args = func_get_args();
+ // PHP 5.5 pushed the handle onto the start of the args
+ if (is_resource($args[0])) {
+ array_shift($args);
+ }
+ call_user_func_array($value, $args);
+ };
+ break;
+
+ case 'debug':
+
+ if ($value) {
+ $options[CURLOPT_STDERR] = Core::getDebugResource($value);
+ $options[CURLOPT_VERBOSE] = true;
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * This function ensures that a response was set on a transaction. If one
+ * was not set, then the request is retried if possible. This error
+ * typically means you are sending a payload, curl encountered a
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
+ * stream, and then encountered a "necessary data rewind wasn't possible"
+ * error, causing the request to be sent through curl_multi_info_read()
+ * without an error status.
+ */
+ private static function retryFailedRewind(
+ callable $handler,
+ array $request,
+ array $response
+ ) {
+ // If there is no body, then there is some other kind of issue. This
+ // is weird and should probably never happen.
+ if (!isset($request['body'])) {
+ $response['err_message'] = 'No response was received for a request '
+ . 'with no body. This could mean that you are saturating your '
+ . 'network.';
+ return self::createErrorResponse($handler, $request, $response);
+ }
+
+ if (!Core::rewindBody($request)) {
+ $response['err_message'] = 'The connection unexpectedly failed '
+ . 'without providing an error. The request would have been '
+ . 'retried, but attempting to rewind the request body failed.';
+ return self::createErrorResponse($handler, $request, $response);
+ }
+
+ // Retry no more than 3 times before giving up.
+ if (!isset($request['curl']['retries'])) {
+ $request['curl']['retries'] = 1;
+ } elseif ($request['curl']['retries'] == 2) {
+ $response['err_message'] = 'The cURL request was retried 3 times '
+ . 'and did no succeed. cURL was unable to rewind the body of '
+ . 'the request and subsequent retries resulted in the same '
+ . 'error. Turn on the debug option to see what went wrong. '
+ . 'See https://bugs.php.net/bug.php?id=47204 for more information.';
+ return self::createErrorResponse($handler, $request, $response);
+ } else {
+ $request['curl']['retries']++;
+ }
+
+ return $handler($request);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php
new file mode 100644
index 0000000..e00aa4e
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php
@@ -0,0 +1,135 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Ring\Core;
+
+/**
+ * HTTP handler that uses cURL easy handles as a transport layer.
+ *
+ * Requires PHP 5.5+
+ *
+ * When using the CurlHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the "client" key of the request.
+ */
+class CurlHandler
+{
+ /** @var callable */
+ private $factory;
+
+ /** @var array Array of curl easy handles */
+ private $handles = [];
+
+ /** @var array Array of owned curl easy handles */
+ private $ownedHandles = [];
+
+ /** @var int Total number of idle handles to keep in cache */
+ private $maxHandles;
+
+ /**
+ * Accepts an associative array of options:
+ *
+ * - factory: Optional callable factory used to create cURL handles.
+ * The callable is passed a request hash when invoked, and returns an
+ * array of the curl handle, headers resource, and body resource.
+ * - max_handles: Maximum number of idle handles (defaults to 5).
+ *
+ * @param array $options Array of options to use with the handler
+ */
+ public function __construct(array $options = [])
+ {
+ $this->handles = $this->ownedHandles = [];
+ $this->factory = isset($options['handle_factory'])
+ ? $options['handle_factory']
+ : new CurlFactory();
+ $this->maxHandles = isset($options['max_handles'])
+ ? $options['max_handles']
+ : 5;
+ }
+
+ public function __destruct()
+ {
+ foreach ($this->handles as $handle) {
+ if (is_resource($handle)) {
+ curl_close($handle);
+ }
+ }
+ }
+
+ /**
+ * @param array $request
+ *
+ * @return CompletedFutureArray
+ */
+ public function __invoke(array $request)
+ {
+ return new CompletedFutureArray(
+ $this->_invokeAsArray($request)
+ );
+ }
+
+ /**
+ * @internal
+ *
+ * @param array $request
+ *
+ * @return array
+ */
+ public function _invokeAsArray(array $request)
+ {
+ $factory = $this->factory;
+
+ // Ensure headers are by reference. They're updated elsewhere.
+ $result = $factory($request, $this->checkoutEasyHandle());
+ $h = $result[0];
+ $hd =& $result[1];
+ $bd = $result[2];
+ Core::doSleep($request);
+ curl_exec($h);
+ $response = ['transfer_stats' => curl_getinfo($h)];
+ $response['curl']['error'] = curl_error($h);
+ $response['curl']['errno'] = curl_errno($h);
+ $response['transfer_stats'] = array_merge($response['transfer_stats'], $response['curl']);
+ $this->releaseEasyHandle($h);
+
+ return CurlFactory::createResponse([$this, '_invokeAsArray'], $request, $response, $hd, $bd);
+ }
+
+ private function checkoutEasyHandle()
+ {
+ // Find an unused handle in the cache
+ if (false !== ($key = array_search(false, $this->ownedHandles, true))) {
+ $this->ownedHandles[$key] = true;
+ return $this->handles[$key];
+ }
+
+ // Add a new handle
+ $handle = curl_init();
+ $id = (int) $handle;
+ $this->handles[$id] = $handle;
+ $this->ownedHandles[$id] = true;
+
+ return $handle;
+ }
+
+ private function releaseEasyHandle($handle)
+ {
+ $id = (int) $handle;
+ if (count($this->ownedHandles) > $this->maxHandles) {
+ curl_close($this->handles[$id]);
+ unset($this->handles[$id], $this->ownedHandles[$id]);
+ } else {
+ // curl_reset doesn't clear these out for some reason
+ static $unsetValues = [
+ CURLOPT_HEADERFUNCTION => null,
+ CURLOPT_WRITEFUNCTION => null,
+ CURLOPT_READFUNCTION => null,
+ CURLOPT_PROGRESSFUNCTION => null,
+ ];
+ curl_setopt_array($handle, $unsetValues);
+ curl_reset($handle);
+ $this->ownedHandles[$id] = false;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php
new file mode 100644
index 0000000..f84cf19
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php
@@ -0,0 +1,248 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Future\FutureArray;
+use React\Promise\Deferred;
+
+/**
+ * Returns an asynchronous response using curl_multi_* functions.
+ *
+ * This handler supports future responses and the "delay" request client
+ * option that can be used to delay before sending a request.
+ *
+ * When using the CurlMultiHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the "client" key of the request.
+ *
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
+ */
+class CurlMultiHandler
+{
+ /** @var callable */
+ private $factory;
+ private $selectTimeout;
+ private $active;
+ private $handles = [];
+ private $delays = [];
+ private $maxHandles;
+
+ /**
+ * This handler accepts the following options:
+ *
+ * - mh: An optional curl_multi resource
+ * - handle_factory: An optional callable used to generate curl handle
+ * resources. the callable accepts a request hash and returns an array
+ * of the handle, headers file resource, and the body resource.
+ * - select_timeout: Optional timeout (in seconds) to block before timing
+ * out while selecting curl handles. Defaults to 1 second.
+ * - max_handles: Optional integer representing the maximum number of
+ * open requests. When this number is reached, the queued futures are
+ * flushed.
+ *
+ * @param array $options
+ */
+ public function __construct(array $options = [])
+ {
+ if (isset($options['mh'])) {
+ $this->_mh = $options['mh'];
+ }
+ $this->factory = isset($options['handle_factory'])
+ ? $options['handle_factory'] : new CurlFactory();
+ $this->selectTimeout = isset($options['select_timeout'])
+ ? $options['select_timeout'] : 1;
+ $this->maxHandles = isset($options['max_handles'])
+ ? $options['max_handles'] : 100;
+ }
+
+ public function __get($name)
+ {
+ if ($name === '_mh') {
+ return $this->_mh = curl_multi_init();
+ }
+
+ throw new \BadMethodCallException();
+ }
+
+ public function __destruct()
+ {
+ // Finish any open connections before terminating the script.
+ if ($this->handles) {
+ $this->execute();
+ }
+
+ if (isset($this->_mh)) {
+ curl_multi_close($this->_mh);
+ unset($this->_mh);
+ }
+ }
+
+ public function __invoke(array $request)
+ {
+ $factory = $this->factory;
+ $result = $factory($request);
+ $entry = [
+ 'request' => $request,
+ 'response' => [],
+ 'handle' => $result[0],
+ 'headers' => &$result[1],
+ 'body' => $result[2],
+ 'deferred' => new Deferred(),
+ ];
+
+ $id = (int) $result[0];
+
+ $future = new FutureArray(
+ $entry['deferred']->promise(),
+ [$this, 'execute'],
+ function () use ($id) {
+ return $this->cancel($id);
+ }
+ );
+
+ $this->addRequest($entry);
+
+ // Transfer outstanding requests if there are too many open handles.
+ if (count($this->handles) >= $this->maxHandles) {
+ $this->execute();
+ }
+
+ return $future;
+ }
+
+ /**
+ * Runs until all outstanding connections have completed.
+ */
+ public function execute()
+ {
+ do {
+
+ if ($this->active &&
+ curl_multi_select($this->_mh, $this->selectTimeout) === -1
+ ) {
+ // Perform a usleep if a select returns -1.
+ // See: https://bugs.php.net/bug.php?id=61141
+ usleep(250);
+ }
+
+ // Add any delayed futures if needed.
+ if ($this->delays) {
+ $this->addDelays();
+ }
+
+ do {
+ $mrc = curl_multi_exec($this->_mh, $this->active);
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
+
+ $this->processMessages();
+
+ // If there are delays but no transfers, then sleep for a bit.
+ if (!$this->active && $this->delays) {
+ usleep(500);
+ }
+
+ } while ($this->active || $this->handles);
+ }
+
+ private function addRequest(array &$entry)
+ {
+ $id = (int) $entry['handle'];
+ $this->handles[$id] = $entry;
+
+ // If the request is a delay, then add the reques to the curl multi
+ // pool only after the specified delay.
+ if (isset($entry['request']['client']['delay'])) {
+ $this->delays[$id] = microtime(true) + ($entry['request']['client']['delay'] / 1000);
+ } elseif (empty($entry['request']['future'])) {
+ curl_multi_add_handle($this->_mh, $entry['handle']);
+ } else {
+ curl_multi_add_handle($this->_mh, $entry['handle']);
+ // "lazy" futures are only sent once the pool has many requests.
+ if ($entry['request']['future'] !== 'lazy') {
+ do {
+ $mrc = curl_multi_exec($this->_mh, $this->active);
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
+ $this->processMessages();
+ }
+ }
+ }
+
+ private function removeProcessed($id)
+ {
+ if (isset($this->handles[$id])) {
+ curl_multi_remove_handle(
+ $this->_mh,
+ $this->handles[$id]['handle']
+ );
+ curl_close($this->handles[$id]['handle']);
+ unset($this->handles[$id], $this->delays[$id]);
+ }
+ }
+
+ /**
+ * Cancels a handle from sending and removes references to it.
+ *
+ * @param int $id Handle ID to cancel and remove.
+ *
+ * @return bool True on success, false on failure.
+ */
+ private function cancel($id)
+ {
+ // Cannot cancel if it has been processed.
+ if (!isset($this->handles[$id])) {
+ return false;
+ }
+
+ $handle = $this->handles[$id]['handle'];
+ unset($this->delays[$id], $this->handles[$id]);
+ curl_multi_remove_handle($this->_mh, $handle);
+ curl_close($handle);
+
+ return true;
+ }
+
+ private function addDelays()
+ {
+ $currentTime = microtime(true);
+
+ foreach ($this->delays as $id => $delay) {
+ if ($currentTime >= $delay) {
+ unset($this->delays[$id]);
+ curl_multi_add_handle(
+ $this->_mh,
+ $this->handles[$id]['handle']
+ );
+ }
+ }
+ }
+
+ private function processMessages()
+ {
+ while ($done = curl_multi_info_read($this->_mh)) {
+ $id = (int) $done['handle'];
+
+ if (!isset($this->handles[$id])) {
+ // Probably was cancelled.
+ continue;
+ }
+
+ $entry = $this->handles[$id];
+ $entry['response']['transfer_stats'] = curl_getinfo($done['handle']);
+
+ if ($done['result'] !== CURLM_OK) {
+ $entry['response']['curl']['errno'] = $done['result'];
+ $entry['response']['curl']['error'] = curl_error($done['handle']);
+ }
+
+ $result = CurlFactory::createResponse(
+ $this,
+ $entry['request'],
+ $entry['response'],
+ $entry['headers'],
+ $entry['body']
+ );
+
+ $this->removeProcessed($id);
+ $entry['deferred']->resolve($result);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/Middleware.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/Middleware.php
new file mode 100644
index 0000000..6fa7318
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/Middleware.php
@@ -0,0 +1,58 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+/**
+ * Provides basic middleware wrappers.
+ *
+ * If a middleware is more complex than a few lines of code, then it should
+ * be implemented in a class rather than a static method.
+ */
+class Middleware
+{
+ /**
+ * Sends future requests to a future compatible handler while sending all
+ * other requests to a default handler.
+ *
+ * When the "future" option is not provided on a request, any future responses
+ * are automatically converted to synchronous responses and block.
+ *
+ * @param callable $default Handler used for non-streaming responses
+ * @param callable $future Handler used for future responses
+ *
+ * @return callable Returns the composed handler.
+ */
+ public static function wrapFuture(
+ callable $default,
+ callable $future
+ ) {
+ return function (array $request) use ($default, $future) {
+ return empty($request['client']['future'])
+ ? $default($request)
+ : $future($request);
+ };
+ }
+
+ /**
+ * Sends streaming requests to a streaming compatible handler while sendin
+ * all other requests to a default handler.
+ *
+ * This, for example, could be useful for taking advantage of the
+ * performance benefits of curl while still supporting true streaming
+ * through the StreamHandler.
+ *
+ * @param callable $default Handler used for non-streaming responses
+ * @param callable $streaming Handler used for streaming responses
+ *
+ * @return callable Returns the composed handler.
+ */
+ public static function wrapStreaming(
+ callable $default,
+ callable $streaming
+ ) {
+ return function (array $request) use ($default, $streaming) {
+ return empty($request['client']['stream'])
+ ? $default($request)
+ : $streaming($request);
+ };
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php
new file mode 100644
index 0000000..56cc32d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php
@@ -0,0 +1,52 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Ring\Future\FutureArrayInterface;
+
+/**
+ * Ring handler that returns a canned response or evaluated function result.
+ */
+class MockHandler
+{
+ /** @var callable|array|FutureArrayInterface */
+ private $result;
+
+ /**
+ * Provide an array or future to always return the same value. Provide a
+ * callable that accepts a request object and returns an array or future
+ * to dynamically create a response.
+ *
+ * @param array|FutureArrayInterface|callable $result Mock return value.
+ */
+ public function __construct($result)
+ {
+ $this->result = $result;
+ }
+
+ public function __invoke(array $request)
+ {
+ Core::doSleep($request);
+ $response = is_callable($this->result)
+ ? call_user_func($this->result, $request)
+ : $this->result;
+
+ if (is_array($response)) {
+ $response = new CompletedFutureArray($response + [
+ 'status' => null,
+ 'body' => null,
+ 'headers' => [],
+ 'reason' => null,
+ 'effective_url' => null,
+ ]);
+ } elseif (!$response instanceof FutureArrayInterface) {
+ throw new \InvalidArgumentException(
+ 'Response must be an array or FutureArrayInterface. Found '
+ . Core::describeType($request)
+ );
+ }
+
+ return $response;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php
new file mode 100644
index 0000000..4bacec1
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php
@@ -0,0 +1,414 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Exception\ConnectException;
+use GuzzleHttp\Ring\Exception\RingException;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Stream\InflateStream;
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\Utils;
+
+/**
+ * RingPHP client handler that uses PHP's HTTP stream wrapper.
+ */
+class StreamHandler
+{
+ private $options;
+ private $lastHeaders;
+
+ public function __construct(array $options = [])
+ {
+ $this->options = $options;
+ }
+
+ public function __invoke(array $request)
+ {
+ $url = Core::url($request);
+ Core::doSleep($request);
+
+ try {
+ // Does not support the expect header.
+ $request = Core::removeHeader($request, 'Expect');
+ $stream = $this->createStream($url, $request);
+ return $this->createResponse($request, $url, $stream);
+ } catch (RingException $e) {
+ return $this->createErrorResponse($url, $e);
+ }
+ }
+
+ private function createResponse(array $request, $url, $stream)
+ {
+ $hdrs = $this->lastHeaders;
+ $this->lastHeaders = null;
+ $parts = explode(' ', array_shift($hdrs), 3);
+ $response = [
+ 'version' => substr($parts[0], 5),
+ 'status' => $parts[1],
+ 'reason' => isset($parts[2]) ? $parts[2] : null,
+ 'headers' => Core::headersFromLines($hdrs),
+ 'effective_url' => $url,
+ ];
+
+ $stream = $this->checkDecode($request, $response, $stream);
+
+ // If not streaming, then drain the response into a stream.
+ if (empty($request['client']['stream'])) {
+ $dest = isset($request['client']['save_to'])
+ ? $request['client']['save_to']
+ : fopen('php://temp', 'r+');
+ $stream = $this->drain($stream, $dest);
+ }
+
+ $response['body'] = $stream;
+
+ return new CompletedFutureArray($response);
+ }
+
+ private function checkDecode(array $request, array $response, $stream)
+ {
+ // Automatically decode responses when instructed.
+ if (!empty($request['client']['decode_content'])) {
+ switch (Core::firstHeader($response, 'Content-Encoding', true)) {
+ case 'gzip':
+ case 'deflate':
+ $stream = new InflateStream(Stream::factory($stream));
+ break;
+ }
+ }
+
+ return $stream;
+ }
+
+ /**
+ * Drains the stream into the "save_to" client option.
+ *
+ * @param resource $stream
+ * @param string|resource|StreamInterface $dest
+ *
+ * @return Stream
+ * @throws \RuntimeException when the save_to option is invalid.
+ */
+ private function drain($stream, $dest)
+ {
+ if (is_resource($stream)) {
+ if (!is_resource($dest)) {
+ $stream = Stream::factory($stream);
+ } else {
+ stream_copy_to_stream($stream, $dest);
+ fclose($stream);
+ rewind($dest);
+ return $dest;
+ }
+ }
+
+ // Stream the response into the destination stream
+ $dest = is_string($dest)
+ ? new Stream(Utils::open($dest, 'r+'))
+ : Stream::factory($dest);
+
+ Utils::copyToStream($stream, $dest);
+ $dest->seek(0);
+ $stream->close();
+
+ return $dest;
+ }
+
+ /**
+ * Creates an error response for the given stream.
+ *
+ * @param string $url
+ * @param RingException $e
+ *
+ * @return array
+ */
+ private function createErrorResponse($url, RingException $e)
+ {
+ // Determine if the error was a networking error.
+ $message = $e->getMessage();
+
+ // This list can probably get more comprehensive.
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
+ || strpos($message, 'Connection refused')
+ ) {
+ $e = new ConnectException($e->getMessage(), 0, $e);
+ }
+
+ return new CompletedFutureArray([
+ 'status' => null,
+ 'body' => null,
+ 'headers' => [],
+ 'effective_url' => $url,
+ 'error' => $e
+ ]);
+ }
+
+ /**
+ * Create a resource and check to ensure it was created successfully
+ *
+ * @param callable $callback Callable that returns stream resource
+ *
+ * @return resource
+ * @throws \RuntimeException on error
+ */
+ private function createResource(callable $callback)
+ {
+ $errors = null;
+ set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
+ $errors[] = [
+ 'message' => $msg,
+ 'file' => $file,
+ 'line' => $line
+ ];
+ return true;
+ });
+
+ $resource = $callback();
+ restore_error_handler();
+
+ if (!$resource) {
+ $message = 'Error creating resource: ';
+ foreach ($errors as $err) {
+ foreach ($err as $key => $value) {
+ $message .= "[$key] $value" . PHP_EOL;
+ }
+ }
+ throw new RingException(trim($message));
+ }
+
+ return $resource;
+ }
+
+ private function createStream($url, array $request)
+ {
+ static $methods;
+ if (!$methods) {
+ $methods = array_flip(get_class_methods(__CLASS__));
+ }
+
+ // HTTP/1.1 streams using the PHP stream wrapper require a
+ // Connection: close header
+ if ((!isset($request['version']) || $request['version'] == '1.1')
+ && !Core::hasHeader($request, 'Connection')
+ ) {
+ $request['headers']['Connection'] = ['close'];
+ }
+
+ // Ensure SSL is verified by default
+ if (!isset($request['client']['verify'])) {
+ $request['client']['verify'] = true;
+ }
+
+ $params = [];
+ $options = $this->getDefaultOptions($request);
+
+ if (isset($request['client'])) {
+ foreach ($request['client'] as $key => $value) {
+ $method = "add_{$key}";
+ if (isset($methods[$method])) {
+ $this->{$method}($request, $options, $value, $params);
+ }
+ }
+ }
+
+ return $this->createStreamResource(
+ $url,
+ $request,
+ $options,
+ $this->createContext($request, $options, $params)
+ );
+ }
+
+ private function getDefaultOptions(array $request)
+ {
+ $headers = "";
+ foreach ($request['headers'] as $name => $value) {
+ foreach ((array) $value as $val) {
+ $headers .= "$name: $val\r\n";
+ }
+ }
+
+ $context = [
+ 'http' => [
+ 'method' => $request['http_method'],
+ 'header' => $headers,
+ 'protocol_version' => isset($request['version']) ? $request['version'] : 1.1,
+ 'ignore_errors' => true,
+ 'follow_location' => 0,
+ ],
+ ];
+
+ $body = Core::body($request);
+ if (isset($body)) {
+ $context['http']['content'] = $body;
+ // Prevent the HTTP handler from adding a Content-Type header.
+ if (!Core::hasHeader($request, 'Content-Type')) {
+ $context['http']['header'] .= "Content-Type:\r\n";
+ }
+ }
+
+ $context['http']['header'] = rtrim($context['http']['header']);
+
+ return $context;
+ }
+
+ private function add_proxy(array $request, &$options, $value, &$params)
+ {
+ if (!is_array($value)) {
+ $options['http']['proxy'] = $value;
+ } else {
+ $scheme = isset($request['scheme']) ? $request['scheme'] : 'http';
+ if (isset($value[$scheme])) {
+ $options['http']['proxy'] = $value[$scheme];
+ }
+ }
+ }
+
+ private function add_timeout(array $request, &$options, $value, &$params)
+ {
+ $options['http']['timeout'] = $value;
+ }
+
+ private function add_verify(array $request, &$options, $value, &$params)
+ {
+ if ($value === true) {
+ // PHP 5.6 or greater will find the system cert by default. When
+ // < 5.6, use the Guzzle bundled cacert.
+ if (PHP_VERSION_ID < 50600) {
+ $options['ssl']['cafile'] = ClientUtils::getDefaultCaBundle();
+ }
+ } elseif (is_string($value)) {
+ $options['ssl']['cafile'] = $value;
+ if (!file_exists($value)) {
+ throw new RingException("SSL CA bundle not found: $value");
+ }
+ } elseif ($value === false) {
+ $options['ssl']['verify_peer'] = false;
+ $options['ssl']['allow_self_signed'] = true;
+ return;
+ } else {
+ throw new RingException('Invalid verify request option');
+ }
+
+ $options['ssl']['verify_peer'] = true;
+ $options['ssl']['allow_self_signed'] = false;
+ }
+
+ private function add_cert(array $request, &$options, $value, &$params)
+ {
+ if (is_array($value)) {
+ $options['ssl']['passphrase'] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new RingException("SSL certificate not found: {$value}");
+ }
+
+ $options['ssl']['local_cert'] = $value;
+ }
+
+ private function add_progress(array $request, &$options, $value, &$params)
+ {
+ $fn = function ($code, $_1, $_2, $_3, $transferred, $total) use ($value) {
+ if ($code == STREAM_NOTIFY_PROGRESS) {
+ $value($total, $transferred, null, null);
+ }
+ };
+
+ // Wrap the existing function if needed.
+ $params['notification'] = isset($params['notification'])
+ ? Core::callArray([$params['notification'], $fn])
+ : $fn;
+ }
+
+ private function add_debug(array $request, &$options, $value, &$params)
+ {
+ if ($value === false) {
+ return;
+ }
+
+ static $map = [
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
+ ];
+
+ static $args = ['severity', 'message', 'message_code',
+ 'bytes_transferred', 'bytes_max'];
+
+ $value = Core::getDebugResource($value);
+ $ident = $request['http_method'] . ' ' . Core::url($request);
+ $fn = function () use ($ident, $value, $map, $args) {
+ $passed = func_get_args();
+ $code = array_shift($passed);
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
+ foreach (array_filter($passed) as $i => $v) {
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
+ }
+ fwrite($value, "\n");
+ };
+
+ // Wrap the existing function if needed.
+ $params['notification'] = isset($params['notification'])
+ ? Core::callArray([$params['notification'], $fn])
+ : $fn;
+ }
+
+ private function applyCustomOptions(array $request, array &$options)
+ {
+ if (!isset($request['client']['stream_context'])) {
+ return;
+ }
+
+ if (!is_array($request['client']['stream_context'])) {
+ throw new RingException('stream_context must be an array');
+ }
+
+ $options = array_replace_recursive(
+ $options,
+ $request['client']['stream_context']
+ );
+ }
+
+ private function createContext(array $request, array $options, array $params)
+ {
+ $this->applyCustomOptions($request, $options);
+ return $this->createResource(
+ function () use ($request, $options, $params) {
+ return stream_context_create($options, $params);
+ },
+ $request,
+ $options
+ );
+ }
+
+ private function createStreamResource(
+ $url,
+ array $request,
+ array $options,
+ $context
+ ) {
+ return $this->createResource(
+ function () use ($url, $context) {
+ if (false === strpos($url, 'http')) {
+ trigger_error("URL is invalid: {$url}", E_USER_WARNING);
+ return null;
+ }
+ $resource = fopen($url, 'r', null, $context);
+ $this->lastHeaders = $http_response_header;
+ return $resource;
+ },
+ $request,
+ $options
+ );
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Core.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Core.php
new file mode 100644
index 0000000..dd7d1a0
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Core.php
@@ -0,0 +1,364 @@
+<?php
+namespace GuzzleHttp\Ring;
+
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Ring\Future\FutureArrayInterface;
+use GuzzleHttp\Ring\Future\FutureArray;
+
+/**
+ * Provides core functionality of Ring handlers and middleware.
+ */
+class Core
+{
+ /**
+ * Returns a function that calls all of the provided functions, in order,
+ * passing the arguments provided to the composed function to each function.
+ *
+ * @param callable[] $functions Array of functions to proxy to.
+ *
+ * @return callable
+ */
+ public static function callArray(array $functions)
+ {
+ return function () use ($functions) {
+ $args = func_get_args();
+ foreach ($functions as $fn) {
+ call_user_func_array($fn, $args);
+ }
+ };
+ }
+
+ /**
+ * Gets an array of header line values from a message for a specific header
+ *
+ * This method searches through the "headers" key of a message for a header
+ * using a case-insensitive search.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to retrieve
+ *
+ * @return array
+ */
+ public static function headerLines($message, $header)
+ {
+ $result = [];
+
+ if (!empty($message['headers'])) {
+ foreach ($message['headers'] as $name => $value) {
+ if (!strcasecmp($name, $header)) {
+ $result = array_merge($result, $value);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Gets a header value from a message as a string or null
+ *
+ * This method searches through the "headers" key of a message for a header
+ * using a case-insensitive search. The lines of the header are imploded
+ * using commas into a single string return value.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to retrieve
+ *
+ * @return string|null Returns the header string if found, or null if not.
+ */
+ public static function header($message, $header)
+ {
+ $match = self::headerLines($message, $header);
+ return $match ? implode(', ', $match) : null;
+ }
+
+ /**
+ * Returns the first header value from a message as a string or null. If
+ * a header line contains multiple values separated by a comma, then this
+ * function will return the first value in the list.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to retrieve
+ *
+ * @return string|null Returns the value as a string if found.
+ */
+ public static function firstHeader($message, $header)
+ {
+ if (!empty($message['headers'])) {
+ foreach ($message['headers'] as $name => $value) {
+ if (!strcasecmp($name, $header)) {
+ // Return the match itself if it is a single value.
+ $pos = strpos($value[0], ',');
+ return $pos ? substr($value[0], 0, $pos) : $value[0];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if a message has the provided case-insensitive header.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to check
+ *
+ * @return bool
+ */
+ public static function hasHeader($message, $header)
+ {
+ if (!empty($message['headers'])) {
+ foreach ($message['headers'] as $name => $value) {
+ if (!strcasecmp($name, $header)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Parses an array of header lines into an associative array of headers.
+ *
+ * @param array $lines Header lines array of strings in the following
+ * format: "Name: Value"
+ * @return array
+ */
+ public static function headersFromLines($lines)
+ {
+ $headers = [];
+
+ foreach ($lines as $line) {
+ $parts = explode(':', $line, 2);
+ $headers[trim($parts[0])][] = isset($parts[1])
+ ? trim($parts[1])
+ : null;
+ }
+
+ return $headers;
+ }
+
+ /**
+ * Removes a header from a message using a case-insensitive comparison.
+ *
+ * @param array $message Message that contains 'headers'
+ * @param string $header Header to remove
+ *
+ * @return array
+ */
+ public static function removeHeader(array $message, $header)
+ {
+ if (isset($message['headers'])) {
+ foreach (array_keys($message['headers']) as $key) {
+ if (!strcasecmp($header, $key)) {
+ unset($message['headers'][$key]);
+ }
+ }
+ }
+
+ return $message;
+ }
+
+ /**
+ * Replaces any existing case insensitive headers with the given value.
+ *
+ * @param array $message Message that contains 'headers'
+ * @param string $header Header to set.
+ * @param array $value Value to set.
+ *
+ * @return array
+ */
+ public static function setHeader(array $message, $header, array $value)
+ {
+ $message = self::removeHeader($message, $header);
+ $message['headers'][$header] = $value;
+
+ return $message;
+ }
+
+ /**
+ * Creates a URL string from a request.
+ *
+ * If the "url" key is present on the request, it is returned, otherwise
+ * the url is built up based on the scheme, host, uri, and query_string
+ * request values.
+ *
+ * @param array $request Request to get the URL from
+ *
+ * @return string Returns the request URL as a string.
+ * @throws \InvalidArgumentException if no Host header is present.
+ */
+ public static function url(array $request)
+ {
+ if (isset($request['url'])) {
+ return $request['url'];
+ }
+
+ $uri = (isset($request['scheme'])
+ ? $request['scheme'] : 'http') . '://';
+
+ if ($host = self::header($request, 'host')) {
+ $uri .= $host;
+ } else {
+ throw new \InvalidArgumentException('No Host header was provided');
+ }
+
+ if (isset($request['uri'])) {
+ $uri .= $request['uri'];
+ }
+
+ if (isset($request['query_string'])) {
+ $uri .= '?' . $request['query_string'];
+ }
+
+ return $uri;
+ }
+
+ /**
+ * Reads the body of a message into a string.
+ *
+ * @param array|FutureArrayInterface $message Array containing a "body" key
+ *
+ * @return null|string Returns the body as a string or null if not set.
+ * @throws \InvalidArgumentException if a request body is invalid.
+ */
+ public static function body($message)
+ {
+ if (!isset($message['body'])) {
+ return null;
+ }
+
+ if ($message['body'] instanceof StreamInterface) {
+ return (string) $message['body'];
+ }
+
+ switch (gettype($message['body'])) {
+ case 'string':
+ return $message['body'];
+ case 'resource':
+ return stream_get_contents($message['body']);
+ case 'object':
+ if ($message['body'] instanceof \Iterator) {
+ return implode('', iterator_to_array($message['body']));
+ } elseif (method_exists($message['body'], '__toString')) {
+ return (string) $message['body'];
+ }
+ default:
+ throw new \InvalidArgumentException('Invalid request body: '
+ . self::describeType($message['body']));
+ }
+ }
+
+ /**
+ * Rewind the body of the provided message if possible.
+ *
+ * @param array $message Message that contains a 'body' field.
+ *
+ * @return bool Returns true on success, false on failure
+ */
+ public static function rewindBody($message)
+ {
+ if ($message['body'] instanceof StreamInterface) {
+ return $message['body']->seek(0);
+ }
+
+ if ($message['body'] instanceof \Generator) {
+ return false;
+ }
+
+ if ($message['body'] instanceof \Iterator) {
+ $message['body']->rewind();
+ return true;
+ }
+
+ if (is_resource($message['body'])) {
+ return rewind($message['body']);
+ }
+
+ return is_string($message['body'])
+ || (is_object($message['body'])
+ && method_exists($message['body'], '__toString'));
+ }
+
+ /**
+ * Debug function used to describe the provided value type and class.
+ *
+ * @param mixed $input
+ *
+ * @return string Returns a string containing the type of the variable and
+ * if a class is provided, the class name.
+ */
+ public static function describeType($input)
+ {
+ switch (gettype($input)) {
+ case 'object':
+ return 'object(' . get_class($input) . ')';
+ case 'array':
+ return 'array(' . count($input) . ')';
+ default:
+ ob_start();
+ var_dump($input);
+ // normalize float vs double
+ return str_replace('double(', 'float(', rtrim(ob_get_clean()));
+ }
+ }
+
+ /**
+ * Sleep for the specified amount of time specified in the request's
+ * ['client']['delay'] option if present.
+ *
+ * This function should only be used when a non-blocking sleep is not
+ * possible.
+ *
+ * @param array $request Request to sleep
+ */
+ public static function doSleep(array $request)
+ {
+ if (isset($request['client']['delay'])) {
+ usleep($request['client']['delay'] * 1000);
+ }
+ }
+
+ /**
+ * Returns a proxied future that modifies the dereferenced value of another
+ * future using a promise.
+ *
+ * @param FutureArrayInterface $future Future to wrap with a new future
+ * @param callable $onFulfilled Invoked when the future fulfilled
+ * @param callable $onRejected Invoked when the future rejected
+ * @param callable $onProgress Invoked when the future progresses
+ *
+ * @return FutureArray
+ */
+ public static function proxy(
+ FutureArrayInterface $future,
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return new FutureArray(
+ $future->then($onFulfilled, $onRejected, $onProgress),
+ [$future, 'wait'],
+ [$future, 'cancel']
+ );
+ }
+
+ /**
+ * Returns a debug stream based on the provided variable.
+ *
+ * @param mixed $value Optional value
+ *
+ * @return resource
+ */
+ public static function getDebugResource($value = null)
+ {
+ if (is_resource($value)) {
+ return $value;
+ } elseif (defined('STDOUT')) {
+ return STDOUT;
+ } else {
+ return fopen('php://output', 'w');
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php
new file mode 100644
index 0000000..95b353a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+/**
+ * Marker interface for cancelled exceptions.
+ */
+interface CancelledException {}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php
new file mode 100644
index 0000000..4a14574
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+class CancelledFutureAccessException extends RingException implements CancelledException {}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php
new file mode 100644
index 0000000..925cd13
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+/**
+ * Occurs when the connection failed.
+ */
+class ConnectException extends RingException {}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/RingException.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/RingException.php
new file mode 100644
index 0000000..eed0daf
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Exception/RingException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+class RingException extends \RuntimeException {};
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php
new file mode 100644
index 0000000..e6a7ca7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php
@@ -0,0 +1,125 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
+use GuzzleHttp\Ring\Exception\RingException;
+use React\Promise\PromiseInterface;
+
+/**
+ * Implements common future functionality built on top of promises.
+ */
+trait BaseFutureTrait
+{
+ /** @var callable */
+ private $waitfn;
+
+ /** @var callable */
+ private $cancelfn;
+
+ /** @var PromiseInterface */
+ private $wrappedPromise;
+
+ /** @var \Exception Error encountered. */
+ private $error;
+
+ /** @var mixed Result of the future */
+ private $result;
+
+ private $isRealized = false;
+
+ /**
+ * @param PromiseInterface $promise Promise to shadow with the future.
+ * @param callable $wait Function that blocks until the deferred
+ * computation has been resolved. This
+ * function MUST resolve the deferred value
+ * associated with the supplied promise.
+ * @param callable $cancel If possible and reasonable, provide a
+ * function that can be used to cancel the
+ * future from completing.
+ */
+ public function __construct(
+ PromiseInterface $promise,
+ callable $wait = null,
+ callable $cancel = null
+ ) {
+ $this->wrappedPromise = $promise;
+ $this->waitfn = $wait;
+ $this->cancelfn = $cancel;
+ }
+
+ public function wait()
+ {
+ if (!$this->isRealized) {
+ $this->addShadow();
+ if (!$this->isRealized && $this->waitfn) {
+ $this->invokeWait();
+ }
+ if (!$this->isRealized) {
+ $this->error = new RingException('Waiting did not resolve future');
+ }
+ }
+
+ if ($this->error) {
+ throw $this->error;
+ }
+
+ return $this->result;
+ }
+
+ public function promise()
+ {
+ return $this->wrappedPromise;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return $this->wrappedPromise->then($onFulfilled, $onRejected, $onProgress);
+ }
+
+ public function cancel()
+ {
+ if (!$this->isRealized) {
+ $cancelfn = $this->cancelfn;
+ $this->waitfn = $this->cancelfn = null;
+ $this->isRealized = true;
+ $this->error = new CancelledFutureAccessException();
+ if ($cancelfn) {
+ $cancelfn($this);
+ }
+ }
+ }
+
+ private function addShadow()
+ {
+ // Get the result and error when the promise is resolved. Note that
+ // calling this function might trigger the resolution immediately.
+ $this->wrappedPromise->then(
+ function ($value) {
+ $this->isRealized = true;
+ $this->result = $value;
+ $this->waitfn = $this->cancelfn = null;
+ },
+ function ($error) {
+ $this->isRealized = true;
+ $this->error = $error;
+ $this->waitfn = $this->cancelfn = null;
+ }
+ );
+ }
+
+ private function invokeWait()
+ {
+ try {
+ $wait = $this->waitfn;
+ $this->waitfn = null;
+ $wait();
+ } catch (\Exception $e) {
+ // Defer can throw to reject.
+ $this->error = $e;
+ $this->isRealized = true;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php
new file mode 100644
index 0000000..0a90c93
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php
@@ -0,0 +1,43 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Represents a future array that has been completed successfully.
+ */
+class CompletedFutureArray extends CompletedFutureValue implements FutureArrayInterface
+{
+ public function __construct(array $result)
+ {
+ parent::__construct($result);
+ }
+
+ public function offsetExists($offset)
+ {
+ return isset($this->result[$offset]);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->result[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->result[$offset] = $value;
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->result[$offset]);
+ }
+
+ public function count()
+ {
+ return count($this->result);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->result);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php
new file mode 100644
index 0000000..0d25af7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php
@@ -0,0 +1,57 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+use React\Promise\FulfilledPromise;
+use React\Promise\RejectedPromise;
+
+/**
+ * Represents a future value that has been resolved or rejected.
+ */
+class CompletedFutureValue implements FutureInterface
+{
+ protected $result;
+ protected $error;
+
+ private $cachedPromise;
+
+ /**
+ * @param mixed $result Resolved result
+ * @param \Exception $e Error. Pass a GuzzleHttp\Ring\Exception\CancelledFutureAccessException
+ * to mark the future as cancelled.
+ */
+ public function __construct($result, \Exception $e = null)
+ {
+ $this->result = $result;
+ $this->error = $e;
+ }
+
+ public function wait()
+ {
+ if ($this->error) {
+ throw $this->error;
+ }
+
+ return $this->result;
+ }
+
+ public function cancel() {}
+
+ public function promise()
+ {
+ if (!$this->cachedPromise) {
+ $this->cachedPromise = $this->error
+ ? new RejectedPromise($this->error)
+ : new FulfilledPromise($this->result);
+ }
+
+ return $this->cachedPromise;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php
new file mode 100644
index 0000000..3d64c96
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php
@@ -0,0 +1,40 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Represents a future array value that when dereferenced returns an array.
+ */
+class FutureArray implements FutureArrayInterface
+{
+ use MagicFutureTrait;
+
+ public function offsetExists($offset)
+ {
+ return isset($this->_value[$offset]);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->_value[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->_value[$offset] = $value;
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->_value[$offset]);
+ }
+
+ public function count()
+ {
+ return count($this->_value);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->_value);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php
new file mode 100644
index 0000000..58f5f73
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php
@@ -0,0 +1,11 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Future that provides array-like access.
+ */
+interface FutureArrayInterface extends
+ FutureInterface,
+ \ArrayAccess,
+ \Countable,
+ \IteratorAggregate {};
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php
new file mode 100644
index 0000000..43d1811
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php
@@ -0,0 +1,40 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+use React\Promise\PromiseInterface;
+use React\Promise\PromisorInterface;
+
+/**
+ * Represents the result of a computation that may not have completed yet.
+ *
+ * You can use the future in a blocking manner using the wait() function, or
+ * you can use a promise from the future to receive the result when the future
+ * has been resolved.
+ *
+ * When the future is dereferenced using wait(), the result of the computation
+ * is cached and returned for subsequent calls to wait(). If the result of the
+ * computation has not yet completed when wait() is called, the call to wait()
+ * will block until the future has completed.
+ */
+interface FutureInterface extends PromiseInterface, PromisorInterface
+{
+ /**
+ * Returns the result of the future either from cache or by blocking until
+ * it is complete.
+ *
+ * This method must block until the future has a result or is cancelled.
+ * Throwing an exception in the wait() method will mark the future as
+ * realized and will throw the exception each time wait() is called.
+ * Throwing an instance of GuzzleHttp\Ring\CancelledException will mark
+ * the future as realized, will not throw immediately, but will throw the
+ * exception if the future's wait() method is called again.
+ *
+ * @return mixed
+ */
+ public function wait();
+
+ /**
+ * Cancels the future, if possible.
+ */
+ public function cancel();
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php
new file mode 100644
index 0000000..4cac928
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php
@@ -0,0 +1,12 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Represents a future value that responds to wait() to retrieve the promised
+ * value, but can also return promises that are delivered the value when it is
+ * available.
+ */
+class FutureValue implements FutureInterface
+{
+ use BaseFutureTrait;
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php
new file mode 100644
index 0000000..58d779d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php
@@ -0,0 +1,32 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Implements common future functionality that is triggered when the result
+ * property is accessed via a magic __get method.
+ *
+ * @property mixed $_value Actual data used by the future. Accessing this
+ * property will cause the future to block if needed.
+ */
+trait MagicFutureTrait
+{
+ use BaseFutureTrait;
+
+ /**
+ * This function handles retrieving the dereferenced result when requested.
+ *
+ * @param string $name Should always be "data" or an exception is thrown.
+ *
+ * @return mixed Returns the dereferenced data.
+ * @throws \RuntimeException
+ * @throws \GuzzleHttp\Ring\Exception\CancelledException
+ */
+ public function __get($name)
+ {
+ if ($name !== '_value') {
+ throw new \RuntimeException("Class has no {$name} property");
+ }
+
+ return $this->_value = $this->wait();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php
new file mode 100644
index 0000000..ebde187
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php
@@ -0,0 +1,821 @@
+<?php
+// Override curl_setopt_array() to get the last set curl options
+namespace GuzzleHttp\Ring\Client {
+ function curl_setopt_array($handle, array $options) {
+ if (!empty($_SERVER['curl_test'])) {
+ $_SERVER['_curl'] = $options;
+ } else {
+ unset($_SERVER['_curl']);
+ }
+ \curl_setopt_array($handle, $options);
+ }
+}
+
+namespace GuzzleHttp\Tests\Ring\Client {
+
+use GuzzleHttp\Ring\Client\CurlFactory;
+use GuzzleHttp\Ring\Client\CurlMultiHandler;
+use GuzzleHttp\Ring\Client\MockHandler;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\NoSeekStream;
+use GuzzleHttp\Stream\Stream;
+
+class CurlFactoryTest extends \PHPUnit_Framework_TestCase
+{
+ public static function setUpBeforeClass()
+ {
+ $_SERVER['curl_test'] = true;
+ unset($_SERVER['_curl']);
+ }
+
+ public static function tearDownAfterClass()
+ {
+ unset($_SERVER['_curl'], $_SERVER['curl_test']);
+ }
+
+ public function testCreatesCurlHandle()
+ {
+ Server::flush();
+ Server::enqueue([[
+ 'status' => 200,
+ 'headers' => [
+ 'Foo' => ['Bar'],
+ 'Baz' => ['bam'],
+ 'Content-Length' => [2],
+ ],
+ 'body' => 'hi',
+ ]]);
+
+ $stream = Stream::factory();
+
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => [
+ 'host' => [Server::$url],
+ 'Hi' => [' 123'],
+ ],
+ 'body' => 'testing',
+ 'client' => ['save_to' => $stream],
+ ];
+
+ $f = new CurlFactory();
+ $result = $f($request);
+ $this->assertInternalType('array', $result);
+ $this->assertCount(3, $result);
+ $this->assertInternalType('resource', $result[0]);
+ $this->assertInternalType('array', $result[1]);
+ $this->assertSame($stream, $result[2]);
+ curl_close($result[0]);
+
+ $this->assertEquals('PUT', $_SERVER['_curl'][CURLOPT_CUSTOMREQUEST]);
+ $this->assertEquals(
+ 'http://http://127.0.0.1:8125/',
+ $_SERVER['_curl'][CURLOPT_URL]
+ );
+ // Sends via post fields when the request is small enough
+ $this->assertEquals('testing', $_SERVER['_curl'][CURLOPT_POSTFIELDS]);
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_RETURNTRANSFER]);
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_HEADER]);
+ $this->assertEquals(150, $_SERVER['_curl'][CURLOPT_CONNECTTIMEOUT]);
+ $this->assertInstanceOf('Closure', $_SERVER['_curl'][CURLOPT_HEADERFUNCTION]);
+
+ if (defined('CURLOPT_PROTOCOLS')) {
+ $this->assertEquals(
+ CURLPROTO_HTTP | CURLPROTO_HTTPS,
+ $_SERVER['_curl'][CURLOPT_PROTOCOLS]
+ );
+ }
+
+ $this->assertContains('Expect:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('Accept:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('Content-Type:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('Hi: 123', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('host: http://127.0.0.1:8125/', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ }
+
+ public function testSendsHeadRequests()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $response->wait();
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_NOBODY]);
+ $checks = [CURLOPT_WRITEFUNCTION, CURLOPT_READFUNCTION, CURLOPT_FILE, CURLOPT_INFILE];
+ foreach ($checks as $check) {
+ $this->assertArrayNotHasKey($check, $_SERVER['_curl']);
+ }
+ $this->assertEquals('HEAD', Server::received()[0]['http_method']);
+ }
+
+ public function testCanAddCustomCurlOptions()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]],
+ ]);
+ $this->assertEquals(10, $_SERVER['_curl'][CURLOPT_LOW_SPEED_LIMIT]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage SSL CA bundle not found: /does/not/exist
+ */
+ public function testValidatesVerify()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => '/does/not/exist'],
+ ]);
+ }
+
+ public function testCanSetVerifyToFile()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => __FILE__],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_CAINFO]);
+ $this->assertEquals(2, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
+ }
+
+ public function testAddsVerifyAsTrue()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => true],
+ ]);
+ $this->assertEquals(2, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
+ $this->assertArrayNotHasKey(CURLOPT_CAINFO, $_SERVER['_curl']);
+ }
+
+ public function testCanDisableVerify()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => false],
+ ]);
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
+ $this->assertEquals(false, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
+ }
+
+ public function testAddsProxy()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['proxy' => 'http://bar.com'],
+ ]);
+ $this->assertEquals('http://bar.com', $_SERVER['_curl'][CURLOPT_PROXY]);
+ }
+
+ public function testAddsViaScheme()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'scheme' => 'http',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => [
+ 'proxy' => ['http' => 'http://bar.com', 'https' => 'https://t'],
+ ],
+ ]);
+ $this->assertEquals('http://bar.com', $_SERVER['_curl'][CURLOPT_PROXY]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage SSL private key not found: /does/not/exist
+ */
+ public function testValidatesSslKey()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['ssl_key' => '/does/not/exist'],
+ ]);
+ }
+
+ public function testAddsSslKey()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['ssl_key' => __FILE__],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLKEY]);
+ }
+
+ public function testAddsSslKeyWithPassword()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['ssl_key' => [__FILE__, 'test']],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLKEY]);
+ $this->assertEquals('test', $_SERVER['_curl'][CURLOPT_SSLKEYPASSWD]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage SSL certificate not found: /does/not/exist
+ */
+ public function testValidatesCert()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['cert' => '/does/not/exist'],
+ ]);
+ }
+
+ public function testAddsCert()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['cert' => __FILE__],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLCERT]);
+ }
+
+ public function testAddsCertWithPassword()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['cert' => [__FILE__, 'test']],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLCERT]);
+ $this->assertEquals('test', $_SERVER['_curl'][CURLOPT_SSLCERTPASSWD]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage progress client option must be callable
+ */
+ public function testValidatesProgress()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['progress' => 'foo'],
+ ]);
+ }
+
+ public function testEmitsDebugInfoToStream()
+ {
+ $res = fopen('php://memory', 'r+');
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['debug' => $res],
+ ]);
+ $response->wait();
+ rewind($res);
+ $output = str_replace("\r", '', stream_get_contents($res));
+ $this->assertContains(
+ "> HEAD / HTTP/1.1\nhost: 127.0.0.1:8125\n\n",
+ $output
+ );
+ $this->assertContains("< HTTP/1.1 200", $output);
+ fclose($res);
+ }
+
+ public function testEmitsProgressToFunction()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $called = [];
+ $response = $a([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'progress' => function () use (&$called) {
+ $called[] = func_get_args();
+ },
+ ],
+ ]);
+ $response->wait();
+ $this->assertNotEmpty($called);
+ foreach ($called as $call) {
+ $this->assertCount(4, $call);
+ }
+ }
+
+ private function addDecodeResponse($withEncoding = true)
+ {
+ $content = gzencode('test');
+ $response = [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => ['Content-Length' => [strlen($content)]],
+ 'body' => $content,
+ ];
+
+ if ($withEncoding) {
+ $response['headers']['Content-Encoding'] = ['gzip'];
+ }
+
+ Server::flush();
+ Server::enqueue([$response]);
+
+ return $content;
+ }
+
+ public function testDecodesGzippedResponses()
+ {
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['decode_content' => true],
+ ]);
+ $response->wait();
+ $this->assertEquals('test', Core::body($response));
+ $this->assertEquals('', $_SERVER['_curl'][CURLOPT_ENCODING]);
+ $sent = Server::received()[0];
+ $this->assertNull(Core::header($sent, 'Accept-Encoding'));
+ }
+
+ public function testDecodesGzippedResponsesWithHeader()
+ {
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'Accept-Encoding' => ['gzip'],
+ ],
+ 'client' => ['decode_content' => true],
+ ]);
+ $response->wait();
+ $this->assertEquals('gzip', $_SERVER['_curl'][CURLOPT_ENCODING]);
+ $sent = Server::received()[0];
+ $this->assertEquals('gzip', Core::header($sent, 'Accept-Encoding'));
+ $this->assertEquals('test', Core::body($response));
+ }
+
+ public function testDoesNotForceDecode()
+ {
+ $content = $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['decode_content' => false],
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertNull(Core::header($sent, 'Accept-Encoding'));
+ $this->assertEquals($content, Core::body($response));
+ }
+
+ public function testProtocolVersion()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'version' => 1.0,
+ ]);
+ $this->assertEquals(CURL_HTTP_VERSION_1_0, $_SERVER['_curl'][CURLOPT_HTTP_VERSION]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesSaveTo()
+ {
+ $handler = new CurlMultiHandler();
+ $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['save_to' => true],
+ ]);
+ }
+
+ public function testSavesToStream()
+ {
+ $stream = fopen('php://memory', 'r+');
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'decode_content' => true,
+ 'save_to' => $stream,
+ ],
+ ]);
+ $response->wait();
+ rewind($stream);
+ $this->assertEquals('test', stream_get_contents($stream));
+ }
+
+ public function testSavesToGuzzleStream()
+ {
+ $stream = Stream::factory();
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'decode_content' => true,
+ 'save_to' => $stream,
+ ],
+ ]);
+ $response->wait();
+ $this->assertEquals('test', (string) $stream);
+ }
+
+ public function testSavesToFileOnDisk()
+ {
+ $tmpfile = tempnam(sys_get_temp_dir(), 'testfile');
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'decode_content' => true,
+ 'save_to' => $tmpfile,
+ ],
+ ]);
+ $response->wait();
+ $this->assertEquals('test', file_get_contents($tmpfile));
+ unlink($tmpfile);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesBody()
+ {
+ $handler = new CurlMultiHandler();
+ $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => false,
+ ]);
+ }
+
+ public function testAddsLargePayloadFromStreamWithNoSizeUsingChunked()
+ {
+ $stream = Stream::factory('foo');
+ $stream = FnStream::decorate($stream, [
+ 'getSize' => function () {
+ return null;
+ }
+ ]);
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => $stream,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals('chunked', Core::header($sent, 'Transfer-Encoding'));
+ $this->assertNull(Core::header($sent, 'Content-Length'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testAddsPayloadFromIterator()
+ {
+ $iter = new \ArrayIterator(['f', 'o', 'o']);
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => $iter,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals('chunked', Core::header($sent, 'Transfer-Encoding'));
+ $this->assertNull(Core::header($sent, 'Content-Length'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testAddsPayloadFromResource()
+ {
+ $res = fopen('php://memory', 'r+');
+ $data = str_repeat('.', 1000000);
+ fwrite($res, $data);
+ rewind($res);
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'content-length' => [1000000],
+ ],
+ 'body' => $res,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
+ $this->assertEquals(1000000, Core::header($sent, 'Content-Length'));
+ $this->assertEquals($data, $sent['body']);
+ }
+
+ public function testAddsContentLengthFromStream()
+ {
+ $stream = Stream::factory('foo');
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => $stream,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals(3, Core::header($sent, 'Content-Length'));
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testDoesNotAddMultipleContentLengthHeaders()
+ {
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'content-length' => [3],
+ ],
+ 'body' => 'foo',
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals(3, Core::header($sent, 'Content-Length'));
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testSendsPostWithNoBodyOrDefaultContentType()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'POST',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $response->wait();
+ $received = Server::received()[0];
+ $this->assertEquals('POST', $received['http_method']);
+ $this->assertNull(Core::header($received, 'content-type'));
+ $this->assertSame('0', Core::firstHeader($received, 'content-length'));
+ }
+
+ public function testParseProtocolVersion()
+ {
+ $res = CurlFactory::createResponse(
+ function () {},
+ [],
+ ['curl' => ['errno' => null]],
+ ['HTTP/1.1 200 Ok'],
+ null
+ );
+
+ $this->assertSame('1.1', $res['version']);
+ }
+
+ public function testFailsWhenNoResponseAndNoBody()
+ {
+ $res = CurlFactory::createResponse(function () {}, [], [], [], null);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\RingException', $res['error']);
+ $this->assertContains(
+ 'No response was received for a request with no body',
+ $res['error']->getMessage()
+ );
+ }
+
+ public function testFailsWhenCannotRewindRetry()
+ {
+ $res = CurlFactory::createResponse(function () {}, [
+ 'body' => new NoSeekStream(Stream::factory('foo'))
+ ], [], [], null);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\RingException', $res['error']);
+ $this->assertContains(
+ 'rewind the request body failed',
+ $res['error']->getMessage()
+ );
+ }
+
+ public function testRetriesWhenBodyCanBeRewound()
+ {
+ $callHandler = $called = false;
+ $res = CurlFactory::createResponse(function () use (&$callHandler) {
+ $callHandler = true;
+ return ['status' => 200];
+ }, [
+ 'body' => FnStream::decorate(Stream::factory('test'), [
+ 'seek' => function () use (&$called) {
+ $called = true;
+ return true;
+ }
+ ])
+ ], [], [], null);
+
+ $this->assertTrue($callHandler);
+ $this->assertTrue($called);
+ $this->assertEquals('200', $res['status']);
+ }
+
+ public function testFailsWhenRetryMoreThanThreeTimes()
+ {
+ $call = 0;
+ $mock = new MockHandler(function (array $request) use (&$mock, &$call) {
+ $call++;
+ return CurlFactory::createResponse($mock, $request, [], [], null);
+ });
+ $response = $mock([
+ 'http_method' => 'GET',
+ 'body' => 'test',
+ ]);
+ $this->assertEquals(3, $call);
+ $this->assertArrayHasKey('error', $response);
+ $this->assertContains(
+ 'The cURL request was retried 3 times',
+ $response['error']->getMessage()
+ );
+ }
+
+ public function testHandles100Continue()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => '200',
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Test' => ['Hello'],
+ 'Content-Length' => ['4'],
+ ],
+ 'body' => 'test',
+ ],
+ ]);
+
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => [
+ 'Host' => [Server::$host],
+ 'Expect' => ['100-Continue'],
+ ],
+ 'body' => 'test',
+ ];
+
+ $handler = new CurlMultiHandler();
+ $response = $handler($request)->wait();
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals(['Hello'], $response['headers']['Test']);
+ $this->assertEquals(['4'], $response['headers']['Content-Length']);
+ $this->assertEquals('test', Core::body($response));
+ }
+
+ public function testCreatesConnectException()
+ {
+ $m = new \ReflectionMethod('GuzzleHttp\Ring\Client\CurlFactory', 'createErrorResponse');
+ $m->setAccessible(true);
+ $response = $m->invoke(
+ null,
+ function () {},
+ [],
+ [
+ 'err_message' => 'foo',
+ 'curl' => [
+ 'errno' => CURLE_COULDNT_CONNECT,
+ ]
+ ]
+ );
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\ConnectException', $response['error']);
+ }
+
+ public function testParsesLastResponseOnly()
+ {
+ $response1 = [
+ 'status' => 301,
+ 'headers' => [
+ 'Content-Length' => ['0'],
+ 'Location' => ['/foo']
+ ]
+ ];
+
+ $response2 = [
+ 'status' => 200,
+ 'headers' => [
+ 'Content-Length' => ['0'],
+ 'Foo' => ['bar']
+ ]
+ ];
+
+ Server::flush();
+ Server::enqueue([$response1, $response2]);
+
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => [Server::$host]],
+ 'client' => [
+ 'curl' => [
+ CURLOPT_FOLLOWLOCATION => true
+ ]
+ ]
+ ])->wait();
+
+ $this->assertEquals(1, $response['transfer_stats']['redirect_count']);
+ $this->assertEquals('http://127.0.0.1:8125/foo', $response['effective_url']);
+ $this->assertEquals(['bar'], $response['headers']['Foo']);
+ $this->assertEquals(200, $response['status']);
+ $this->assertFalse(Core::hasHeader($response, 'Location'));
+ }
+
+ public function testMaintainsMultiHeaderOrder()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'headers' => [
+ 'Content-Length' => ['0'],
+ 'Foo' => ['a', 'b'],
+ 'foo' => ['c', 'd'],
+ ]
+ ]
+ ]);
+
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => [Server::$host]]
+ ])->wait();
+
+ $this->assertEquals(
+ ['a', 'b', 'c', 'd'],
+ Core::headerLines($response, 'Foo')
+ );
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Directory /path/to/does/not does not exist for save_to value of /path/to/does/not/exist.txt
+ */
+ public function testThrowsWhenDirNotFound()
+ {
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$url]],
+ 'client' => ['save_to' => '/path/to/does/not/exist.txt'],
+ ];
+
+ $f = new CurlFactory();
+ $f($request);
+ }
+}
+
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php
new file mode 100644
index 0000000..ba03b8c
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php
@@ -0,0 +1,96 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\CurlHandler;
+
+class CurlHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ protected function setUp()
+ {
+ if (!function_exists('curl_reset')) {
+ $this->markTestSkipped('curl_reset() is not available');
+ }
+ }
+
+ protected function getHandler($factory = null, $options = [])
+ {
+ return new CurlHandler($options);
+ }
+
+ public function testCanSetMaxHandles()
+ {
+ $a = new CurlHandler(['max_handles' => 10]);
+ $this->assertEquals(10, $this->readAttribute($a, 'maxHandles'));
+ }
+
+ public function testCreatesCurlErrors()
+ {
+ $handler = new CurlHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['localhost:123']],
+ 'client' => ['timeout' => 0.001, 'connect_timeout' => 0.001],
+ ]);
+ $this->assertNull($response['status']);
+ $this->assertNull($response['reason']);
+ $this->assertEquals([], $response['headers']);
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Ring\Exception\RingException',
+ $response['error']
+ );
+
+ $this->assertEquals(
+ 1,
+ preg_match('/^cURL error \d+: .*$/', $response['error']->getMessage())
+ );
+ }
+
+ public function testReleasesAdditionalEasyHandles()
+ {
+ Server::flush();
+ $response = [
+ 'status' => 200,
+ 'headers' => ['Content-Length' => [4]],
+ 'body' => 'test',
+ ];
+
+ Server::enqueue([$response, $response, $response, $response]);
+ $a = new CurlHandler(['max_handles' => 2]);
+
+ $fn = function () use (&$calls, $a, &$fn) {
+ if (++$calls < 4) {
+ $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['progress' => $fn],
+ ]);
+ }
+ };
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'progress' => $fn,
+ ],
+ ];
+
+ $a($request);
+ $this->assertCount(2, $this->readAttribute($a, 'handles'));
+ }
+
+ public function testReusesHandles()
+ {
+ Server::flush();
+ $response = ['status' => 200];
+ Server::enqueue([$response, $response]);
+ $a = new CurlHandler();
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ];
+ $a($request);
+ $a($request);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php
new file mode 100644
index 0000000..530b239
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php
@@ -0,0 +1,181 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+class CurlMultiHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSendsRequest()
+ {
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(200, $response['status']);
+ $this->assertArrayHasKey('transfer_stats', $response);
+ $realUrl = trim($response['transfer_stats']['url'], '/');
+ $this->assertEquals(trim(Server::$url, '/'), $realUrl);
+ $this->assertArrayHasKey('effective_url', $response);
+ $this->assertEquals(
+ trim(Server::$url, '/'),
+ trim($response['effective_url'], '/')
+ );
+ }
+
+ public function testCreatesErrorResponses()
+ {
+ $url = 'http://localhost:123/';
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['localhost:123']],
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertNull($response['status']);
+ $this->assertNull($response['reason']);
+ $this->assertEquals([], $response['headers']);
+ $this->assertArrayHasKey('error', $response);
+ $this->assertContains('cURL error ', $response['error']->getMessage());
+ $this->assertArrayHasKey('transfer_stats', $response);
+ $this->assertEquals(
+ trim($url, '/'),
+ trim($response['transfer_stats']['url'], '/')
+ );
+ $this->assertArrayHasKey('effective_url', $response);
+ $this->assertEquals(
+ trim($url, '/'),
+ trim($response['effective_url'], '/')
+ );
+ }
+
+ public function testSendsFuturesWhenDestructed()
+ {
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $a->__destruct();
+ $this->assertEquals(200, $response['status']);
+ }
+
+ public function testCanSetMaxHandles()
+ {
+ $a = new CurlMultiHandler(['max_handles' => 2]);
+ $this->assertEquals(2, $this->readAttribute($a, 'maxHandles'));
+ }
+
+ public function testCanSetSelectTimeout()
+ {
+ $a = new CurlMultiHandler(['select_timeout' => 2]);
+ $this->assertEquals(2, $this->readAttribute($a, 'selectTimeout'));
+ }
+
+ public function testSendsFuturesWhenMaxHandlesIsReached()
+ {
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => ['host' => [Server::$host]],
+ 'future' => 'lazy', // passing this to control the test
+ ];
+ $response = ['status' => 200];
+ Server::flush();
+ Server::enqueue([$response, $response, $response]);
+ $a = new CurlMultiHandler(['max_handles' => 3]);
+ for ($i = 0; $i < 5; $i++) {
+ $responses[] = $a($request);
+ }
+ $this->assertCount(3, Server::received());
+ $responses[3]->cancel();
+ $responses[4]->cancel();
+ }
+
+ public function testCanCancel()
+ {
+ Server::flush();
+ $response = ['status' => 200];
+ Server::enqueue(array_fill_keys(range(0, 10), $response));
+ $a = new CurlMultiHandler();
+ $responses = [];
+
+ for ($i = 0; $i < 10; $i++) {
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'future' => 'lazy',
+ ]);
+ $response->cancel();
+ $responses[] = $response;
+ }
+
+ $this->assertCount(0, Server::received());
+
+ foreach ($responses as $response) {
+ $this->assertTrue($this->readAttribute($response, 'isRealized'));
+ }
+ }
+
+ public function testCannotCancelFinished()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $response->wait();
+ $response->cancel();
+ }
+
+ public function testDelaysInParallel()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $expected = microtime(true) + (100 / 1000);
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['delay' => 100],
+ ]);
+ $response->wait();
+ $this->assertGreaterThanOrEqual($expected, microtime(true));
+ }
+
+ public function testSendsNonLazyFutures()
+ {
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'future' => true,
+ ];
+ Server::flush();
+ Server::enqueue([['status' => 202]]);
+ $a = new CurlMultiHandler();
+ $response = $a($request);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(202, $response['status']);
+ }
+
+ public function testExtractsErrors()
+ {
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['127.0.0.1:123']],
+ 'future' => true,
+ ];
+ Server::flush();
+ Server::enqueue([['status' => 202]]);
+ $a = new CurlMultiHandler();
+ $response = $a($request);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(CURLE_COULDNT_CONNECT, $response['curl']['errno']);
+ $this->assertNotEmpty($response['curl']['error']);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php
new file mode 100644
index 0000000..a47bb30
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php
@@ -0,0 +1,65 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\Middleware;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+
+class MiddlewareTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFutureCallsDefaultHandler()
+ {
+ $future = new CompletedFutureArray(['status' => 200]);
+ $calledA = false;
+ $a = function (array $req) use (&$calledA, $future) {
+ $calledA = true;
+ return $future;
+ };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
+ $s = Middleware::wrapFuture($a, $b);
+ $s([]);
+ $this->assertTrue($calledA);
+ $this->assertFalse($calledB);
+ }
+
+ public function testFutureCallsStreamingHandler()
+ {
+ $future = new CompletedFutureArray(['status' => 200]);
+ $calledA = false;
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB, $future) {
+ $calledB = true;
+ return $future;
+ };
+ $s = Middleware::wrapFuture($a, $b);
+ $result = $s(['client' => ['future' => true]]);
+ $this->assertFalse($calledA);
+ $this->assertTrue($calledB);
+ $this->assertSame($future, $result);
+ }
+
+ public function testStreamingCallsDefaultHandler()
+ {
+ $calledA = false;
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
+ $s = Middleware::wrapStreaming($a, $b);
+ $s([]);
+ $this->assertTrue($calledA);
+ $this->assertFalse($calledB);
+ }
+
+ public function testStreamingCallsStreamingHandler()
+ {
+ $calledA = false;
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
+ $s = Middleware::wrapStreaming($a, $b);
+ $s(['client' => ['stream' => true]]);
+ $this->assertFalse($calledA);
+ $this->assertTrue($calledB);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php
new file mode 100644
index 0000000..26bcd6c
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php
@@ -0,0 +1,86 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\MockHandler;
+use GuzzleHttp\Ring\Future\FutureArray;
+use React\Promise\Deferred;
+
+class MockHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsArray()
+ {
+ $mock = new MockHandler(['status' => 200]);
+ $response = $mock([]);
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals([], $response['headers']);
+ $this->assertNull($response['body']);
+ $this->assertNull($response['reason']);
+ $this->assertNull($response['effective_url']);
+ }
+
+ public function testReturnsFutures()
+ {
+ $deferred = new Deferred();
+ $future = new FutureArray(
+ $deferred->promise(),
+ function () use ($deferred) {
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+ $mock = new MockHandler($future);
+ $response = $mock([]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(200, $response['status']);
+ }
+
+ public function testReturnsFuturesWithThenCall()
+ {
+ $deferred = new Deferred();
+ $future = new FutureArray(
+ $deferred->promise(),
+ function () use ($deferred) {
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+ $mock = new MockHandler($future);
+ $response = $mock([]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(200, $response['status']);
+ $req = null;
+ $promise = $response->then(function ($value) use (&$req) {
+ $req = $value;
+ $this->assertEquals(200, $req['status']);
+ });
+ $this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
+ $this->assertEquals(200, $req['status']);
+ }
+
+ public function testReturnsFuturesAndProxiesCancel()
+ {
+ $c = null;
+ $deferred = new Deferred();
+ $future = new FutureArray(
+ $deferred->promise(),
+ function () {},
+ function () use (&$c) {
+ $c = true;
+ return true;
+ }
+ );
+ $mock = new MockHandler($future);
+ $response = $mock([]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $response->cancel();
+ $this->assertTrue($c);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Response must be an array or FutureArrayInterface. Found
+ */
+ public function testEnsuresMockIsValid()
+ {
+ $mock = new MockHandler('foo');
+ $mock([]);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/Server.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/Server.php
new file mode 100644
index 0000000..14665a5
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/Server.php
@@ -0,0 +1,183 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\StreamHandler;
+use GuzzleHttp\Ring\Core;
+
+/**
+ * Class uses to control the test webserver.
+ *
+ * Queued responses will be served to requests using a FIFO order. All requests
+ * received by the server are stored on the node.js server and can be retrieved
+ * by calling {@see Server::received()}.
+ *
+ * Mock responses that don't require data to be transmitted over HTTP a great
+ * for testing. Mock response, however, cannot test the actual sending of an
+ * HTTP request using cURL. This test server allows the simulation of any
+ * number of HTTP request response transactions to test the actual sending of
+ * requests over the wire without having to leave an internal network.
+ */
+class Server
+{
+ public static $started;
+ public static $url = 'http://127.0.0.1:8125/';
+ public static $host = '127.0.0.1:8125';
+ public static $port = 8125;
+
+ /**
+ * Flush the received requests from the server
+ * @throws \RuntimeException
+ */
+ public static function flush()
+ {
+ self::send('DELETE', '/guzzle-server/requests');
+ }
+
+ /**
+ * Queue an array of responses or a single response on the server.
+ *
+ * Any currently queued responses will be overwritten. Subsequent requests
+ * on the server will return queued responses in FIFO order.
+ *
+ * @param array $responses An array of responses. The shape of a response
+ * is the shape described in the RingPHP spec.
+ * @throws \Exception
+ */
+ public static function enqueue(array $responses)
+ {
+ $data = [];
+
+ foreach ($responses as $response) {
+ if (!is_array($response)) {
+ throw new \Exception('Each response must be an array');
+ }
+
+ if (isset($response['body'])) {
+ $response['body'] = base64_encode($response['body']);
+ }
+
+ $response += ['headers' => [], 'reason' => '', 'body' => ''];
+ $data[] = $response;
+ }
+
+ self::send('PUT', '/guzzle-server/responses', json_encode($data));
+ }
+
+ /**
+ * Get all of the received requests as a RingPHP request structure.
+ *
+ * @return array
+ * @throws \RuntimeException
+ */
+ public static function received()
+ {
+ if (!self::$started) {
+ return [];
+ }
+
+ $response = self::send('GET', '/guzzle-server/requests');
+ $body = Core::body($response);
+ $result = json_decode($body, true);
+ if ($result === false) {
+ throw new \RuntimeException('Error decoding response: '
+ . json_last_error());
+ }
+
+ foreach ($result as &$res) {
+ if (isset($res['uri'])) {
+ $res['resource'] = $res['uri'];
+ }
+ if (isset($res['query_string'])) {
+ $res['resource'] .= '?' . $res['query_string'];
+ }
+ if (!isset($res['resource'])) {
+ $res['resource'] = '';
+ }
+ // Ensure that headers are all arrays
+ if (isset($res['headers'])) {
+ foreach ($res['headers'] as &$h) {
+ $h = (array) $h;
+ }
+ unset($h);
+ }
+ }
+
+ unset($res);
+ return $result;
+ }
+
+ /**
+ * Stop running the node.js server
+ */
+ public static function stop()
+ {
+ if (self::$started) {
+ self::send('DELETE', '/guzzle-server');
+ }
+
+ self::$started = false;
+ }
+
+ public static function wait($maxTries = 20)
+ {
+ $tries = 0;
+ while (!self::isListening() && ++$tries < $maxTries) {
+ usleep(100000);
+ }
+
+ if (!self::isListening()) {
+ throw new \RuntimeException('Unable to contact node.js server');
+ }
+ }
+
+ public static function start()
+ {
+ if (self::$started) {
+ return;
+ }
+
+ try {
+ self::wait();
+ } catch (\Exception $e) {
+ exec('node ' . __DIR__ . \DIRECTORY_SEPARATOR . 'server.js '
+ . self::$port . ' >> /tmp/server.log 2>&1 &');
+ self::wait();
+ }
+
+ self::$started = true;
+ }
+
+ private static function isListening()
+ {
+ $response = self::send('GET', '/guzzle-server/perf', null, [
+ 'connect_timeout' => 1,
+ 'timeout' => 1
+ ]);
+
+ return !isset($response['error']);
+ }
+
+ private static function send(
+ $method,
+ $path,
+ $body = null,
+ array $client = []
+ ) {
+ $handler = new StreamHandler();
+
+ $request = [
+ 'http_method' => $method,
+ 'uri' => $path,
+ 'request_port' => 8125,
+ 'headers' => ['host' => ['127.0.0.1:8125']],
+ 'body' => $body,
+ 'client' => $client,
+ ];
+
+ if ($body) {
+ $request['headers']['content-length'] = [strlen($body)];
+ }
+
+ return $handler($request);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php
new file mode 100644
index 0000000..3cb9a8e
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php
@@ -0,0 +1,480 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\ClientUtils;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Client\StreamHandler;
+
+class StreamHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsResponseForSuccessfulRequest()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'Foo' => ['Bar'],
+ ],
+ ]);
+
+ $this->assertEquals('1.1', $response['version']);
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals(['Bar'], $response['headers']['Foo']);
+ $this->assertEquals(['8'], $response['headers']['Content-Length']);
+ $this->assertEquals('hi there', Core::body($response));
+
+ $sent = Server::received()[0];
+ $this->assertEquals('GET', $sent['http_method']);
+ $this->assertEquals('/', $sent['resource']);
+ $this->assertEquals(['127.0.0.1:8125'], $sent['headers']['host']);
+ $this->assertEquals('Bar', Core::header($sent, 'foo'));
+ }
+
+ public function testAddsErrorToResponse()
+ {
+ $handler = new StreamHandler();
+ $result = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['localhost:123']],
+ 'client' => ['timeout' => 0.01],
+ ]);
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Ring\Future\CompletedFutureArray',
+ $result
+ );
+ $this->assertNull($result['status']);
+ $this->assertNull($result['body']);
+ $this->assertEquals([], $result['headers']);
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Ring\Exception\RingException',
+ $result['error']
+ );
+ }
+
+ public function testEnsuresTheHttpProtocol()
+ {
+ $handler = new StreamHandler();
+ $result = $handler([
+ 'http_method' => 'GET',
+ 'url' => 'ftp://localhost:123',
+ ]);
+ $this->assertArrayHasKey('error', $result);
+ $this->assertContains(
+ 'URL is invalid: ftp://localhost:123',
+ $result['error']->getMessage()
+ );
+ }
+
+ public function testStreamAttributeKeepsStreamOpen()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'PUT',
+ 'uri' => '/foo',
+ 'query_string' => 'baz=bar',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'Foo' => ['Bar'],
+ ],
+ 'body' => 'test',
+ 'client' => ['stream' => true],
+ ]);
+
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals('8', Core::header($response, 'Content-Length'));
+ $body = $response['body'];
+ $this->assertTrue(is_resource($body));
+ $this->assertEquals('http', stream_get_meta_data($body)['wrapper_type']);
+ $this->assertEquals('hi there', stream_get_contents($body));
+ fclose($body);
+ $sent = Server::received()[0];
+ $this->assertEquals('PUT', $sent['http_method']);
+ $this->assertEquals('/foo', $sent['uri']);
+ $this->assertEquals('baz=bar', $sent['query_string']);
+ $this->assertEquals('/foo?baz=bar', $sent['resource']);
+ $this->assertEquals('127.0.0.1:8125', Core::header($sent, 'host'));
+ $this->assertEquals('Bar', Core::header($sent, 'foo'));
+ }
+
+ public function testDrainsResponseIntoTempStream()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $body = $response['body'];
+ $this->assertEquals('php://temp', stream_get_meta_data($body)['uri']);
+ $this->assertEquals('hi', fread($body, 2));
+ fclose($body);
+ }
+
+ public function testDrainsResponseIntoSaveToBody()
+ {
+ $r = fopen('php://temp', 'r+');
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['save_to' => $r],
+ ]);
+ $body = $response['body'];
+ $this->assertEquals('php://temp', stream_get_meta_data($body)['uri']);
+ $this->assertEquals('hi', fread($body, 2));
+ $this->assertEquals(' there', stream_get_contents($r));
+ fclose($r);
+ }
+
+ public function testDrainsResponseIntoSaveToBodyAtPath()
+ {
+ $tmpfname = tempnam('/tmp', 'save_to_path');
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['save_to' => $tmpfname],
+ ]);
+ $body = $response['body'];
+ $this->assertInstanceOf('GuzzleHttp\Stream\StreamInterface', $body);
+ $this->assertEquals($tmpfname, $body->getMetadata('uri'));
+ $this->assertEquals('hi', $body->read(2));
+ $body->close();
+ unlink($tmpfname);
+ }
+
+ public function testAutomaticallyDecompressGzip()
+ {
+ Server::flush();
+ $content = gzencode('test');
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Content-Encoding' => ['gzip'],
+ 'Content-Length' => [strlen($content)],
+ ],
+ 'body' => $content,
+ ],
+ ]);
+
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/',
+ 'client' => ['decode_content' => true],
+ ]);
+ $this->assertEquals('test', Core::body($response));
+ }
+
+ public function testDoesNotForceGzipDecode()
+ {
+ Server::flush();
+ $content = gzencode('test');
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Content-Encoding' => ['gzip'],
+ 'Content-Length' => [strlen($content)],
+ ],
+ 'body' => $content,
+ ],
+ ]);
+
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/',
+ 'client' => ['stream' => true, 'decode_content' => false],
+ ]);
+ $this->assertSame($content, Core::body($response));
+ }
+
+ public function testProtocolVersion()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'version' => 1.0,
+ ]);
+
+ $this->assertEquals(1.0, Server::received()[0]['version']);
+ }
+
+ protected function getSendResult(array $opts)
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $opts['stream'] = true;
+ return $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => $opts,
+ ]);
+ }
+
+ public function testAddsProxy()
+ {
+ $res = $this->getSendResult(['stream' => true, 'proxy' => '127.0.0.1:8125']);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals('127.0.0.1:8125', $opts['http']['proxy']);
+ }
+
+ public function testAddsTimeout()
+ {
+ $res = $this->getSendResult(['stream' => true, 'timeout' => 200]);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals(200, $opts['http']['timeout']);
+ }
+
+ public function testVerifiesVerifyIsValidIfPath()
+ {
+ $res = $this->getSendResult(['verify' => '/does/not/exist']);
+ $this->assertContains(
+ 'SSL CA bundle not found: /does/not/exist',
+ (string) $res['error']
+ );
+ }
+
+ public function testVerifyCanBeDisabled()
+ {
+ $res = $this->getSendResult(['verify' => false]);
+ $this->assertArrayNotHasKey('error', $res);
+ }
+
+ public function testVerifiesCertIfValidPath()
+ {
+ $res = $this->getSendResult(['cert' => '/does/not/exist']);
+ $this->assertContains(
+ 'SSL certificate not found: /does/not/exist',
+ (string) $res['error']
+ );
+ }
+
+ public function testVerifyCanBeSetToPath()
+ {
+ $path = $path = ClientUtils::getDefaultCaBundle();
+ $res = $this->getSendResult(['verify' => $path]);
+ $this->assertArrayNotHasKey('error', $res);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals(true, $opts['ssl']['verify_peer']);
+ $this->assertEquals($path, $opts['ssl']['cafile']);
+ $this->assertTrue(file_exists($opts['ssl']['cafile']));
+ }
+
+ public function testUsesSystemDefaultBundle()
+ {
+ $path = $path = ClientUtils::getDefaultCaBundle();
+ $res = $this->getSendResult(['verify' => true]);
+ $this->assertArrayNotHasKey('error', $res);
+ $opts = stream_context_get_options($res['body']);
+ if (PHP_VERSION_ID < 50600) {
+ $this->assertEquals($path, $opts['ssl']['cafile']);
+ }
+ }
+
+ public function testEnsuresVerifyOptionIsValid()
+ {
+ $res = $this->getSendResult(['verify' => 10]);
+ $this->assertContains(
+ 'Invalid verify request option',
+ (string) $res['error']
+ );
+ }
+
+ public function testCanSetPasswordWhenSettingCert()
+ {
+ $path = __FILE__;
+ $res = $this->getSendResult(['cert' => [$path, 'foo']]);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals($path, $opts['ssl']['local_cert']);
+ $this->assertEquals('foo', $opts['ssl']['passphrase']);
+ }
+
+ public function testDebugAttributeWritesToStream()
+ {
+ $this->queueRes();
+ $f = fopen('php://temp', 'w+');
+ $this->getSendResult(['debug' => $f]);
+ fseek($f, 0);
+ $contents = stream_get_contents($f);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [CONNECT]', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [FILE_SIZE_IS]', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [PROGRESS]', $contents);
+ }
+
+ public function testDebugAttributeWritesStreamInfoToBuffer()
+ {
+ $called = false;
+ $this->queueRes();
+ $buffer = fopen('php://temp', 'r+');
+ $this->getSendResult([
+ 'progress' => function () use (&$called) { $called = true; },
+ 'debug' => $buffer,
+ ]);
+ fseek($buffer, 0);
+ $contents = stream_get_contents($buffer);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [CONNECT]', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [FILE_SIZE_IS] message: "Content-Length: 8"', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [PROGRESS] bytes_max: "8"', $contents);
+ $this->assertTrue($called);
+ }
+
+ public function testEmitsProgressInformation()
+ {
+ $called = [];
+ $this->queueRes();
+ $this->getSendResult([
+ 'progress' => function () use (&$called) {
+ $called[] = func_get_args();
+ },
+ ]);
+ $this->assertNotEmpty($called);
+ $this->assertEquals(8, $called[0][0]);
+ $this->assertEquals(0, $called[0][1]);
+ }
+
+ public function testEmitsProgressInformationAndDebugInformation()
+ {
+ $called = [];
+ $this->queueRes();
+ $buffer = fopen('php://memory', 'w+');
+ $this->getSendResult([
+ 'debug' => $buffer,
+ 'progress' => function () use (&$called) {
+ $called[] = func_get_args();
+ },
+ ]);
+ $this->assertNotEmpty($called);
+ $this->assertEquals(8, $called[0][0]);
+ $this->assertEquals(0, $called[0][1]);
+ rewind($buffer);
+ $this->assertNotEmpty(stream_get_contents($buffer));
+ fclose($buffer);
+ }
+
+ public function testAddsProxyByProtocol()
+ {
+ $url = str_replace('http', 'tcp', Server::$url);
+ $res = $this->getSendResult(['proxy' => ['http' => $url]]);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals($url, $opts['http']['proxy']);
+ }
+
+ public function testPerformsShallowMergeOfCustomContextOptions()
+ {
+ $res = $this->getSendResult([
+ 'stream_context' => [
+ 'http' => [
+ 'request_fulluri' => true,
+ 'method' => 'HEAD',
+ ],
+ 'socket' => [
+ 'bindto' => '127.0.0.1:0',
+ ],
+ 'ssl' => [
+ 'verify_peer' => false,
+ ],
+ ],
+ ]);
+
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals('HEAD', $opts['http']['method']);
+ $this->assertTrue($opts['http']['request_fulluri']);
+ $this->assertFalse($opts['ssl']['verify_peer']);
+ $this->assertEquals('127.0.0.1:0', $opts['socket']['bindto']);
+ }
+
+ public function testEnsuresThatStreamContextIsAnArray()
+ {
+ $res = $this->getSendResult(['stream_context' => 'foo']);
+ $this->assertContains(
+ 'stream_context must be an array',
+ (string) $res['error']
+ );
+ }
+
+ public function testDoesNotAddContentTypeByDefault()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $handler([
+ 'http_method' => 'PUT',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host], 'content-length' => [3]],
+ 'body' => 'foo',
+ ]);
+ $req = Server::received()[0];
+ $this->assertEquals('', Core::header($req, 'Content-Type'));
+ $this->assertEquals(3, Core::header($req, 'Content-Length'));
+ }
+
+ private function queueRes()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Foo' => ['Bar'],
+ 'Content-Length' => [8],
+ ],
+ 'body' => 'hi there',
+ ],
+ ]);
+ }
+
+ public function testSupports100Continue()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => '200',
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Test' => ['Hello'],
+ 'Content-Length' => ['4'],
+ ],
+ 'body' => 'test',
+ ],
+ ]);
+
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => [
+ 'Host' => [Server::$host],
+ 'Expect' => ['100-Continue'],
+ ],
+ 'body' => 'test',
+ ];
+
+ $handler = new StreamHandler();
+ $response = $handler($request);
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals(['Hello'], $response['headers']['Test']);
+ $this->assertEquals(['4'], $response['headers']['Content-Length']);
+ $this->assertEquals('test', Core::body($response));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/server.js b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/server.js
new file mode 100644
index 0000000..6a03e33
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Client/server.js
@@ -0,0 +1,241 @@
+/**
+ * Guzzle node.js test server to return queued responses to HTTP requests and
+ * expose a RESTful API for enqueueing responses and retrieving the requests
+ * that have been received.
+ *
+ * - Delete all requests that have been received:
+ * > DELETE /guzzle-server/requests
+ * > Host: 127.0.0.1:8125
+ *
+ * - Enqueue responses
+ * > PUT /guzzle-server/responses
+ * > Host: 127.0.0.1:8125
+ * >
+ * > [{'status': 200, 'reason': 'OK', 'headers': {}, 'body': '' }]
+ *
+ * - Get the received requests
+ * > GET /guzzle-server/requests
+ * > Host: 127.0.0.1:8125
+ *
+ * < HTTP/1.1 200 OK
+ * <
+ * < [{'http_method': 'GET', 'uri': '/', 'headers': {}, 'body': 'string'}]
+ *
+ * - Attempt access to the secure area
+ * > GET /secure/by-digest/qop-auth/guzzle-server/requests
+ * > Host: 127.0.0.1:8125
+ *
+ * < HTTP/1.1 401 Unauthorized
+ * < WWW-Authenticate: Digest realm="Digest Test", qop="auth", nonce="0796e98e1aeef43141fab2a66bf4521a", algorithm="MD5", stale="false"
+ * <
+ * < 401 Unauthorized
+ *
+ * - Shutdown the server
+ * > DELETE /guzzle-server
+ * > Host: 127.0.0.1:8125
+ *
+ * @package Guzzle PHP <http://www.guzzlephp.org>
+ * @license See the LICENSE file that was distributed with this source code.
+ */
+
+var http = require('http');
+var url = require('url');
+
+/**
+ * Guzzle node.js server
+ * @class
+ */
+var GuzzleServer = function(port, log) {
+
+ this.port = port;
+ this.log = log;
+ this.responses = [];
+ this.requests = [];
+ var that = this;
+
+ var md5 = function(input) {
+ var crypto = require('crypto');
+ var hasher = crypto.createHash('md5');
+ hasher.update(input);
+ return hasher.digest('hex');
+ }
+
+ /**
+ * Node.js HTTP server authentication module.
+ *
+ * It is only initialized on demand (by loadAuthentifier). This avoids
+ * requiring the dependency to http-auth on standard operations, and the
+ * performance hit at startup.
+ */
+ var auth;
+
+ /**
+ * Provides authentication handlers (Basic, Digest).
+ */
+ var loadAuthentifier = function(type, options) {
+ var typeId = type;
+ if (type == 'digest') {
+ typeId += '.'+(options && options.qop ? options.qop : 'none');
+ }
+ if (!loadAuthentifier[typeId]) {
+ if (!auth) {
+ try {
+ auth = require('http-auth');
+ } catch (e) {
+ if (e.code == 'MODULE_NOT_FOUND') {
+ return;
+ }
+ }
+ }
+ switch (type) {
+ case 'digest':
+ var digestParams = {
+ realm: 'Digest Test',
+ login: 'me',
+ password: 'test'
+ };
+ if (options && options.qop) {
+ digestParams.qop = options.qop;
+ }
+ loadAuthentifier[typeId] = auth.digest(digestParams, function(username, callback) {
+ callback(md5(digestParams.login + ':' + digestParams.realm + ':' + digestParams.password));
+ });
+ break
+ }
+ }
+ return loadAuthentifier[typeId];
+ };
+
+ var firewallRequest = function(request, req, res, requestHandlerCallback) {
+ var securedAreaUriParts = request.uri.match(/^\/secure\/by-(digest)(\/qop-([^\/]*))?(\/.*)$/);
+ if (securedAreaUriParts) {
+ var authentifier = loadAuthentifier(securedAreaUriParts[1], { qop: securedAreaUriParts[2] });
+ if (!authentifier) {
+ res.writeHead(501, 'HTTP authentication not implemented', { 'Content-Length': 0 });
+ res.end();
+ return;
+ }
+ authentifier.check(req, res, function(req, res) {
+ req.url = securedAreaUriParts[4];
+ requestHandlerCallback(request, req, res);
+ });
+ } else {
+ requestHandlerCallback(request, req, res);
+ }
+ };
+
+ var controlRequest = function(request, req, res) {
+ if (req.url == '/guzzle-server/perf') {
+ res.writeHead(200, 'OK', {'Content-Length': 16});
+ res.end('Body of response');
+ } else if (req.method == 'DELETE') {
+ if (req.url == '/guzzle-server/requests') {
+ // Clear the received requests
+ that.requests = [];
+ res.writeHead(200, 'OK', { 'Content-Length': 0 });
+ res.end();
+ if (that.log) {
+ console.log('Flushing requests');
+ }
+ } else if (req.url == '/guzzle-server') {
+ // Shutdown the server
+ res.writeHead(200, 'OK', { 'Content-Length': 0, 'Connection': 'close' });
+ res.end();
+ if (that.log) {
+ console.log('Shutting down');
+ }
+ that.server.close();
+ }
+ } else if (req.method == 'GET') {
+ if (req.url === '/guzzle-server/requests') {
+ if (that.log) {
+ console.log('Sending received requests');
+ }
+ // Get received requests
+ var body = JSON.stringify(that.requests);
+ res.writeHead(200, 'OK', { 'Content-Length': body.length });
+ res.end(body);
+ }
+ } else if (req.method == 'PUT' && req.url == '/guzzle-server/responses') {
+ if (that.log) {
+ console.log('Adding responses...');
+ }
+ if (!request.body) {
+ if (that.log) {
+ console.log('No response data was provided');
+ }
+ res.writeHead(400, 'NO RESPONSES IN REQUEST', { 'Content-Length': 0 });
+ } else {
+ that.responses = eval('(' + request.body + ')');
+ for (var i = 0; i < that.responses.length; i++) {
+ if (that.responses[i].body) {
+ that.responses[i].body = new Buffer(that.responses[i].body, 'base64');
+ }
+ }
+ if (that.log) {
+ console.log(that.responses);
+ }
+ res.writeHead(200, 'OK', { 'Content-Length': 0 });
+ }
+ res.end();
+ }
+ };
+
+ var receivedRequest = function(request, req, res) {
+ if (req.url.indexOf('/guzzle-server') === 0) {
+ controlRequest(request, req, res);
+ } else if (req.url.indexOf('/guzzle-server') == -1 && !that.responses.length) {
+ res.writeHead(500);
+ res.end('No responses in queue');
+ } else {
+ if (that.log) {
+ console.log('Returning response from queue and adding request');
+ }
+ that.requests.push(request);
+ var response = that.responses.shift();
+ res.writeHead(response.status, response.reason, response.headers);
+ res.end(response.body);
+ }
+ };
+
+ this.start = function() {
+
+ that.server = http.createServer(function(req, res) {
+
+ var parts = url.parse(req.url, false);
+ var request = {
+ http_method: req.method,
+ scheme: parts.scheme,
+ uri: parts.pathname,
+ query_string: parts.query,
+ headers: req.headers,
+ version: req.httpVersion,
+ body: ''
+ };
+
+ // Receive each chunk of the request body
+ req.addListener('data', function(chunk) {
+ request.body += chunk;
+ });
+
+ // Called when the request completes
+ req.addListener('end', function() {
+ firewallRequest(request, req, res, receivedRequest);
+ });
+ });
+
+ that.server.listen(this.port, '127.0.0.1');
+
+ if (this.log) {
+ console.log('Server running at http://127.0.0.1:8125/');
+ }
+ };
+};
+
+// Get the port from the arguments
+port = process.argv.length >= 3 ? process.argv[2] : 8125;
+log = process.argv.length >= 4 ? process.argv[3] : false;
+
+// Start the server
+server = new GuzzleServer(port, log);
+server.start();
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/CoreTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/CoreTest.php
new file mode 100644
index 0000000..49522f2
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/CoreTest.php
@@ -0,0 +1,336 @@
+<?php
+namespace GuzzleHttp\Tests\Ring;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Ring\Future\FutureArray;
+use GuzzleHttp\Stream\Stream;
+use React\Promise\Deferred;
+
+class CoreTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsNullNoHeadersAreSet()
+ {
+ $this->assertNull(Core::header([], 'Foo'));
+ $this->assertNull(Core::firstHeader([], 'Foo'));
+ }
+
+ public function testChecksIfHasHeader()
+ {
+ $message = [
+ 'headers' => [
+ 'Foo' => ['Bar', 'Baz'],
+ 'foo' => ['hello'],
+ 'bar' => ['1']
+ ]
+ ];
+ $this->assertTrue(Core::hasHeader($message, 'Foo'));
+ $this->assertTrue(Core::hasHeader($message, 'foo'));
+ $this->assertTrue(Core::hasHeader($message, 'FoO'));
+ $this->assertTrue(Core::hasHeader($message, 'bar'));
+ $this->assertFalse(Core::hasHeader($message, 'barr'));
+ }
+
+ public function testReturnsFirstHeaderWhenSimple()
+ {
+ $this->assertEquals('Bar', Core::firstHeader([
+ 'headers' => ['Foo' => ['Bar', 'Baz']],
+ ], 'Foo'));
+ }
+
+ public function testReturnsFirstHeaderWhenMultiplePerLine()
+ {
+ $this->assertEquals('Bar', Core::firstHeader([
+ 'headers' => ['Foo' => ['Bar, Baz']],
+ ], 'Foo'));
+ }
+
+ public function testExtractsCaseInsensitiveHeader()
+ {
+ $this->assertEquals(
+ 'hello',
+ Core::header(['headers' => ['foo' => ['hello']]], 'FoO')
+ );
+ }
+
+ public function testExtractsCaseInsensitiveHeaderLines()
+ {
+ $this->assertEquals(
+ ['a', 'b', 'c', 'd'],
+ Core::headerLines([
+ 'headers' => [
+ 'foo' => ['a', 'b'],
+ 'Foo' => ['c', 'd']
+ ]
+ ], 'foo')
+ );
+ }
+
+ public function testExtractsHeaderLines()
+ {
+ $this->assertEquals(
+ ['bar', 'baz'],
+ Core::headerLines([
+ 'headers' => [
+ 'Foo' => ['bar', 'baz'],
+ ],
+ ], 'Foo')
+ );
+ }
+
+ public function testExtractsHeaderAsString()
+ {
+ $this->assertEquals(
+ 'bar, baz',
+ Core::header([
+ 'headers' => [
+ 'Foo' => ['bar', 'baz'],
+ ],
+ ], 'Foo', true)
+ );
+ }
+
+ public function testReturnsNullWhenHeaderNotFound()
+ {
+ $this->assertNull(Core::header(['headers' => []], 'Foo'));
+ }
+
+ public function testRemovesHeaders()
+ {
+ $message = [
+ 'headers' => [
+ 'foo' => ['bar'],
+ 'Foo' => ['bam'],
+ 'baz' => ['123'],
+ ],
+ ];
+
+ $this->assertSame($message, Core::removeHeader($message, 'bam'));
+ $this->assertEquals([
+ 'headers' => ['baz' => ['123']],
+ ], Core::removeHeader($message, 'foo'));
+ }
+
+ public function testCreatesUrl()
+ {
+ $req = [
+ 'scheme' => 'http',
+ 'headers' => ['host' => ['foo.com']],
+ 'uri' => '/',
+ ];
+
+ $this->assertEquals('http://foo.com/', Core::url($req));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage No Host header was provided
+ */
+ public function testEnsuresHostIsAvailableWhenCreatingUrls()
+ {
+ Core::url([]);
+ }
+
+ public function testCreatesUrlWithQueryString()
+ {
+ $req = [
+ 'scheme' => 'http',
+ 'headers' => ['host' => ['foo.com']],
+ 'uri' => '/',
+ 'query_string' => 'foo=baz',
+ ];
+
+ $this->assertEquals('http://foo.com/?foo=baz', Core::url($req));
+ }
+
+ public function testUsesUrlIfSet()
+ {
+ $req = ['url' => 'http://foo.com'];
+ $this->assertEquals('http://foo.com', Core::url($req));
+ }
+
+ public function testReturnsNullWhenNoBody()
+ {
+ $this->assertNull(Core::body([]));
+ }
+
+ public function testReturnsStreamAsString()
+ {
+ $this->assertEquals(
+ 'foo',
+ Core::body(['body' => Stream::factory('foo')])
+ );
+ }
+
+ public function testReturnsString()
+ {
+ $this->assertEquals('foo', Core::body(['body' => 'foo']));
+ }
+
+ public function testReturnsResourceContent()
+ {
+ $r = fopen('php://memory', 'w+');
+ fwrite($r, 'foo');
+ rewind($r);
+ $this->assertEquals('foo', Core::body(['body' => $r]));
+ fclose($r);
+ }
+
+ public function testReturnsIteratorContent()
+ {
+ $a = new \ArrayIterator(['a', 'b', 'cd', '']);
+ $this->assertEquals('abcd', Core::body(['body' => $a]));
+ }
+
+ public function testReturnsObjectToString()
+ {
+ $this->assertEquals('foo', Core::body(['body' => new StrClass]));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testEnsuresBodyIsValid()
+ {
+ Core::body(['body' => false]);
+ }
+
+ public function testParsesHeadersFromLines()
+ {
+ $lines = ['Foo: bar', 'Foo: baz', 'Abc: 123', 'Def: a, b'];
+ $this->assertEquals([
+ 'Foo' => ['bar', 'baz'],
+ 'Abc' => ['123'],
+ 'Def' => ['a, b'],
+ ], Core::headersFromLines($lines));
+ }
+
+ public function testParsesHeadersFromLinesWithMultipleLines()
+ {
+ $lines = ['Foo: bar', 'Foo: baz', 'Foo: 123'];
+ $this->assertEquals([
+ 'Foo' => ['bar', 'baz', '123'],
+ ], Core::headersFromLines($lines));
+ }
+
+ public function testCreatesArrayCallFunctions()
+ {
+ $called = [];
+ $a = function ($a, $b) use (&$called) {
+ $called['a'] = func_get_args();
+ };
+ $b = function ($a, $b) use (&$called) {
+ $called['b'] = func_get_args();
+ };
+ $c = Core::callArray([$a, $b]);
+ $c(1, 2);
+ $this->assertEquals([1, 2], $called['a']);
+ $this->assertEquals([1, 2], $called['b']);
+ }
+
+ public function testRewindsGuzzleStreams()
+ {
+ $str = Stream::factory('foo');
+ $this->assertTrue(Core::rewindBody(['body' => $str]));
+ }
+
+ public function testRewindsStreams()
+ {
+ $str = Stream::factory('foo')->detach();
+ $this->assertTrue(Core::rewindBody(['body' => $str]));
+ }
+
+ public function testRewindsIterators()
+ {
+ $iter = new \ArrayIterator(['foo']);
+ $this->assertTrue(Core::rewindBody(['body' => $iter]));
+ }
+
+ public function testRewindsStrings()
+ {
+ $this->assertTrue(Core::rewindBody(['body' => 'hi']));
+ }
+
+ public function testRewindsToStrings()
+ {
+ $this->assertTrue(Core::rewindBody(['body' => new StrClass()]));
+ }
+
+ public function typeProvider()
+ {
+ return [
+ ['foo', 'string(3) "foo"'],
+ [true, 'bool(true)'],
+ [false, 'bool(false)'],
+ [10, 'int(10)'],
+ [1.0, 'float(1)'],
+ [new StrClass(), 'object(GuzzleHttp\Tests\Ring\StrClass)'],
+ [['foo'], 'array(1)']
+ ];
+ }
+
+ /**
+ * @dataProvider typeProvider
+ */
+ public function testDescribesType($input, $output)
+ {
+ $this->assertEquals($output, Core::describeType($input));
+ }
+
+ public function testDoesSleep()
+ {
+ $t = microtime(true);
+ $expected = $t + (100 / 1000);
+ Core::doSleep(['client' => ['delay' => 100]]);
+ $this->assertGreaterThanOrEqual($expected, microtime(true));
+ }
+
+ public function testProxiesFuture()
+ {
+ $f = new CompletedFutureArray(['status' => 200]);
+ $res = null;
+ $proxied = Core::proxy($f, function ($value) use (&$res) {
+ $value['foo'] = 'bar';
+ $res = $value;
+ return $value;
+ });
+ $this->assertNotSame($f, $proxied);
+ $this->assertEquals(200, $f->wait()['status']);
+ $this->assertArrayNotHasKey('foo', $f->wait());
+ $this->assertEquals('bar', $proxied->wait()['foo']);
+ $this->assertEquals(200, $proxied->wait()['status']);
+ }
+
+ public function testProxiesDeferredFuture()
+ {
+ $d = new Deferred();
+ $f = new FutureArray($d->promise());
+ $f2 = Core::proxy($f);
+ $d->resolve(['foo' => 'bar']);
+ $this->assertEquals('bar', $f['foo']);
+ $this->assertEquals('bar', $f2['foo']);
+ }
+
+ public function testProxiesDeferredFutureFailure()
+ {
+ $d = new Deferred();
+ $f = new FutureArray($d->promise());
+ $f2 = Core::proxy($f);
+ $d->reject(new \Exception('foo'));
+ try {
+ $f2['hello?'];
+ $this->fail('did not throw');
+ } catch (\Exception $e) {
+ $this->assertEquals('foo', $e->getMessage());
+ }
+
+ }
+}
+
+final class StrClass
+{
+ public function __toString()
+ {
+ return 'foo';
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php
new file mode 100644
index 0000000..82d7efb
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php
@@ -0,0 +1,21 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+
+class CompletedFutureArrayTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsAsArray()
+ {
+ $f = new CompletedFutureArray(['foo' => 'bar']);
+ $this->assertEquals('bar', $f['foo']);
+ $this->assertFalse(isset($f['baz']));
+ $f['abc'] = '123';
+ $this->assertTrue(isset($f['abc']));
+ $this->assertEquals(['foo' => 'bar', 'abc' => '123'], iterator_to_array($f));
+ $this->assertEquals(2, count($f));
+ unset($f['abc']);
+ $this->assertEquals(1, count($f));
+ $this->assertEquals(['foo' => 'bar'], iterator_to_array($f));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php
new file mode 100644
index 0000000..6ded40d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php
@@ -0,0 +1,46 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
+use GuzzleHttp\Ring\Future\CompletedFutureValue;
+
+class CompletedFutureValueTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsValue()
+ {
+ $f = new CompletedFutureValue('hi');
+ $this->assertEquals('hi', $f->wait());
+ $f->cancel();
+
+ $a = null;
+ $f->then(function ($v) use (&$a) {
+ $a = $v;
+ });
+ $this->assertSame('hi', $a);
+ }
+
+ public function testThrows()
+ {
+ $ex = new \Exception('foo');
+ $f = new CompletedFutureValue(null, $ex);
+ $f->cancel();
+ try {
+ $f->wait();
+ $this->fail('did not throw');
+ } catch (\Exception $e) {
+ $this->assertSame($e, $ex);
+ }
+ }
+
+ public function testMarksAsCancelled()
+ {
+ $ex = new CancelledFutureAccessException();
+ $f = new CompletedFutureValue(null, $ex);
+ try {
+ $f->wait();
+ $this->fail('did not throw');
+ } catch (\Exception $e) {
+ $this->assertSame($e, $ex);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php
new file mode 100644
index 0000000..0e09f5a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php
@@ -0,0 +1,56 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Future\FutureArray;
+use React\Promise\Deferred;
+
+class FutureArrayTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLazilyCallsDeref()
+ {
+ $c = false;
+ $deferred = new Deferred();
+ $f = new FutureArray(
+ $deferred->promise(),
+ function () use (&$c, $deferred) {
+ $c = true;
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+ $this->assertFalse($c);
+ $this->assertFalse($this->readAttribute($f, 'isRealized'));
+ $this->assertEquals(200, $f['status']);
+ $this->assertTrue($c);
+ }
+
+ public function testActsLikeArray()
+ {
+ $deferred = new Deferred();
+ $f = new FutureArray(
+ $deferred->promise(),
+ function () use (&$c, $deferred) {
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+
+ $this->assertTrue(isset($f['status']));
+ $this->assertEquals(200, $f['status']);
+ $this->assertEquals(['status' => 200], $f->wait());
+ $this->assertEquals(1, count($f));
+ $f['baz'] = 10;
+ $this->assertEquals(10, $f['baz']);
+ unset($f['baz']);
+ $this->assertFalse(isset($f['baz']));
+ $this->assertEquals(['status' => 200], iterator_to_array($f));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testThrowsWhenAccessingInvalidProperty()
+ {
+ $deferred = new Deferred();
+ $f = new FutureArray($deferred->promise(), function () {});
+ $f->foo;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php
new file mode 100644
index 0000000..d59c543
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php
@@ -0,0 +1,109 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
+use GuzzleHttp\Ring\Future\FutureValue;
+use React\Promise\Deferred;
+
+class FutureValueTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDerefReturnsValue()
+ {
+ $called = 0;
+ $deferred = new Deferred();
+
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use ($deferred, &$called) {
+ $called++;
+ $deferred->resolve('foo');
+ }
+ );
+
+ $this->assertEquals('foo', $f->wait());
+ $this->assertEquals(1, $called);
+ $this->assertEquals('foo', $f->wait());
+ $this->assertEquals(1, $called);
+ $f->cancel();
+ $this->assertTrue($this->readAttribute($f, 'isRealized'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Ring\Exception\CancelledFutureAccessException
+ */
+ public function testThrowsWhenAccessingCancelled()
+ {
+ $f = new FutureValue(
+ (new Deferred())->promise(),
+ function () {},
+ function () { return true; }
+ );
+ $f->cancel();
+ $f->wait();
+ }
+
+ /**
+ * @expectedException \OutOfBoundsException
+ */
+ public function testThrowsWhenDerefFailure()
+ {
+ $called = false;
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use(&$called) {
+ $called = true;
+ }
+ );
+ $deferred->reject(new \OutOfBoundsException());
+ $f->wait();
+ $this->assertFalse($called);
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Ring\Exception\RingException
+ * @expectedExceptionMessage Waiting did not resolve future
+ */
+ public function testThrowsWhenDerefDoesNotResolve()
+ {
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use(&$called) {
+ $called = true;
+ }
+ );
+ $f->wait();
+ }
+
+ public function testThrowingCancelledFutureAccessExceptionCancels()
+ {
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use ($deferred) {
+ throw new CancelledFutureAccessException();
+ }
+ );
+ try {
+ $f->wait();
+ $this->fail('did not throw');
+ } catch (CancelledFutureAccessException $e) {}
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage foo
+ */
+ public function testThrowingExceptionInDerefMarksAsFailed()
+ {
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () {
+ throw new \Exception('foo');
+ }
+ );
+ $f->wait();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/ringphp/tests/bootstrap.php b/public/system/storage/vendor/guzzlehttp/ringphp/tests/bootstrap.php
new file mode 100644
index 0000000..017610f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/ringphp/tests/bootstrap.php
@@ -0,0 +1,11 @@
+<?php
+require __DIR__ . '/../vendor/autoload.php';
+require __DIR__ . '/Client/Server.php';
+
+use GuzzleHttp\Tests\Ring\Client\Server;
+
+Server::start();
+
+register_shutdown_function(function () {
+ Server::stop();
+});
diff --git a/public/system/storage/vendor/guzzlehttp/streams/.gitignore b/public/system/storage/vendor/guzzlehttp/streams/.gitignore
new file mode 100644
index 0000000..c33d396
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/.gitignore
@@ -0,0 +1,6 @@
+.idea
+.DS_STORE
+coverage
+phpunit.xml
+composer.lock
+vendor/
diff --git a/public/system/storage/vendor/guzzlehttp/streams/.travis.yml b/public/system/storage/vendor/guzzlehttp/streams/.travis.yml
new file mode 100644
index 0000000..a6f8a87
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/.travis.yml
@@ -0,0 +1,17 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+before_script:
+ - composer self-update
+ - composer install --no-interaction --prefer-source --dev
+
+script: vendor/bin/phpunit
+
+matrix:
+ allow_failures:
+ - php: hhvm
diff --git a/public/system/storage/vendor/guzzlehttp/streams/CHANGELOG.rst b/public/system/storage/vendor/guzzlehttp/streams/CHANGELOG.rst
new file mode 100644
index 0000000..0018ffe
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/CHANGELOG.rst
@@ -0,0 +1,94 @@
+=========
+Changelog
+=========
+
+3.0.0 (2014-10-12)
+------------------
+
+* Now supports creating streams from functions and iterators.
+* Supports creating buffered streams and asynchronous streams.
+* Removed ``functions.php``. Use the corresponding functions provided by
+ ``GuzzleHttp\Streams\Utils`` instead.
+* Moved ``GuzzleHttp\Stream\MetadataStreamInterface::getMetadata`` to
+ ``GuzzleHttp\Stream\StreamInterface``. MetadataStreamInterface is no longer
+ used and is marked as deprecated.
+* Added ``attach()`` to ``GuzzleHttp\Stream\StreamInterface`` for PSR-7
+ compatibility.
+* Removed ``flush()`` from StreamInterface.
+* Removed the ``$maxLength`` parameter from
+ ``GuzzleHttp\Stream\StreamInterface::getContents()``. This function now
+ returns the entire remainder of the stream. If you want to limit the maximum
+ amount of data read from the stream, use the
+ ``GuzzleHttp\Stream\Utils::copyToString()`` function.
+* Streams that return an empty string, ``''``, are no longer considered a
+ failure. You MUST return ``false`` to mark the read as a failure, and ensure
+ that any decorators you create properly return ``true`` in response to the
+ ``eof()`` method when the stream is consumed.
+* ``GuzzleHttp\Stream\Stream::__construct``,
+ ``GuzzleHttp\Stream\Stream::factory``, and
+ ``GuzzleHttp\Stream\Utils::create`` no longer accept a size in the second
+ argument. They now accept an associative array of options, including the
+ "size" key and "metadata" key which can be used to provide custom metadata.
+* Added ``GuzzleHttp\Stream\BufferStream`` to add support for buffering data,
+ and when read, shifting data off of the buffer.
+* Added ``GuzzleHttp\Stream\NullBuffer`` which can be used as a buffer that
+ does not actually store any data.
+* Added ``GuzzleHttp\Stream\AsyncStream`` to provide support for non-blocking
+ streams that can be filled by a remote source (e.g., an event-loop). If a
+ ``drain`` option is provided, the stream can also act as if it is a blocking
+ stream.
+
+2.1.0 (2014-08-17)
+------------------
+
+* Added an InflateStream to inflate gzipped or deflated content.
+* Added ``flush`` to stream wrapper.
+* Added the ability to easily register the GuzzleStreamWrapper if needed.
+
+2.0.0 (2014-08-16)
+------------------
+
+* Deprecated functions.php and moved all of those methods to
+ ``GuzzleHttp\Streams\Utils``. Use ``GuzzleHttp\Stream\Stream::factory()``
+ instead of ``GuzzleHttp\Stream\create()`` to create new streams.
+* Added ``flush()`` to ``StreamInterface``. This method is used to flush any
+ underlying stream write buffers.
+* Added ``FnStream`` to easily decorate stream behavior with callables.
+* ``Utils::hash`` now throws an exception when the stream cannot seek to 0.
+
+1.5.1 (2014-09-10)
+------------------
+
+* Stream metadata is grabbed from the underlying stream each time
+ ``getMetadata`` is called rather than returning a value from a cache.
+* Properly closing all underlying streams when AppendStream is closed.
+* Seek functions no longer throw exceptions.
+* LazyOpenStream now correctly returns the underlying stream resource when
+ detached.
+
+1.5.0 (2014-08-07)
+------------------
+
+* Added ``Stream\safe_open`` to open stream resources and throw exceptions
+ instead of raising errors.
+
+1.4.0 (2014-07-19)
+------------------
+
+* Added a LazyOpenStream
+
+1.3.0 (2014-07-15)
+------------------
+
+* Added an AppendStream to stream over multiple stream one after the other.
+
+1.2.0 (2014-07-15)
+------------------
+
+* Updated the ``detach()`` method to return the underlying stream resource or
+ ``null`` if it does not wrap a resource.
+* Multiple fixes for how streams behave when the underlying resource is
+ detached
+* Do not clear statcache when a stream does not have a 'uri'
+* Added a fix to LimitStream
+* Added a condition to ensure that functions.php can be required multiple times
diff --git a/public/system/storage/vendor/guzzlehttp/streams/LICENSE b/public/system/storage/vendor/guzzlehttp/streams/LICENSE
new file mode 100644
index 0000000..71d3b78
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/guzzlehttp/streams/Makefile b/public/system/storage/vendor/guzzlehttp/streams/Makefile
new file mode 100644
index 0000000..f4d4284
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/Makefile
@@ -0,0 +1,19 @@
+all: clean coverage
+
+release: tag
+ git push origin --tags
+
+tag:
+ chag tag --sign --debug CHANGELOG.rst
+
+test:
+ vendor/bin/phpunit
+
+coverage:
+ vendor/bin/phpunit --coverage-html=artifacts/coverage
+
+view-coverage:
+ open artifacts/coverage/index.html
+
+clean:
+ rm -rf artifacts/*
diff --git a/public/system/storage/vendor/guzzlehttp/streams/README.rst b/public/system/storage/vendor/guzzlehttp/streams/README.rst
new file mode 100644
index 0000000..baff63b
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/README.rst
@@ -0,0 +1,36 @@
+==============
+Guzzle Streams
+==============
+
+Provides a simple abstraction over streams of data.
+
+This library is used in `Guzzle 5 <https://github.com/guzzle/guzzle>`_, and is
+(currently) compatible with the WIP PSR-7.
+
+Installation
+============
+
+This package can be installed easily using `Composer <http://getcomposer.org>`_.
+Simply add the following to the composer.json file at the root of your project:
+
+.. code-block:: javascript
+
+ {
+ "require": {
+ "guzzlehttp/streams": "~3.0"
+ }
+ }
+
+Then install your dependencies using ``composer.phar install``.
+
+Documentation
+=============
+
+The documentation for this package can be found on the main Guzzle website at
+http://docs.guzzlephp.org/en/guzzle4/streams.html.
+
+Testing
+=======
+
+This library is tested using PHPUnit. You'll need to install the dependencies
+using `Composer <http://getcomposer.org>`_ then run ``make test``.
diff --git a/public/system/storage/vendor/guzzlehttp/streams/composer.json b/public/system/storage/vendor/guzzlehttp/streams/composer.json
new file mode 100644
index 0000000..6d70343
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "guzzlehttp/streams",
+ "description": "Provides a simple abstraction over streams of data",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": ["stream", "guzzle"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "autoload": {
+ "psr-4": { "GuzzleHttp\\Stream\\": "src/" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/phpunit.xml.dist b/public/system/storage/vendor/guzzlehttp/streams/phpunit.xml.dist
new file mode 100644
index 0000000..6e758c1
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/phpunit.xml.dist
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./vendor/autoload.php"
+ colors="true">
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ <exclude>
+ <file>src/functions.php</file>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/AppendStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/AppendStream.php
new file mode 100644
index 0000000..94bda71
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/AppendStream.php
@@ -0,0 +1,220 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Reads from multiple streams, one after the other.
+ *
+ * This is a read-only stream decorator.
+ */
+class AppendStream implements StreamInterface
+{
+ /** @var StreamInterface[] Streams being decorated */
+ private $streams = [];
+
+ private $seekable = true;
+ private $current = 0;
+ private $pos = 0;
+ private $detached = false;
+
+ /**
+ * @param StreamInterface[] $streams Streams to decorate. Each stream must
+ * be readable.
+ */
+ public function __construct(array $streams = [])
+ {
+ foreach ($streams as $stream) {
+ $this->addStream($stream);
+ }
+ }
+
+ public function __toString()
+ {
+ try {
+ $this->seek(0);
+ return $this->getContents();
+ } catch (\Exception $e) {
+ return '';
+ }
+ }
+
+ /**
+ * Add a stream to the AppendStream
+ *
+ * @param StreamInterface $stream Stream to append. Must be readable.
+ *
+ * @throws \InvalidArgumentException if the stream is not readable
+ */
+ public function addStream(StreamInterface $stream)
+ {
+ if (!$stream->isReadable()) {
+ throw new \InvalidArgumentException('Each stream must be readable');
+ }
+
+ // The stream is only seekable if all streams are seekable
+ if (!$stream->isSeekable()) {
+ $this->seekable = false;
+ }
+
+ $this->streams[] = $stream;
+ }
+
+ public function getContents()
+ {
+ return Utils::copyToString($this);
+ }
+
+ /**
+ * Closes each attached stream.
+ *
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ $this->pos = $this->current = 0;
+
+ foreach ($this->streams as $stream) {
+ $stream->close();
+ }
+
+ $this->streams = [];
+ }
+
+ /**
+ * Detaches each attached stream
+ *
+ * {@inheritdoc}
+ */
+ public function detach()
+ {
+ $this->close();
+ $this->detached = true;
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function tell()
+ {
+ return $this->pos;
+ }
+
+ /**
+ * Tries to calculate the size by adding the size of each stream.
+ *
+ * If any of the streams do not return a valid number, then the size of the
+ * append stream cannot be determined and null is returned.
+ *
+ * {@inheritdoc}
+ */
+ public function getSize()
+ {
+ $size = 0;
+
+ foreach ($this->streams as $stream) {
+ $s = $stream->getSize();
+ if ($s === null) {
+ return null;
+ }
+ $size += $s;
+ }
+
+ return $size;
+ }
+
+ public function eof()
+ {
+ return !$this->streams ||
+ ($this->current >= count($this->streams) - 1 &&
+ $this->streams[$this->current]->eof());
+ }
+
+ /**
+ * Attempts to seek to the given position. Only supports SEEK_SET.
+ *
+ * {@inheritdoc}
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if (!$this->seekable || $whence !== SEEK_SET) {
+ return false;
+ }
+
+ $success = true;
+ $this->pos = $this->current = 0;
+
+ // Rewind each stream
+ foreach ($this->streams as $stream) {
+ if (!$stream->seek(0)) {
+ $success = false;
+ }
+ }
+
+ if (!$success) {
+ return false;
+ }
+
+ // Seek to the actual position by reading from each stream
+ while ($this->pos < $offset && !$this->eof()) {
+ $this->read(min(8096, $offset - $this->pos));
+ }
+
+ return $this->pos == $offset;
+ }
+
+ /**
+ * Reads from all of the appended streams until the length is met or EOF.
+ *
+ * {@inheritdoc}
+ */
+ public function read($length)
+ {
+ $buffer = '';
+ $total = count($this->streams) - 1;
+ $remaining = $length;
+
+ while ($remaining > 0) {
+ // Progress to the next stream if needed.
+ if ($this->streams[$this->current]->eof()) {
+ if ($this->current == $total) {
+ break;
+ }
+ $this->current++;
+ }
+ $buffer .= $this->streams[$this->current]->read($remaining);
+ $remaining = $length - strlen($buffer);
+ }
+
+ $this->pos += strlen($buffer);
+
+ return $buffer;
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function isSeekable()
+ {
+ return $this->seekable;
+ }
+
+ public function write($string)
+ {
+ return false;
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $key ? null : [];
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/AsyncReadStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/AsyncReadStream.php
new file mode 100644
index 0000000..25ad960
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/AsyncReadStream.php
@@ -0,0 +1,207 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Represents an asynchronous read-only stream that supports a drain event and
+ * pumping data from a source stream.
+ *
+ * The AsyncReadStream can be used as a completely asynchronous stream, meaning
+ * the data you can read from the stream will immediately return only
+ * the data that is currently buffered.
+ *
+ * AsyncReadStream can also be used in a "blocking" manner if a "pump" function
+ * is provided. When a caller requests more bytes than are available in the
+ * buffer, then the pump function is used to block until the requested number
+ * of bytes are available or the remote source stream has errored, closed, or
+ * timed-out. This behavior isn't strictly "blocking" because the pump function
+ * can send other transfers while waiting on the desired buffer size to be
+ * ready for reading (e.g., continue to tick an event loop).
+ *
+ * @unstable This class is subject to change.
+ */
+class AsyncReadStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var callable|null Fn used to notify writers the buffer has drained */
+ private $drain;
+
+ /** @var callable|null Fn used to block for more data */
+ private $pump;
+
+ /** @var int|null Highwater mark of the underlying buffer */
+ private $hwm;
+
+ /** @var bool Whether or not drain needs to be called at some point */
+ private $needsDrain;
+
+ /** @var int The expected size of the remote source */
+ private $size;
+
+ /**
+ * In order to utilize high water marks to tell writers to slow down, the
+ * provided stream must answer to the "hwm" stream metadata variable,
+ * providing the high water mark. If no "hwm" metadata value is available,
+ * then the "drain" functionality is not utilized.
+ *
+ * This class accepts an associative array of configuration options.
+ *
+ * - drain: (callable) Function to invoke when the stream has drained,
+ * meaning the buffer is now writable again because the size of the
+ * buffer is at an acceptable level (e.g., below the high water mark).
+ * The function accepts a single argument, the buffer stream object that
+ * has drained.
+ * - pump: (callable) A function that accepts the number of bytes to read
+ * from the source stream. This function will block until all of the data
+ * that was requested has been read, EOF of the source stream, or the
+ * source stream is closed.
+ * - size: (int) The expected size in bytes of the data that will be read
+ * (if known up-front).
+ *
+ * @param StreamInterface $buffer Buffer that contains the data that has
+ * been read by the event loop.
+ * @param array $config Associative array of options.
+ *
+ * @throws \InvalidArgumentException if the buffer is not readable and
+ * writable.
+ */
+ public function __construct(
+ StreamInterface $buffer,
+ array $config = []
+ ) {
+ if (!$buffer->isReadable() || !$buffer->isWritable()) {
+ throw new \InvalidArgumentException(
+ 'Buffer must be readable and writable'
+ );
+ }
+
+ if (isset($config['size'])) {
+ $this->size = $config['size'];
+ }
+
+ static $callables = ['pump', 'drain'];
+ foreach ($callables as $check) {
+ if (isset($config[$check])) {
+ if (!is_callable($config[$check])) {
+ throw new \InvalidArgumentException(
+ $check . ' must be callable'
+ );
+ }
+ $this->{$check} = $config[$check];
+ }
+ }
+
+ $this->hwm = $buffer->getMetadata('hwm');
+
+ // Cannot drain when there's no high water mark.
+ if ($this->hwm === null) {
+ $this->drain = null;
+ }
+
+ $this->stream = $buffer;
+ }
+
+ /**
+ * Factory method used to create new async stream and an underlying buffer
+ * if no buffer is provided.
+ *
+ * This function accepts the same options as AsyncReadStream::__construct,
+ * but added the following key value pairs:
+ *
+ * - buffer: (StreamInterface) Buffer used to buffer data. If none is
+ * provided, a default buffer is created.
+ * - hwm: (int) High water mark to use if a buffer is created on your
+ * behalf.
+ * - max_buffer: (int) If provided, wraps the utilized buffer in a
+ * DroppingStream decorator to ensure that buffer does not exceed a given
+ * length. When exceeded, the stream will begin dropping data. Set the
+ * max_buffer to 0, to use a NullStream which does not store data.
+ * - write: (callable) A function that is invoked when data is written
+ * to the underlying buffer. The function accepts the buffer as the first
+ * argument, and the data being written as the second. The function MUST
+ * return the number of bytes that were written or false to let writers
+ * know to slow down.
+ * - drain: (callable) See constructor documentation.
+ * - pump: (callable) See constructor documentation.
+ *
+ * @param array $options Associative array of options.
+ *
+ * @return array Returns an array containing the buffer used to buffer
+ * data, followed by the ready to use AsyncReadStream object.
+ */
+ public static function create(array $options = [])
+ {
+ $maxBuffer = isset($options['max_buffer'])
+ ? $options['max_buffer']
+ : null;
+
+ if ($maxBuffer === 0) {
+ $buffer = new NullStream();
+ } elseif (isset($options['buffer'])) {
+ $buffer = $options['buffer'];
+ } else {
+ $hwm = isset($options['hwm']) ? $options['hwm'] : 16384;
+ $buffer = new BufferStream($hwm);
+ }
+
+ if ($maxBuffer > 0) {
+ $buffer = new DroppingStream($buffer, $options['max_buffer']);
+ }
+
+ // Call the on_write callback if an on_write function was provided.
+ if (isset($options['write'])) {
+ $onWrite = $options['write'];
+ $buffer = FnStream::decorate($buffer, [
+ 'write' => function ($string) use ($buffer, $onWrite) {
+ $result = $buffer->write($string);
+ $onWrite($buffer, $string);
+ return $result;
+ }
+ ]);
+ }
+
+ return [$buffer, new self($buffer, $options)];
+ }
+
+ public function getSize()
+ {
+ return $this->size;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ return false;
+ }
+
+ public function read($length)
+ {
+ if (!$this->needsDrain && $this->drain) {
+ $this->needsDrain = $this->stream->getSize() >= $this->hwm;
+ }
+
+ $result = $this->stream->read($length);
+
+ // If we need to drain, then drain when the buffer is empty.
+ if ($this->needsDrain && $this->stream->getSize() === 0) {
+ $this->needsDrain = false;
+ $drainFn = $this->drain;
+ $drainFn($this->stream);
+ }
+
+ $resultLen = strlen($result);
+
+ // If a pump was provided, the buffer is still open, and not enough
+ // data was given, then block until the data is provided.
+ if ($this->pump && $resultLen < $length) {
+ $pumpFn = $this->pump;
+ $result .= $pumpFn($length - $resultLen);
+ }
+
+ return $result;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/BufferStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/BufferStream.php
new file mode 100644
index 0000000..0fffbd6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/BufferStream.php
@@ -0,0 +1,138 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Provides a buffer stream that can be written to to fill a buffer, and read
+ * from to remove bytes from the buffer.
+ *
+ * This stream returns a "hwm" metadata value that tells upstream consumers
+ * what the configured high water mark of the stream is, or the maximum
+ * preferred size of the buffer.
+ *
+ * @package GuzzleHttp\Stream
+ */
+class BufferStream implements StreamInterface
+{
+ private $hwm;
+ private $buffer = '';
+
+ /**
+ * @param int $hwm High water mark, representing the preferred maximum
+ * buffer size. If the size of the buffer exceeds the high
+ * water mark, then calls to write will continue to succeed
+ * but will return false to inform writers to slow down
+ * until the buffer has been drained by reading from it.
+ */
+ public function __construct($hwm = 16384)
+ {
+ $this->hwm = $hwm;
+ }
+
+ public function __toString()
+ {
+ return $this->getContents();
+ }
+
+ public function getContents()
+ {
+ $buffer = $this->buffer;
+ $this->buffer = '';
+
+ return $buffer;
+ }
+
+ public function close()
+ {
+ $this->buffer = '';
+ }
+
+ public function detach()
+ {
+ $this->close();
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function getSize()
+ {
+ return strlen($this->buffer);
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return true;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function eof()
+ {
+ return strlen($this->buffer) === 0;
+ }
+
+ public function tell()
+ {
+ return false;
+ }
+
+ /**
+ * Reads data from the buffer.
+ */
+ public function read($length)
+ {
+ $currentLength = strlen($this->buffer);
+
+ if ($length >= $currentLength) {
+ // No need to slice the buffer because we don't have enough data.
+ $result = $this->buffer;
+ $this->buffer = '';
+ } else {
+ // Slice up the result to provide a subset of the buffer.
+ $result = substr($this->buffer, 0, $length);
+ $this->buffer = substr($this->buffer, $length);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Writes data to the buffer.
+ */
+ public function write($string)
+ {
+ $this->buffer .= $string;
+
+ if (strlen($this->buffer) >= $this->hwm) {
+ return false;
+ }
+
+ return strlen($string);
+ }
+
+ public function getMetadata($key = null)
+ {
+ if ($key == 'hwm') {
+ return $this->hwm;
+ }
+
+ return $key ? null : [];
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/CachingStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/CachingStream.php
new file mode 100644
index 0000000..60bb905
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/CachingStream.php
@@ -0,0 +1,122 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+
+/**
+ * Stream decorator that can cache previously read bytes from a sequentially
+ * read stream.
+ */
+class CachingStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var StreamInterface Stream being wrapped */
+ private $remoteStream;
+
+ /** @var int Number of bytes to skip reading due to a write on the buffer */
+ private $skipReadBytes = 0;
+
+ /**
+ * We will treat the buffer object as the body of the stream
+ *
+ * @param StreamInterface $stream Stream to cache
+ * @param StreamInterface $target Optionally specify where data is cached
+ */
+ public function __construct(
+ StreamInterface $stream,
+ StreamInterface $target = null
+ ) {
+ $this->remoteStream = $stream;
+ $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
+ }
+
+ public function getSize()
+ {
+ return max($this->stream->getSize(), $this->remoteStream->getSize());
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws SeekException When seeking with SEEK_END or when seeking
+ * past the total size of the buffer stream
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($whence == SEEK_SET) {
+ $byte = $offset;
+ } elseif ($whence == SEEK_CUR) {
+ $byte = $offset + $this->tell();
+ } else {
+ return false;
+ }
+
+ // You cannot skip ahead past where you've read from the remote stream
+ if ($byte > $this->stream->getSize()) {
+ throw new SeekException(
+ $this,
+ $byte,
+ sprintf('Cannot seek to byte %d when the buffered stream only'
+ . ' contains %d bytes', $byte, $this->stream->getSize())
+ );
+ }
+
+ return $this->stream->seek($byte);
+ }
+
+ public function read($length)
+ {
+ // Perform a regular read on any previously read data from the buffer
+ $data = $this->stream->read($length);
+ $remaining = $length - strlen($data);
+
+ // More data was requested so read from the remote stream
+ if ($remaining) {
+ // If data was written to the buffer in a position that would have
+ // been filled from the remote stream, then we must skip bytes on
+ // the remote stream to emulate overwriting bytes from that
+ // position. This mimics the behavior of other PHP stream wrappers.
+ $remoteData = $this->remoteStream->read(
+ $remaining + $this->skipReadBytes
+ );
+
+ if ($this->skipReadBytes) {
+ $len = strlen($remoteData);
+ $remoteData = substr($remoteData, $this->skipReadBytes);
+ $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
+ }
+
+ $data .= $remoteData;
+ $this->stream->write($remoteData);
+ }
+
+ return $data;
+ }
+
+ public function write($string)
+ {
+ // When appending to the end of the currently read stream, you'll want
+ // to skip bytes from being read from the remote stream to emulate
+ // other stream wrappers. Basically replacing bytes of data of a fixed
+ // length.
+ $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
+ if ($overflow > 0) {
+ $this->skipReadBytes += $overflow;
+ }
+
+ return $this->stream->write($string);
+ }
+
+ public function eof()
+ {
+ return $this->stream->eof() && $this->remoteStream->eof();
+ }
+
+ /**
+ * Close both the remote stream and buffer stream
+ */
+ public function close()
+ {
+ $this->remoteStream->close() && $this->stream->close();
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/DroppingStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/DroppingStream.php
new file mode 100644
index 0000000..56ee80c
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/DroppingStream.php
@@ -0,0 +1,42 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Stream decorator that begins dropping data once the size of the underlying
+ * stream becomes too full.
+ */
+class DroppingStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ private $maxLength;
+
+ /**
+ * @param StreamInterface $stream Underlying stream to decorate.
+ * @param int $maxLength Maximum size before dropping data.
+ */
+ public function __construct(StreamInterface $stream, $maxLength)
+ {
+ $this->stream = $stream;
+ $this->maxLength = $maxLength;
+ }
+
+ public function write($string)
+ {
+ $diff = $this->maxLength - $this->stream->getSize();
+
+ // Begin returning false when the underlying stream is too large.
+ if ($diff <= 0) {
+ return false;
+ }
+
+ // Write the stream or a subset of the stream if needed.
+ if (strlen($string) < $diff) {
+ return $this->stream->write($string);
+ }
+
+ $this->stream->write(substr($string, 0, $diff));
+
+ return false;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php b/public/system/storage/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php
new file mode 100644
index 0000000..e631b9f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Stream\Exception;
+
+class CannotAttachException extends \RuntimeException {}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/Exception/SeekException.php b/public/system/storage/vendor/guzzlehttp/streams/src/Exception/SeekException.php
new file mode 100644
index 0000000..3f6d5eb
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/Exception/SeekException.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Stream\Exception;
+
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Exception thrown when a seek fails on a stream.
+ */
+class SeekException extends \RuntimeException
+{
+ private $stream;
+
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
+ {
+ $this->stream = $stream;
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
+ parent::__construct($msg);
+ }
+
+ /**
+ * @return StreamInterface
+ */
+ public function getStream()
+ {
+ return $this->stream;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/FnStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/FnStream.php
new file mode 100644
index 0000000..6b5872d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/FnStream.php
@@ -0,0 +1,147 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Compose stream implementations based on a hash of functions.
+ *
+ * Allows for easy testing and extension of a provided stream without needing
+ * to create a concrete class for a simple extension point.
+ */
+class FnStream implements StreamInterface
+{
+ /** @var array */
+ private $methods;
+
+ /** @var array Methods that must be implemented in the given array */
+ private static $slots = ['__toString', 'close', 'detach', 'attach',
+ 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
+ 'isReadable', 'read', 'getContents', 'getMetadata'];
+
+ /**
+ * @param array $methods Hash of method name to a callable.
+ */
+ public function __construct(array $methods)
+ {
+ $this->methods = $methods;
+
+ // Create the functions on the class
+ foreach ($methods as $name => $fn) {
+ $this->{'_fn_' . $name} = $fn;
+ }
+ }
+
+ /**
+ * Lazily determine which methods are not implemented.
+ * @throws \BadMethodCallException
+ */
+ public function __get($name)
+ {
+ throw new \BadMethodCallException(str_replace('_fn_', '', $name)
+ . '() is not implemented in the FnStream');
+ }
+
+ /**
+ * The close method is called on the underlying stream only if possible.
+ */
+ public function __destruct()
+ {
+ if (isset($this->_fn_close)) {
+ call_user_func($this->_fn_close);
+ }
+ }
+
+ /**
+ * Adds custom functionality to an underlying stream by intercepting
+ * specific method calls.
+ *
+ * @param StreamInterface $stream Stream to decorate
+ * @param array $methods Hash of method name to a closure
+ *
+ * @return FnStream
+ */
+ public static function decorate(StreamInterface $stream, array $methods)
+ {
+ // If any of the required methods were not provided, then simply
+ // proxy to the decorated stream.
+ foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
+ $methods[$diff] = [$stream, $diff];
+ }
+
+ return new self($methods);
+ }
+
+ public function __toString()
+ {
+ return call_user_func($this->_fn___toString);
+ }
+
+ public function close()
+ {
+ return call_user_func($this->_fn_close);
+ }
+
+ public function detach()
+ {
+ return call_user_func($this->_fn_detach);
+ }
+
+ public function attach($stream)
+ {
+ return call_user_func($this->_fn_attach, $stream);
+ }
+
+ public function getSize()
+ {
+ return call_user_func($this->_fn_getSize);
+ }
+
+ public function tell()
+ {
+ return call_user_func($this->_fn_tell);
+ }
+
+ public function eof()
+ {
+ return call_user_func($this->_fn_eof);
+ }
+
+ public function isSeekable()
+ {
+ return call_user_func($this->_fn_isSeekable);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return call_user_func($this->_fn_seek, $offset, $whence);
+ }
+
+ public function isWritable()
+ {
+ return call_user_func($this->_fn_isWritable);
+ }
+
+ public function write($string)
+ {
+ return call_user_func($this->_fn_write, $string);
+ }
+
+ public function isReadable()
+ {
+ return call_user_func($this->_fn_isReadable);
+ }
+
+ public function read($length)
+ {
+ return call_user_func($this->_fn_read, $length);
+ }
+
+ public function getContents()
+ {
+ return call_user_func($this->_fn_getContents);
+ }
+
+ public function getMetadata($key = null)
+ {
+ return call_user_func($this->_fn_getMetadata, $key);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php b/public/system/storage/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php
new file mode 100644
index 0000000..4d049a6
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php
@@ -0,0 +1,117 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Converts Guzzle streams into PHP stream resources.
+ */
+class GuzzleStreamWrapper
+{
+ /** @var resource */
+ public $context;
+
+ /** @var StreamInterface */
+ private $stream;
+
+ /** @var string r, r+, or w */
+ private $mode;
+
+ /**
+ * Returns a resource representing the stream.
+ *
+ * @param StreamInterface $stream The stream to get a resource for
+ *
+ * @return resource
+ * @throws \InvalidArgumentException if stream is not readable or writable
+ */
+ public static function getResource(StreamInterface $stream)
+ {
+ self::register();
+
+ if ($stream->isReadable()) {
+ $mode = $stream->isWritable() ? 'r+' : 'r';
+ } elseif ($stream->isWritable()) {
+ $mode = 'w';
+ } else {
+ throw new \InvalidArgumentException('The stream must be readable, '
+ . 'writable, or both.');
+ }
+
+ return fopen('guzzle://stream', $mode, null, stream_context_create([
+ 'guzzle' => ['stream' => $stream]
+ ]));
+ }
+
+ /**
+ * Registers the stream wrapper if needed
+ */
+ public static function register()
+ {
+ if (!in_array('guzzle', stream_get_wrappers())) {
+ stream_wrapper_register('guzzle', __CLASS__);
+ }
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path)
+ {
+ $options = stream_context_get_options($this->context);
+
+ if (!isset($options['guzzle']['stream'])) {
+ return false;
+ }
+
+ $this->mode = $mode;
+ $this->stream = $options['guzzle']['stream'];
+
+ return true;
+ }
+
+ public function stream_read($count)
+ {
+ return $this->stream->read($count);
+ }
+
+ public function stream_write($data)
+ {
+ return (int) $this->stream->write($data);
+ }
+
+ public function stream_tell()
+ {
+ return $this->stream->tell();
+ }
+
+ public function stream_eof()
+ {
+ return $this->stream->eof();
+ }
+
+ public function stream_seek($offset, $whence)
+ {
+ return $this->stream->seek($offset, $whence);
+ }
+
+ public function stream_stat()
+ {
+ static $modeMap = [
+ 'r' => 33060,
+ 'r+' => 33206,
+ 'w' => 33188
+ ];
+
+ return [
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => $modeMap[$this->mode],
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => $this->stream->getSize() ?: 0,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0
+ ];
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/InflateStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/InflateStream.php
new file mode 100644
index 0000000..978af21
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/InflateStream.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
+ *
+ * This stream decorator skips the first 10 bytes of the given stream to remove
+ * the gzip header, converts the provided stream to a PHP stream resource,
+ * then appends the zlib.inflate filter. The stream is then converted back
+ * to a Guzzle stream resource to be used as a Guzzle stream.
+ *
+ * @link http://tools.ietf.org/html/rfc1952
+ * @link http://php.net/manual/en/filters.compression.php
+ */
+class InflateStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ public function __construct(StreamInterface $stream)
+ {
+ // Skip the first 10 bytes
+ $stream = new LimitStream($stream, -1, 10);
+ $resource = GuzzleStreamWrapper::getResource($stream);
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
+ $this->stream = new Stream($resource);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/LazyOpenStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/LazyOpenStream.php
new file mode 100644
index 0000000..6242ee7
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/LazyOpenStream.php
@@ -0,0 +1,37 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Lazily reads or writes to a file that is opened only after an IO operation
+ * take place on the stream.
+ */
+class LazyOpenStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var string File to open */
+ private $filename;
+
+ /** @var string $mode */
+ private $mode;
+
+ /**
+ * @param string $filename File to lazily open
+ * @param string $mode fopen mode to use when opening the stream
+ */
+ public function __construct($filename, $mode)
+ {
+ $this->filename = $filename;
+ $this->mode = $mode;
+ }
+
+ /**
+ * Creates the underlying stream lazily when required.
+ *
+ * @return StreamInterface
+ */
+ protected function createStream()
+ {
+ return Stream::factory(Utils::open($this->filename, $this->mode));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/LimitStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/LimitStream.php
new file mode 100644
index 0000000..e9fad98
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/LimitStream.php
@@ -0,0 +1,161 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+
+/**
+ * Decorator used to return only a subset of a stream
+ */
+class LimitStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var int Offset to start reading from */
+ private $offset;
+
+ /** @var int Limit the number of bytes that can be read */
+ private $limit;
+
+ /**
+ * @param StreamInterface $stream Stream to wrap
+ * @param int $limit Total number of bytes to allow to be read
+ * from the stream. Pass -1 for no limit.
+ * @param int|null $offset Position to seek to before reading (only
+ * works on seekable streams).
+ */
+ public function __construct(
+ StreamInterface $stream,
+ $limit = -1,
+ $offset = 0
+ ) {
+ $this->stream = $stream;
+ $this->setLimit($limit);
+ $this->setOffset($offset);
+ }
+
+ public function eof()
+ {
+ // Always return true if the underlying stream is EOF
+ if ($this->stream->eof()) {
+ return true;
+ }
+
+ // No limit and the underlying stream is not at EOF
+ if ($this->limit == -1) {
+ return false;
+ }
+
+ $tell = $this->stream->tell();
+ if ($tell === false) {
+ return false;
+ }
+
+ return $tell >= $this->offset + $this->limit;
+ }
+
+ /**
+ * Returns the size of the limited subset of data
+ * {@inheritdoc}
+ */
+ public function getSize()
+ {
+ if (null === ($length = $this->stream->getSize())) {
+ return null;
+ } elseif ($this->limit == -1) {
+ return $length - $this->offset;
+ } else {
+ return min($this->limit, $length - $this->offset);
+ }
+ }
+
+ /**
+ * Allow for a bounded seek on the read limited stream
+ * {@inheritdoc}
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($whence !== SEEK_SET || $offset < 0) {
+ return false;
+ }
+
+ $offset += $this->offset;
+
+ if ($this->limit !== -1) {
+ if ($offset > $this->offset + $this->limit) {
+ $offset = $this->offset + $this->limit;
+ }
+ }
+
+ return $this->stream->seek($offset);
+ }
+
+ /**
+ * Give a relative tell()
+ * {@inheritdoc}
+ */
+ public function tell()
+ {
+ return $this->stream->tell() - $this->offset;
+ }
+
+ /**
+ * Set the offset to start limiting from
+ *
+ * @param int $offset Offset to seek to and begin byte limiting from
+ *
+ * @return self
+ * @throws SeekException
+ */
+ public function setOffset($offset)
+ {
+ $current = $this->stream->tell();
+
+ if ($current !== $offset) {
+ // If the stream cannot seek to the offset position, then read to it
+ if (!$this->stream->seek($offset)) {
+ if ($current > $offset) {
+ throw new SeekException($this, $offset);
+ } else {
+ $this->stream->read($offset - $current);
+ }
+ }
+ }
+
+ $this->offset = $offset;
+
+ return $this;
+ }
+
+ /**
+ * Set the limit of bytes that the decorator allows to be read from the
+ * stream.
+ *
+ * @param int $limit Number of bytes to allow to be read from the stream.
+ * Use -1 for no limit.
+ * @return self
+ */
+ public function setLimit($limit)
+ {
+ $this->limit = $limit;
+
+ return $this;
+ }
+
+ public function read($length)
+ {
+ if ($this->limit == -1) {
+ return $this->stream->read($length);
+ }
+
+ // Check if the current position is less than the total allowed
+ // bytes + original offset
+ $remaining = ($this->offset + $this->limit) - $this->stream->tell();
+ if ($remaining > 0) {
+ // Only return the amount of requested data, ensuring that the byte
+ // limit is not exceeded
+ return $this->stream->read(min($remaining, $length));
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php b/public/system/storage/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php
new file mode 100644
index 0000000..c1433ad
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php
@@ -0,0 +1,11 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * This interface is deprecated and should no longer be used. Just use
+ * StreamInterface now that the getMetadata method has been added to
+ * StreamInterface.
+ *
+ * @deprecated
+ */
+interface MetadataStreamInterface extends StreamInterface {}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/NoSeekStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/NoSeekStream.php
new file mode 100644
index 0000000..3d42395
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/NoSeekStream.php
@@ -0,0 +1,25 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Stream decorator that prevents a stream from being seeked
+ */
+class NoSeekStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function attach($stream)
+ {
+ $this->stream->attach($stream);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/NullStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/NullStream.php
new file mode 100644
index 0000000..41ee776
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/NullStream.php
@@ -0,0 +1,78 @@
+<?php
+namespace GuzzleHttp\Stream;
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Does not store any data written to it.
+ */
+class NullStream implements StreamInterface
+{
+ public function __toString()
+ {
+ return '';
+ }
+
+ public function getContents()
+ {
+ return '';
+ }
+
+ public function close() {}
+
+ public function detach() {}
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function getSize()
+ {
+ return 0;
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return true;
+ }
+
+ public function isSeekable()
+ {
+ return true;
+ }
+
+ public function eof()
+ {
+ return true;
+ }
+
+ public function tell()
+ {
+ return 0;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function read($length)
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ return strlen($string);
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $key ? null : [];
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/PumpStream.php b/public/system/storage/vendor/guzzlehttp/streams/src/PumpStream.php
new file mode 100644
index 0000000..9963207
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/PumpStream.php
@@ -0,0 +1,161 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Provides a read only stream that pumps data from a PHP callable.
+ *
+ * When invoking the provided callable, the PumpStream will pass the amount of
+ * data requested to read to the callable. The callable can choose to ignore
+ * this value and return fewer or more bytes than requested. Any extra data
+ * returned by the provided callable is buffered internally until drained using
+ * the read() function of the PumpStream. The provided callable MUST return
+ * false when there is no more data to read.
+ */
+class PumpStream implements StreamInterface
+{
+ /** @var callable */
+ private $source;
+
+ /** @var int */
+ private $size;
+
+ /** @var int */
+ private $tellPos = 0;
+
+ /** @var array */
+ private $metadata;
+
+ /** @var BufferStream */
+ private $buffer;
+
+ /**
+ * @param callable $source Source of the stream data. The callable MAY
+ * accept an integer argument used to control the
+ * amount of data to return. The callable MUST
+ * return a string when called, or false on error
+ * or EOF.
+ * @param array $options Stream options:
+ * - metadata: Hash of metadata to use with stream.
+ * - size: Size of the stream, if known.
+ */
+ public function __construct(callable $source, array $options = [])
+ {
+ $this->source = $source;
+ $this->size = isset($options['size']) ? $options['size'] : null;
+ $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
+ $this->buffer = new BufferStream();
+ }
+
+ public function __toString()
+ {
+ return Utils::copyToString($this);
+ }
+
+ public function close()
+ {
+ $this->detach();
+ }
+
+ public function detach()
+ {
+ $this->tellPos = false;
+ $this->source = null;
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function getSize()
+ {
+ return $this->size;
+ }
+
+ public function tell()
+ {
+ return $this->tellPos;
+ }
+
+ public function eof()
+ {
+ return !$this->source;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ return false;
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function read($length)
+ {
+ $data = $this->buffer->read($length);
+ $readLen = strlen($data);
+ $this->tellPos += $readLen;
+ $remaining = $length - $readLen;
+
+ if ($remaining) {
+ $this->pump($remaining);
+ $data .= $this->buffer->read($remaining);
+ $this->tellPos += strlen($data) - $readLen;
+ }
+
+ return $data;
+ }
+
+ public function getContents()
+ {
+ $result = '';
+ while (!$this->eof()) {
+ $result .= $this->read(1000000);
+ }
+
+ return $result;
+ }
+
+ public function getMetadata($key = null)
+ {
+ if (!$key) {
+ return $this->metadata;
+ }
+
+ return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
+ }
+
+ private function pump($length)
+ {
+ if ($this->source) {
+ do {
+ $data = call_user_func($this->source, $length);
+ if ($data === false || $data === null) {
+ $this->source = null;
+ return;
+ }
+ $this->buffer->write($data);
+ $length -= strlen($data);
+ } while ($length > 0);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/Stream.php b/public/system/storage/vendor/guzzlehttp/streams/src/Stream.php
new file mode 100644
index 0000000..7adbc5e
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/Stream.php
@@ -0,0 +1,261 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * PHP stream implementation
+ */
+class Stream implements StreamInterface
+{
+ private $stream;
+ private $size;
+ private $seekable;
+ private $readable;
+ private $writable;
+ private $uri;
+ private $customMetadata;
+
+ /** @var array Hash of readable and writable stream types */
+ private static $readWriteHash = [
+ 'read' => [
+ 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
+ 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
+ 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
+ 'x+t' => true, 'c+t' => true, 'a+' => true
+ ],
+ 'write' => [
+ 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
+ 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
+ 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
+ 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
+ ]
+ ];
+
+ /**
+ * Create a new stream based on the input type.
+ *
+ * This factory accepts the same associative array of options as described
+ * in the constructor.
+ *
+ * @param resource|string|StreamInterface $resource Entity body data
+ * @param array $options Additional options
+ *
+ * @return Stream
+ * @throws \InvalidArgumentException if the $resource arg is not valid.
+ */
+ public static function factory($resource = '', array $options = [])
+ {
+ $type = gettype($resource);
+
+ if ($type == 'string') {
+ $stream = fopen('php://temp', 'r+');
+ if ($resource !== '') {
+ fwrite($stream, $resource);
+ fseek($stream, 0);
+ }
+ return new self($stream, $options);
+ }
+
+ if ($type == 'resource') {
+ return new self($resource, $options);
+ }
+
+ if ($resource instanceof StreamInterface) {
+ return $resource;
+ }
+
+ if ($type == 'object' && method_exists($resource, '__toString')) {
+ return self::factory((string) $resource, $options);
+ }
+
+ if (is_callable($resource)) {
+ return new PumpStream($resource, $options);
+ }
+
+ if ($resource instanceof \Iterator) {
+ return new PumpStream(function () use ($resource) {
+ if (!$resource->valid()) {
+ return false;
+ }
+ $result = $resource->current();
+ $resource->next();
+ return $result;
+ }, $options);
+ }
+
+ throw new \InvalidArgumentException('Invalid resource type: ' . $type);
+ }
+
+ /**
+ * This constructor accepts an associative array of options.
+ *
+ * - size: (int) If a read stream would otherwise have an indeterminate
+ * size, but the size is known due to foreknownledge, then you can
+ * provide that size, in bytes.
+ * - metadata: (array) Any additional metadata to return when the metadata
+ * of the stream is accessed.
+ *
+ * @param resource $stream Stream resource to wrap.
+ * @param array $options Associative array of options.
+ *
+ * @throws \InvalidArgumentException if the stream is not a stream resource
+ */
+ public function __construct($stream, $options = [])
+ {
+ if (!is_resource($stream)) {
+ throw new \InvalidArgumentException('Stream must be a resource');
+ }
+
+ if (isset($options['size'])) {
+ $this->size = $options['size'];
+ }
+
+ $this->customMetadata = isset($options['metadata'])
+ ? $options['metadata']
+ : [];
+
+ $this->attach($stream);
+ }
+
+ /**
+ * Closes the stream when the destructed
+ */
+ public function __destruct()
+ {
+ $this->close();
+ }
+
+ public function __toString()
+ {
+ if (!$this->stream) {
+ return '';
+ }
+
+ $this->seek(0);
+
+ return (string) stream_get_contents($this->stream);
+ }
+
+ public function getContents()
+ {
+ return $this->stream ? stream_get_contents($this->stream) : '';
+ }
+
+ public function close()
+ {
+ if (is_resource($this->stream)) {
+ fclose($this->stream);
+ }
+
+ $this->detach();
+ }
+
+ public function detach()
+ {
+ $result = $this->stream;
+ $this->stream = $this->size = $this->uri = null;
+ $this->readable = $this->writable = $this->seekable = false;
+
+ return $result;
+ }
+
+ public function attach($stream)
+ {
+ $this->stream = $stream;
+ $meta = stream_get_meta_data($this->stream);
+ $this->seekable = $meta['seekable'];
+ $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
+ $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
+ $this->uri = $this->getMetadata('uri');
+ }
+
+ public function getSize()
+ {
+ if ($this->size !== null) {
+ return $this->size;
+ }
+
+ if (!$this->stream) {
+ return null;
+ }
+
+ // Clear the stat cache if the stream has a URI
+ if ($this->uri) {
+ clearstatcache(true, $this->uri);
+ }
+
+ $stats = fstat($this->stream);
+ if (isset($stats['size'])) {
+ $this->size = $stats['size'];
+ return $this->size;
+ }
+
+ return null;
+ }
+
+ public function isReadable()
+ {
+ return $this->readable;
+ }
+
+ public function isWritable()
+ {
+ return $this->writable;
+ }
+
+ public function isSeekable()
+ {
+ return $this->seekable;
+ }
+
+ public function eof()
+ {
+ return !$this->stream || feof($this->stream);
+ }
+
+ public function tell()
+ {
+ return $this->stream ? ftell($this->stream) : false;
+ }
+
+ public function setSize($size)
+ {
+ $this->size = $size;
+
+ return $this;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return $this->seekable
+ ? fseek($this->stream, $offset, $whence) === 0
+ : false;
+ }
+
+ public function read($length)
+ {
+ return $this->readable ? fread($this->stream, $length) : false;
+ }
+
+ public function write($string)
+ {
+ // We can't know the size after writing anything
+ $this->size = null;
+
+ return $this->writable ? fwrite($this->stream, $string) : false;
+ }
+
+ public function getMetadata($key = null)
+ {
+ if (!$this->stream) {
+ return $key ? null : [];
+ } elseif (!$key) {
+ return $this->customMetadata + stream_get_meta_data($this->stream);
+ } elseif (isset($this->customMetadata[$key])) {
+ return $this->customMetadata[$key];
+ }
+
+ $meta = stream_get_meta_data($this->stream);
+
+ return isset($meta[$key]) ? $meta[$key] : null;
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php b/public/system/storage/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php
new file mode 100644
index 0000000..39c19c5
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php
@@ -0,0 +1,143 @@
+<?php
+namespace GuzzleHttp\Stream;
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Stream decorator trait
+ * @property StreamInterface stream
+ */
+trait StreamDecoratorTrait
+{
+ /**
+ * @param StreamInterface $stream Stream to decorate
+ */
+ public function __construct(StreamInterface $stream)
+ {
+ $this->stream = $stream;
+ }
+
+ /**
+ * Magic method used to create a new stream if streams are not added in
+ * the constructor of a decorator (e.g., LazyOpenStream).
+ */
+ public function __get($name)
+ {
+ if ($name == 'stream') {
+ $this->stream = $this->createStream();
+ return $this->stream;
+ }
+
+ throw new \UnexpectedValueException("$name not found on class");
+ }
+
+ public function __toString()
+ {
+ try {
+ $this->seek(0);
+ return $this->getContents();
+ } catch (\Exception $e) {
+ // Really, PHP? https://bugs.php.net/bug.php?id=53648
+ trigger_error('StreamDecorator::__toString exception: '
+ . (string) $e, E_USER_ERROR);
+ return '';
+ }
+ }
+
+ public function getContents()
+ {
+ return Utils::copyToString($this);
+ }
+
+ /**
+ * Allow decorators to implement custom methods
+ *
+ * @param string $method Missing method name
+ * @param array $args Method arguments
+ *
+ * @return mixed
+ */
+ public function __call($method, array $args)
+ {
+ $result = call_user_func_array(array($this->stream, $method), $args);
+
+ // Always return the wrapped object if the result is a return $this
+ return $result === $this->stream ? $this : $result;
+ }
+
+ public function close()
+ {
+ $this->stream->close();
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $this->stream->getMetadata($key);
+ }
+
+ public function detach()
+ {
+ return $this->stream->detach();
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function getSize()
+ {
+ return $this->stream->getSize();
+ }
+
+ public function eof()
+ {
+ return $this->stream->eof();
+ }
+
+ public function tell()
+ {
+ return $this->stream->tell();
+ }
+
+ public function isReadable()
+ {
+ return $this->stream->isReadable();
+ }
+
+ public function isWritable()
+ {
+ return $this->stream->isWritable();
+ }
+
+ public function isSeekable()
+ {
+ return $this->stream->isSeekable();
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return $this->stream->seek($offset, $whence);
+ }
+
+ public function read($length)
+ {
+ return $this->stream->read($length);
+ }
+
+ public function write($string)
+ {
+ return $this->stream->write($string);
+ }
+
+ /**
+ * Implement in subclasses to dynamically create streams when requested.
+ *
+ * @return StreamInterface
+ * @throws \BadMethodCallException
+ */
+ protected function createStream()
+ {
+ throw new \BadMethodCallException('createStream() not implemented in '
+ . get_class($this));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/StreamInterface.php b/public/system/storage/vendor/guzzlehttp/streams/src/StreamInterface.php
new file mode 100644
index 0000000..fd19c6f
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/StreamInterface.php
@@ -0,0 +1,159 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Describes a stream instance.
+ */
+interface StreamInterface
+{
+ /**
+ * Attempts to seek to the beginning of the stream and reads all data into
+ * a string until the end of the stream is reached.
+ *
+ * Warning: This could attempt to load a large amount of data into memory.
+ *
+ * @return string
+ */
+ public function __toString();
+
+ /**
+ * Closes the stream and any underlying resources.
+ */
+ public function close();
+
+ /**
+ * Separates any underlying resources from the stream.
+ *
+ * After the underlying resource has been detached, the stream object is in
+ * an unusable state. If you wish to use a Stream object as a PHP stream
+ * but keep the Stream object in a consistent state, use
+ * {@see GuzzleHttp\Stream\GuzzleStreamWrapper::getResource}.
+ *
+ * @return resource|null Returns the underlying PHP stream resource or null
+ * if the Stream object did not utilize an underlying
+ * stream resource.
+ */
+ public function detach();
+
+ /**
+ * Replaces the underlying stream resource with the provided stream.
+ *
+ * Use this method to replace the underlying stream with another; as an
+ * example, in server-side code, if you decide to return a file, you
+ * would replace the original content-oriented stream with the file
+ * stream.
+ *
+ * Any internal state such as caching of cursor position should be reset
+ * when attach() is called, as the stream has changed.
+ *
+ * @param resource $stream
+ *
+ * @return void
+ */
+ public function attach($stream);
+
+ /**
+ * Get the size of the stream if known
+ *
+ * @return int|null Returns the size in bytes if known, or null if unknown
+ */
+ public function getSize();
+
+ /**
+ * Returns the current position of the file read/write pointer
+ *
+ * @return int|bool Returns the position of the file pointer or false on error
+ */
+ public function tell();
+
+ /**
+ * Returns true if the stream is at the end of the stream.
+ *
+ * @return bool
+ */
+ public function eof();
+
+ /**
+ * Returns whether or not the stream is seekable
+ *
+ * @return bool
+ */
+ public function isSeekable();
+
+ /**
+ * Seek to a position in the stream
+ *
+ * @param int $offset Stream offset
+ * @param int $whence Specifies how the cursor position will be calculated
+ * based on the seek offset. Valid values are identical
+ * to the built-in PHP $whence values for `fseek()`.
+ * SEEK_SET: Set position equal to offset bytes
+ * SEEK_CUR: Set position to current location plus offset
+ * SEEK_END: Set position to end-of-stream plus offset
+ *
+ * @return bool Returns true on success or false on failure
+ * @link http://www.php.net/manual/en/function.fseek.php
+ */
+ public function seek($offset, $whence = SEEK_SET);
+
+ /**
+ * Returns whether or not the stream is writable
+ *
+ * @return bool
+ */
+ public function isWritable();
+
+ /**
+ * Write data to the stream
+ *
+ * @param string $string The string that is to be written.
+ *
+ * @return int|bool Returns the number of bytes written to the stream on
+ * success returns false on failure (e.g., broken pipe,
+ * writer needs to slow down, buffer is full, etc.)
+ */
+ public function write($string);
+
+ /**
+ * Returns whether or not the stream is readable
+ *
+ * @return bool
+ */
+ public function isReadable();
+
+ /**
+ * Read data from the stream
+ *
+ * @param int $length Read up to $length bytes from the object and return
+ * them. Fewer than $length bytes may be returned if
+ * underlying stream call returns fewer bytes.
+ *
+ * @return string Returns the data read from the stream.
+ */
+ public function read($length);
+
+ /**
+ * Returns the remaining contents of the stream as a string.
+ *
+ * Note: this could potentially load a large amount of data into memory.
+ *
+ * @return string
+ */
+ public function getContents();
+
+ /**
+ * Get stream metadata as an associative array or retrieve a specific key.
+ *
+ * The keys returned are identical to the keys returned from PHP's
+ * stream_get_meta_data() function.
+ *
+ * @param string $key Specific metadata to retrieve.
+ *
+ * @return array|mixed|null Returns an associative array if no key is
+ * no key is provided. Returns a specific key
+ * value if a key is provided and the value is
+ * found, or null if the key is not found.
+ * @see http://php.net/manual/en/function.stream-get-meta-data.php
+ */
+ public function getMetadata($key = null);
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/src/Utils.php b/public/system/storage/vendor/guzzlehttp/streams/src/Utils.php
new file mode 100644
index 0000000..94cb42d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/src/Utils.php
@@ -0,0 +1,196 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+
+/**
+ * Static utility class because PHP's autoloaders don't support the concept
+ * of namespaced function autoloading.
+ */
+class Utils
+{
+ /**
+ * Safely opens a PHP stream resource using a filename.
+ *
+ * When fopen fails, PHP normally raises a warning. This function adds an
+ * error handler that checks for errors and throws an exception instead.
+ *
+ * @param string $filename File to open
+ * @param string $mode Mode used to open the file
+ *
+ * @return resource
+ * @throws \RuntimeException if the file cannot be opened
+ */
+ public static function open($filename, $mode)
+ {
+ $ex = null;
+ set_error_handler(function () use ($filename, $mode, &$ex) {
+ $ex = new \RuntimeException(sprintf(
+ 'Unable to open %s using mode %s: %s',
+ $filename,
+ $mode,
+ func_get_args()[1]
+ ));
+ });
+
+ $handle = fopen($filename, $mode);
+ restore_error_handler();
+
+ if ($ex) {
+ /** @var $ex \RuntimeException */
+ throw $ex;
+ }
+
+ return $handle;
+ }
+
+ /**
+ * Copy the contents of a stream into a string until the given number of
+ * bytes have been read.
+ *
+ * @param StreamInterface $stream Stream to read
+ * @param int $maxLen Maximum number of bytes to read. Pass -1
+ * to read the entire stream.
+ * @return string
+ */
+ public static function copyToString(StreamInterface $stream, $maxLen = -1)
+ {
+ $buffer = '';
+
+ if ($maxLen === -1) {
+ while (!$stream->eof()) {
+ $buf = $stream->read(1048576);
+ if ($buf === false) {
+ break;
+ }
+ $buffer .= $buf;
+ }
+ return $buffer;
+ }
+
+ $len = 0;
+ while (!$stream->eof() && $len < $maxLen) {
+ $buf = $stream->read($maxLen - $len);
+ if ($buf === false) {
+ break;
+ }
+ $buffer .= $buf;
+ $len = strlen($buffer);
+ }
+
+ return $buffer;
+ }
+
+ /**
+ * Copy the contents of a stream into another stream until the given number
+ * of bytes have been read.
+ *
+ * @param StreamInterface $source Stream to read from
+ * @param StreamInterface $dest Stream to write to
+ * @param int $maxLen Maximum number of bytes to read. Pass -1
+ * to read the entire stream.
+ */
+ public static function copyToStream(
+ StreamInterface $source,
+ StreamInterface $dest,
+ $maxLen = -1
+ ) {
+ if ($maxLen === -1) {
+ while (!$source->eof()) {
+ if (!$dest->write($source->read(1048576))) {
+ break;
+ }
+ }
+ return;
+ }
+
+ $bytes = 0;
+ while (!$source->eof()) {
+ $buf = $source->read($maxLen - $bytes);
+ if (!($len = strlen($buf))) {
+ break;
+ }
+ $bytes += $len;
+ $dest->write($buf);
+ if ($bytes == $maxLen) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Calculate a hash of a Stream
+ *
+ * @param StreamInterface $stream Stream to calculate the hash for
+ * @param string $algo Hash algorithm (e.g. md5, crc32, etc)
+ * @param bool $rawOutput Whether or not to use raw output
+ *
+ * @return string Returns the hash of the stream
+ * @throws SeekException
+ */
+ public static function hash(
+ StreamInterface $stream,
+ $algo,
+ $rawOutput = false
+ ) {
+ $pos = $stream->tell();
+
+ if ($pos > 0 && !$stream->seek(0)) {
+ throw new SeekException($stream);
+ }
+
+ $ctx = hash_init($algo);
+ while (!$stream->eof()) {
+ hash_update($ctx, $stream->read(1048576));
+ }
+
+ $out = hash_final($ctx, (bool) $rawOutput);
+ $stream->seek($pos);
+
+ return $out;
+ }
+
+ /**
+ * Read a line from the stream up to the maximum allowed buffer length
+ *
+ * @param StreamInterface $stream Stream to read from
+ * @param int $maxLength Maximum buffer length
+ *
+ * @return string|bool
+ */
+ public static function readline(StreamInterface $stream, $maxLength = null)
+ {
+ $buffer = '';
+ $size = 0;
+
+ while (!$stream->eof()) {
+ if (false === ($byte = $stream->read(1))) {
+ return $buffer;
+ }
+ $buffer .= $byte;
+ // Break when a new line is found or the max length - 1 is reached
+ if ($byte == PHP_EOL || ++$size == $maxLength - 1) {
+ break;
+ }
+ }
+
+ return $buffer;
+ }
+
+ /**
+ * Alias of GuzzleHttp\Stream\Stream::factory.
+ *
+ * @param mixed $resource Resource to create
+ * @param array $options Associative array of stream options defined in
+ * {@see \GuzzleHttp\Stream\Stream::__construct}
+ *
+ * @return StreamInterface
+ *
+ * @see GuzzleHttp\Stream\Stream::factory
+ * @see GuzzleHttp\Stream\Stream::__construct
+ */
+ public static function create($resource, array $options = [])
+ {
+ return Stream::factory($resource, $options);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/AppendStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/AppendStreamTest.php
new file mode 100644
index 0000000..78798d9
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/AppendStreamTest.php
@@ -0,0 +1,178 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\AppendStream;
+use GuzzleHttp\Stream\Stream;
+
+class AppendStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Each stream must be readable
+ */
+ public function testValidatesStreamsAreReadable()
+ {
+ $a = new AppendStream();
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isReadable'])
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $a->addStream($s);
+ }
+
+ public function testValidatesSeekType()
+ {
+ $a = new AppendStream();
+ $this->assertFalse($a->seek(100, SEEK_CUR));
+ }
+
+ public function testTriesToRewindOnSeek()
+ {
+ $a = new AppendStream();
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isReadable', 'seek', 'isSeekable'])
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(true));
+ $s->expects($this->once())
+ ->method('isSeekable')
+ ->will($this->returnValue(true));
+ $s->expects($this->once())
+ ->method('seek')
+ ->will($this->returnValue(false));
+ $a->addStream($s);
+ $this->assertFalse($a->seek(10));
+ }
+
+ public function testSeeksToPositionByReading()
+ {
+ $a = new AppendStream([
+ Stream::factory('foo'),
+ Stream::factory('bar'),
+ Stream::factory('baz'),
+ ]);
+
+ $this->assertTrue($a->seek(3));
+ $this->assertEquals(3, $a->tell());
+ $this->assertEquals('bar', $a->read(3));
+ $a->seek(6);
+ $this->assertEquals(6, $a->tell());
+ $this->assertEquals('baz', $a->read(3));
+ }
+
+ public function testDetachesEachStream()
+ {
+ $s1 = Stream::factory('foo');
+ $s2 = Stream::factory('foo');
+ $a = new AppendStream([$s1, $s2]);
+ $this->assertSame('foofoo', (string) $a);
+ $a->detach();
+ $this->assertSame('', (string) $a);
+ $this->assertSame(0, $a->getSize());
+ }
+
+ public function testClosesEachStream()
+ {
+ $s1 = Stream::factory('foo');
+ $a = new AppendStream([$s1]);
+ $a->close();
+ $this->assertSame('', (string) $a);
+ }
+
+ public function testIsNotWritable()
+ {
+ $a = new AppendStream([Stream::factory('foo')]);
+ $this->assertFalse($a->isWritable());
+ $this->assertTrue($a->isSeekable());
+ $this->assertTrue($a->isReadable());
+ $this->assertFalse($a->write('foo'));
+ }
+
+ public function testDoesNotNeedStreams()
+ {
+ $a = new AppendStream();
+ $this->assertEquals('', (string) $a);
+ }
+
+ public function testCanReadFromMultipleStreams()
+ {
+ $a = new AppendStream([
+ Stream::factory('foo'),
+ Stream::factory('bar'),
+ Stream::factory('baz'),
+ ]);
+ $this->assertFalse($a->eof());
+ $this->assertSame(0, $a->tell());
+ $this->assertEquals('foo', $a->read(3));
+ $this->assertEquals('bar', $a->read(3));
+ $this->assertEquals('baz', $a->read(3));
+ $this->assertTrue($a->eof());
+ $this->assertSame(9, $a->tell());
+ $this->assertEquals('foobarbaz', (string) $a);
+ }
+
+ public function testCanDetermineSizeFromMultipleStreams()
+ {
+ $a = new AppendStream([
+ Stream::factory('foo'),
+ Stream::factory('bar')
+ ]);
+ $this->assertEquals(6, $a->getSize());
+
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isSeekable', 'isReadable'])
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isSeekable')
+ ->will($this->returnValue(null));
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(true));
+ $a->addStream($s);
+ $this->assertNull($a->getSize());
+ }
+
+ public function testCatchesExceptionsWhenCastingToString()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['read', 'isReadable', 'eof'])
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('read')
+ ->will($this->throwException(new \RuntimeException('foo')));
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(true));
+ $s->expects($this->any())
+ ->method('eof')
+ ->will($this->returnValue(false));
+ $a = new AppendStream([$s]);
+ $this->assertFalse($a->eof());
+ $this->assertSame('', (string) $a);
+ }
+
+ public function testCanDetach()
+ {
+ $s = new AppendStream();
+ $s->detach();
+ }
+
+ public function testReturnsEmptyMetadata()
+ {
+ $s = new AppendStream();
+ $this->assertEquals([], $s->getMetadata());
+ $this->assertNull($s->getMetadata('foo'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = new AppendStream();
+ $p->attach('a');
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php
new file mode 100644
index 0000000..8c78995
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php
@@ -0,0 +1,186 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\AsyncReadStream;
+use GuzzleHttp\Stream\BufferStream;
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\Stream;
+
+class AsyncReadStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Buffer must be readable and writable
+ */
+ public function testValidatesReadableBuffer()
+ {
+ new AsyncReadStream(FnStream::decorate(
+ Stream::factory(),
+ ['isReadable' => function () { return false; }]
+ ));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Buffer must be readable and writable
+ */
+ public function testValidatesWritableBuffer()
+ {
+ new AsyncReadStream(FnStream::decorate(
+ Stream::factory(),
+ ['isWritable' => function () { return false; }]
+ ));
+ }
+
+ public function testValidatesHwmMetadata()
+ {
+ $a = new AsyncReadStream(Stream::factory(), [
+ 'drain' => function() {}
+ ]);
+ $this->assertNull($this->readAttribute($a, 'drain'));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage pump must be callable
+ */
+ public function testValidatesPumpIsCallable()
+ {
+ new AsyncReadStream(new BufferStream(), ['pump' => true]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage drain must be callable
+ */
+ public function testValidatesDrainIsCallable()
+ {
+ new AsyncReadStream(new BufferStream(), ['drain' => true]);
+ }
+
+ public function testCanInitialize()
+ {
+ $buffer = new BufferStream();
+ $a = new AsyncReadStream($buffer, [
+ 'size' => 10,
+ 'drain' => function () {},
+ 'pump' => function () {},
+ ]);
+ $this->assertSame($buffer, $this->readAttribute($a, 'stream'));
+ $this->assertTrue(is_callable($this->readAttribute($a, 'drain')));
+ $this->assertTrue(is_callable($this->readAttribute($a, 'pump')));
+ $this->assertTrue($a->isReadable());
+ $this->assertFalse($a->isSeekable());
+ $this->assertFalse($a->isWritable());
+ $this->assertFalse($a->write('foo'));
+ $this->assertEquals(10, $a->getSize());
+ }
+
+ public function testReadsFromBufferWithNoDrainOrPump()
+ {
+ $buffer = new BufferStream();
+ $a = new AsyncReadStream($buffer);
+ $buffer->write('foo');
+ $this->assertNull($a->getSize());
+ $this->assertEquals('foo', $a->read(10));
+ $this->assertEquals('', $a->read(10));
+ }
+
+ public function testCallsPumpForMoreDataWhenRequested()
+ {
+ $called = 0;
+ $buffer = new BufferStream();
+ $a = new AsyncReadStream($buffer, [
+ 'pump' => function ($size) use (&$called) {
+ $called++;
+ return str_repeat('.', $size);
+ }
+ ]);
+ $buffer->write('foobar');
+ $this->assertEquals('foo', $a->read(3));
+ $this->assertEquals(0, $called);
+ $this->assertEquals('bar.....', $a->read(8));
+ $this->assertEquals(1, $called);
+ $this->assertEquals('..', $a->read(2));
+ $this->assertEquals(2, $called);
+ }
+
+ public function testCallsDrainWhenNeeded()
+ {
+ $called = 0;
+ $buffer = new BufferStream(5);
+ $a = new AsyncReadStream($buffer, [
+ 'drain' => function (BufferStream $b) use (&$called, $buffer) {
+ $this->assertSame($b, $buffer);
+ $called++;
+ }
+ ]);
+
+ $buffer->write('foobar');
+ $this->assertEquals(6, $buffer->getSize());
+ $this->assertEquals(0, $called);
+
+ $a->read(3);
+ $this->assertTrue($this->readAttribute($a, 'needsDrain'));
+ $this->assertEquals(3, $buffer->getSize());
+ $this->assertEquals(0, $called);
+
+ $a->read(3);
+ $this->assertEquals(0, $buffer->getSize());
+ $this->assertFalse($this->readAttribute($a, 'needsDrain'));
+ $this->assertEquals(1, $called);
+ }
+
+ public function testCreatesBufferWithNoConfig()
+ {
+ list($buffer, $async) = AsyncReadStream::create();
+ $this->assertInstanceOf('GuzzleHttp\Stream\BufferStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ }
+
+ public function testCreatesBufferWithSpecifiedBuffer()
+ {
+ $buf = new BufferStream();
+ list($buffer, $async) = AsyncReadStream::create(['buffer' => $buf]);
+ $this->assertSame($buf, $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ }
+
+ public function testCreatesNullStream()
+ {
+ list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 0]);
+ $this->assertInstanceOf('GuzzleHttp\Stream\NullStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ }
+
+ public function testCreatesDroppingStream()
+ {
+ list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 5]);
+ $this->assertInstanceOf('GuzzleHttp\Stream\DroppingStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ $buffer->write('12345678910');
+ $this->assertEquals(5, $buffer->getSize());
+ }
+
+ public function testCreatesOnWriteStream()
+ {
+ $c = 0;
+ $b = new BufferStream();
+ list($buffer, $async) = AsyncReadStream::create([
+ 'buffer' => $b,
+ 'write' => function (BufferStream $buf, $data) use (&$c, $b) {
+ $this->assertSame($buf, $b);
+ $this->assertEquals('foo', $data);
+ $c++;
+ }
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Stream\FnStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ $this->assertEquals(0, $c);
+ $this->assertEquals(3, $buffer->write('foo'));
+ $this->assertEquals(1, $c);
+ $this->assertEquals(3, $buffer->write('foo'));
+ $this->assertEquals(2, $c);
+ $this->assertEquals('foofoo', (string) $buffer);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/BufferStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/BufferStreamTest.php
new file mode 100644
index 0000000..f9bfea2
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/BufferStreamTest.php
@@ -0,0 +1,69 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\BufferStream;
+
+class BufferStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadata()
+ {
+ $b = new BufferStream(10);
+ $this->assertTrue($b->isReadable());
+ $this->assertTrue($b->isWritable());
+ $this->assertFalse($b->isSeekable());
+ $this->assertEquals(null, $b->getMetadata('foo'));
+ $this->assertEquals(10, $b->getMetadata('hwm'));
+ $this->assertEquals([], $b->getMetadata());
+ }
+
+ public function testRemovesReadDataFromBuffer()
+ {
+ $b = new BufferStream();
+ $this->assertEquals(3, $b->write('foo'));
+ $this->assertEquals(3, $b->getSize());
+ $this->assertFalse($b->eof());
+ $this->assertEquals('foo', $b->read(10));
+ $this->assertTrue($b->eof());
+ $this->assertEquals('', $b->read(10));
+ }
+
+ public function testCanCastToStringOrGetContents()
+ {
+ $b = new BufferStream();
+ $b->write('foo');
+ $b->write('baz');
+ $this->assertEquals('foo', $b->read(3));
+ $b->write('bar');
+ $this->assertEquals('bazbar', (string) $b);
+ $this->assertFalse($b->tell());
+ }
+
+ public function testDetachClearsBuffer()
+ {
+ $b = new BufferStream();
+ $b->write('foo');
+ $b->detach();
+ $this->assertEquals(0, $b->tell());
+ $this->assertTrue($b->eof());
+ $this->assertEquals(3, $b->write('abc'));
+ $this->assertEquals('abc', $b->read(10));
+ }
+
+ public function testExceedingHighwaterMarkReturnsFalseButStillBuffers()
+ {
+ $b = new BufferStream(5);
+ $this->assertEquals(3, $b->write('hi '));
+ $this->assertFalse($b->write('hello'));
+ $this->assertEquals('hi hello', (string) $b);
+ $this->assertEquals(4, $b->write('test'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = new BufferStream();
+ $p->attach('a');
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/CachingStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/CachingStreamTest.php
new file mode 100644
index 0000000..ea969b3
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/CachingStreamTest.php
@@ -0,0 +1,136 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\CachingStream;
+use GuzzleHttp\Stream\Utils;
+
+/**
+ * @covers GuzzleHttp\Stream\CachingStream
+ */
+class CachingStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /** @var CachingStream */
+ protected $body;
+
+ /** @var Stream */
+ protected $decorated;
+
+ public function setUp()
+ {
+ $this->decorated = Stream::factory('testing');
+ $this->body = new CachingStream($this->decorated);
+ }
+
+ public function tearDown()
+ {
+ $this->decorated->close();
+ $this->body->close();
+ }
+
+ public function testUsesRemoteSizeIfPossible()
+ {
+ $body = Stream::factory('test');
+ $caching = new CachingStream($body);
+ $this->assertEquals(4, $caching->getSize());
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot seek to byte 10
+ */
+ public function testCannotSeekPastWhatHasBeenRead()
+ {
+ $this->body->seek(10);
+ }
+
+ public function testCannotUseSeekEnd()
+ {
+ $this->assertFalse($this->body->seek(2, SEEK_END));
+ }
+
+ public function testRewindUsesSeek()
+ {
+ $a = Stream::factory('foo');
+ $d = $this->getMockBuilder('GuzzleHttp\Stream\CachingStream')
+ ->setMethods(array('seek'))
+ ->setConstructorArgs(array($a))
+ ->getMock();
+ $d->expects($this->once())
+ ->method('seek')
+ ->with(0)
+ ->will($this->returnValue(true));
+ $d->seek(0);
+ }
+
+ public function testCanSeekToReadBytes()
+ {
+ $this->assertEquals('te', $this->body->read(2));
+ $this->body->seek(0);
+ $this->assertEquals('test', $this->body->read(4));
+ $this->assertEquals(4, $this->body->tell());
+ $this->body->seek(2);
+ $this->assertEquals(2, $this->body->tell());
+ $this->body->seek(2, SEEK_CUR);
+ $this->assertEquals(4, $this->body->tell());
+ $this->assertEquals('ing', $this->body->read(3));
+ }
+
+ public function testWritesToBufferStream()
+ {
+ $this->body->read(2);
+ $this->body->write('hi');
+ $this->body->seek(0);
+ $this->assertEquals('tehiing', (string) $this->body);
+ }
+
+ public function testSkipsOverwrittenBytes()
+ {
+ $decorated = Stream::factory(
+ implode("\n", array_map(function ($n) {
+ return str_pad($n, 4, '0', STR_PAD_LEFT);
+ }, range(0, 25)))
+ );
+
+ $body = new CachingStream($decorated);
+
+ $this->assertEquals("0000\n", Utils::readline($body));
+ $this->assertEquals("0001\n", Utils::readline($body));
+ // Write over part of the body yet to be read, so skip some bytes
+ $this->assertEquals(5, $body->write("TEST\n"));
+ $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
+ // Read, which skips bytes, then reads
+ $this->assertEquals("0003\n", Utils::readline($body));
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
+ $this->assertEquals("0004\n", Utils::readline($body));
+ $this->assertEquals("0005\n", Utils::readline($body));
+
+ // Overwrite part of the cached body (so don't skip any bytes)
+ $body->seek(5);
+ $this->assertEquals(5, $body->write("ABCD\n"));
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
+ $this->assertEquals("TEST\n", Utils::readline($body));
+ $this->assertEquals("0003\n", Utils::readline($body));
+ $this->assertEquals("0004\n", Utils::readline($body));
+ $this->assertEquals("0005\n", Utils::readline($body));
+ $this->assertEquals("0006\n", Utils::readline($body));
+ $this->assertEquals(5, $body->write("1234\n"));
+ $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
+
+ // Seek to 0 and ensure the overwritten bit is replaced
+ $body->seek(0);
+ $this->assertEquals("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", $body->read(50));
+
+ // Ensure that casting it to a string does not include the bit that was overwritten
+ $this->assertContains("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", (string) $body);
+ }
+
+ public function testClosesBothStreams()
+ {
+ $s = fopen('php://temp', 'r');
+ $a = Stream::factory($s);
+ $d = new CachingStream($a);
+ $d->close();
+ $this->assertFalse(is_resource($s));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php
new file mode 100644
index 0000000..bb2cb22
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php
@@ -0,0 +1,26 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\BufferStream;
+use GuzzleHttp\Stream\DroppingStream;
+
+class DroppingStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testBeginsDroppingWhenSizeExceeded()
+ {
+ $stream = new BufferStream();
+ $drop = new DroppingStream($stream, 5);
+ $this->assertEquals(3, $drop->write('hel'));
+ $this->assertFalse($drop->write('lo'));
+ $this->assertEquals(5, $drop->getSize());
+ $this->assertEquals('hello', $drop->read(5));
+ $this->assertEquals(0, $drop->getSize());
+ $drop->write('12345678910');
+ $this->assertEquals(5, $stream->getSize());
+ $this->assertEquals(5, $drop->getSize());
+ $this->assertEquals('12345', (string) $drop);
+ $this->assertEquals(0, $drop->getSize());
+ $drop->write('hello');
+ $this->assertFalse($drop->write('test'));
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php
new file mode 100644
index 0000000..fd8cd1a
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Tests\Stream\Exception;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+use GuzzleHttp\Stream\Stream;
+
+class SeekExceptionTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasStream()
+ {
+ $s = Stream::factory('foo');
+ $e = new SeekException($s, 10);
+ $this->assertSame($s, $e->getStream());
+ $this->assertContains('10', $e->getMessage());
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/FnStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/FnStreamTest.php
new file mode 100644
index 0000000..6cc336b
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/FnStreamTest.php
@@ -0,0 +1,89 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\FnStream;
+
+/**
+ * @covers GuzzleHttp\Stream\FnStream
+ */
+class FnStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \BadMethodCallException
+ * @expectedExceptionMessage seek() is not implemented in the FnStream
+ */
+ public function testThrowsWhenNotImplemented()
+ {
+ (new FnStream([]))->seek(1);
+ }
+
+ public function testProxiesToFunction()
+ {
+ $s = new FnStream([
+ 'read' => function ($len) {
+ $this->assertEquals(3, $len);
+ return 'foo';
+ }
+ ]);
+
+ $this->assertEquals('foo', $s->read(3));
+ }
+
+ public function testCanCloseOnDestruct()
+ {
+ $called = false;
+ $s = new FnStream([
+ 'close' => function () use (&$called) {
+ $called = true;
+ }
+ ]);
+ unset($s);
+ $this->assertTrue($called);
+ }
+
+ public function testDoesNotRequireClose()
+ {
+ $s = new FnStream([]);
+ unset($s);
+ }
+
+ public function testDecoratesStream()
+ {
+ $a = Stream::factory('foo');
+ $b = FnStream::decorate($a, []);
+ $this->assertEquals(3, $b->getSize());
+ $this->assertEquals($b->isWritable(), true);
+ $this->assertEquals($b->isReadable(), true);
+ $this->assertEquals($b->isSeekable(), true);
+ $this->assertEquals($b->read(3), 'foo');
+ $this->assertEquals($b->tell(), 3);
+ $this->assertEquals($a->tell(), 3);
+ $this->assertEquals($b->eof(), true);
+ $this->assertEquals($a->eof(), true);
+ $b->seek(0);
+ $this->assertEquals('foo', (string) $b);
+ $b->seek(0);
+ $this->assertEquals('foo', $b->getContents());
+ $this->assertEquals($a->getMetadata(), $b->getMetadata());
+ $b->seek(0, SEEK_END);
+ $b->write('bar');
+ $this->assertEquals('foobar', (string) $b);
+ $this->assertInternalType('resource', $b->detach());
+ $b->close();
+ }
+
+ public function testDecoratesWithCustomizations()
+ {
+ $called = false;
+ $a = Stream::factory('foo');
+ $b = FnStream::decorate($a, [
+ 'read' => function ($len) use (&$called, $a) {
+ $called = true;
+ return $a->read($len);
+ }
+ ]);
+ $this->assertEquals('foo', $b->read(3));
+ $this->assertTrue($called);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php
new file mode 100644
index 0000000..33c3ecc
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php
@@ -0,0 +1,99 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\GuzzleStreamWrapper;
+use GuzzleHttp\Stream\Stream;
+
+/**
+ * @covers GuzzleHttp\Stream\GuzzleStreamWrapper
+ */
+class GuzzleStreamWrapperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testResource()
+ {
+ $stream = Stream::factory('foo');
+ $handle = GuzzleStreamWrapper::getResource($stream);
+ $this->assertSame('foo', fread($handle, 3));
+ $this->assertSame(3, ftell($handle));
+ $this->assertSame(3, fwrite($handle, 'bar'));
+ $this->assertSame(0, fseek($handle, 0));
+ $this->assertSame('foobar', fread($handle, 6));
+ $this->assertTrue(feof($handle));
+
+ // This fails on HHVM for some reason
+ if (!defined('HHVM_VERSION')) {
+ $this->assertEquals([
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => 33206,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 6,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0,
+ 0 => 0,
+ 1 => 0,
+ 2 => 33206,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 6,
+ 8 => 0,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ ], fstat($handle));
+ }
+
+ $this->assertTrue(fclose($handle));
+ $this->assertSame('foobar', (string) $stream);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesStream()
+ {
+ $stream = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isReadable', 'isWritable'])
+ ->getMockForAbstractClass();
+ $stream->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $stream->expects($this->once())
+ ->method('isWritable')
+ ->will($this->returnValue(false));
+ GuzzleStreamWrapper::getResource($stream);
+ }
+
+ /**
+ * @expectedException \PHPUnit_Framework_Error_Warning
+ */
+ public function testReturnsFalseWhenStreamDoesNotExist()
+ {
+ fopen('guzzle://foo', 'r');
+ }
+
+ public function testCanOpenReadonlyStream()
+ {
+ $stream = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isReadable', 'isWritable'])
+ ->getMockForAbstractClass();
+ $stream->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $stream->expects($this->once())
+ ->method('isWritable')
+ ->will($this->returnValue(true));
+ $r = GuzzleStreamWrapper::getResource($stream);
+ $this->assertInternalType('resource', $r);
+ fclose($r);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/InflateStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/InflateStreamTest.php
new file mode 100644
index 0000000..ead9356
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/InflateStreamTest.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\InflateStream;
+use GuzzleHttp\Stream\Stream;
+
+class InflateStreamtest extends \PHPUnit_Framework_TestCase
+{
+ public function testInflatesStreams()
+ {
+ $content = gzencode('test');
+ $a = Stream::factory($content);
+ $b = new InflateStream($a);
+ $this->assertEquals('test', (string) $b);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php
new file mode 100644
index 0000000..79e0078
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php
@@ -0,0 +1,64 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\LazyOpenStream;
+
+class LazyOpenStreamTest extends \PHPUnit_Framework_TestCase
+{
+ private $fname;
+
+ public function setup()
+ {
+ $this->fname = tempnam('/tmp', 'tfile');
+
+ if (file_exists($this->fname)) {
+ unlink($this->fname);
+ }
+ }
+
+ public function tearDown()
+ {
+ if (file_exists($this->fname)) {
+ unlink($this->fname);
+ }
+ }
+
+ public function testOpensLazily()
+ {
+ $l = new LazyOpenStream($this->fname, 'w+');
+ $l->write('foo');
+ $this->assertInternalType('array', $l->getMetadata());
+ $this->assertFileExists($this->fname);
+ $this->assertEquals('foo', file_get_contents($this->fname));
+ $this->assertEquals('foo', (string) $l);
+ }
+
+ public function testProxiesToFile()
+ {
+ file_put_contents($this->fname, 'foo');
+ $l = new LazyOpenStream($this->fname, 'r');
+ $this->assertEquals('foo', $l->read(4));
+ $this->assertTrue($l->eof());
+ $this->assertEquals(3, $l->tell());
+ $this->assertTrue($l->isReadable());
+ $this->assertTrue($l->isSeekable());
+ $this->assertFalse($l->isWritable());
+ $l->seek(1);
+ $this->assertEquals('oo', $l->getContents());
+ $this->assertEquals('foo', (string) $l);
+ $this->assertEquals(3, $l->getSize());
+ $this->assertInternalType('array', $l->getMetadata());
+ $l->close();
+ }
+
+ public function testDetachesUnderlyingStream()
+ {
+ file_put_contents($this->fname, 'foo');
+ $l = new LazyOpenStream($this->fname, 'r');
+ $r = $l->detach();
+ $this->assertInternalType('resource', $r);
+ fseek($r, 0);
+ $this->assertEquals('foo', stream_get_contents($r));
+ fclose($r);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/LimitStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/LimitStreamTest.php
new file mode 100644
index 0000000..efb1dc5
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/LimitStreamTest.php
@@ -0,0 +1,133 @@
+<?php
+namespace GuzzleHttp\Tests\Http;
+
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\LimitStream;
+use GuzzleHttp\Stream\NoSeekStream;
+
+/**
+ * @covers GuzzleHttp\Stream\LimitStream
+ */
+class LimitStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /** @var LimitStream */
+ protected $body;
+
+ /** @var Stream */
+ protected $decorated;
+
+ public function setUp()
+ {
+ $this->decorated = Stream::factory(fopen(__FILE__, 'r'));
+ $this->body = new LimitStream($this->decorated, 10, 3);
+ }
+
+ public function testReturnsSubset()
+ {
+ $body = new LimitStream(Stream::factory('foo'), -1, 1);
+ $this->assertEquals('oo', (string) $body);
+ $this->assertTrue($body->eof());
+ $body->seek(0);
+ $this->assertFalse($body->eof());
+ $this->assertEquals('oo', $body->read(100));
+ $this->assertTrue($body->eof());
+ }
+
+ public function testReturnsSubsetWhenCastToString()
+ {
+ $body = Stream::factory('foo_baz_bar');
+ $limited = new LimitStream($body, 3, 4);
+ $this->assertEquals('baz', (string) $limited);
+ }
+
+ public function testReturnsSubsetOfEmptyBodyWhenCastToString()
+ {
+ $body = Stream::factory('');
+ $limited = new LimitStream($body, 0, 10);
+ $this->assertEquals('', (string) $limited);
+ }
+
+ public function testSeeksWhenConstructed()
+ {
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ }
+
+ public function testAllowsBoundedSeek()
+ {
+ $this->assertEquals(true, $this->body->seek(100));
+ $this->assertEquals(10, $this->body->tell());
+ $this->assertEquals(13, $this->decorated->tell());
+ $this->assertEquals(true, $this->body->seek(0));
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ $this->assertEquals(false, $this->body->seek(-10));
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ $this->assertEquals(true, $this->body->seek(5));
+ $this->assertEquals(5, $this->body->tell());
+ $this->assertEquals(8, $this->decorated->tell());
+ $this->assertEquals(false, $this->body->seek(1000, SEEK_END));
+ }
+
+ public function testReadsOnlySubsetOfData()
+ {
+ $data = $this->body->read(100);
+ $this->assertEquals(10, strlen($data));
+ $this->assertFalse($this->body->read(1000));
+
+ $this->body->setOffset(10);
+ $newData = $this->body->read(100);
+ $this->assertEquals(10, strlen($newData));
+ $this->assertNotSame($data, $newData);
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\SeekException
+ * @expectedExceptionMessage Could not seek the stream to position 2
+ */
+ public function testThrowsWhenCurrentGreaterThanOffsetSeek()
+ {
+ $a = Stream::factory('foo_bar');
+ $b = new NoSeekStream($a);
+ $c = new LimitStream($b);
+ $a->getContents();
+ $c->setOffset(2);
+ }
+
+ public function testClaimsConsumedWhenReadLimitIsReached()
+ {
+ $this->assertFalse($this->body->eof());
+ $this->body->read(1000);
+ $this->assertTrue($this->body->eof());
+ }
+
+ public function testContentLengthIsBounded()
+ {
+ $this->assertEquals(10, $this->body->getSize());
+ }
+
+ public function testGetContentsIsBasedOnSubset()
+ {
+ $body = new LimitStream(Stream::factory('foobazbar'), 3, 3);
+ $this->assertEquals('baz', $body->getContents());
+ }
+
+ public function testReturnsNullIfSizeCannotBeDetermined()
+ {
+ $a = new FnStream([
+ 'getSize' => function () { return null; },
+ 'tell' => function () { return 0; },
+ ]);
+ $b = new LimitStream($a);
+ $this->assertNull($b->getSize());
+ }
+
+ public function testLengthLessOffsetWhenNoLimitSize()
+ {
+ $a = Stream::factory('foo_bar');
+ $b = new LimitStream($a, -1, 4);
+ $this->assertEquals(3, $b->getSize());
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php
new file mode 100644
index 0000000..21b7c6d
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php
@@ -0,0 +1,41 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\NoSeekStream;
+
+/**
+ * @covers GuzzleHttp\Stream\NoSeekStream
+ * @covers GuzzleHttp\Stream\StreamDecoratorTrait
+ */
+class NoSeekStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCannotSeek()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isSeekable', 'seek'])
+ ->getMockForAbstractClass();
+ $s->expects($this->never())->method('seek');
+ $s->expects($this->never())->method('isSeekable');
+ $wrapped = new NoSeekStream($s);
+ $this->assertFalse($wrapped->isSeekable());
+ $this->assertFalse($wrapped->seek(2));
+ }
+
+ public function testHandlesClose()
+ {
+ $s = Stream::factory('foo');
+ $wrapped = new NoSeekStream($s);
+ $wrapped->close();
+ $this->assertFalse($wrapped->write('foo'));
+ }
+
+ public function testCanAttach()
+ {
+ $s1 = Stream::factory('foo');
+ $s2 = Stream::factory('bar');
+ $wrapped = new NoSeekStream($s1);
+ $wrapped->attach($s2->detach());
+ $this->assertEquals('bar', (string) $wrapped);
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/NullStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/NullStreamTest.php
new file mode 100644
index 0000000..8e41431
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/NullStreamTest.php
@@ -0,0 +1,39 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\NullStream;
+
+class NullStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDoesNothing()
+ {
+ $b = new NullStream();
+ $this->assertEquals('', $b->read(10));
+ $this->assertEquals(4, $b->write('test'));
+ $this->assertEquals('', (string) $b);
+ $this->assertNull($b->getMetadata('a'));
+ $this->assertEquals([], $b->getMetadata());
+ $this->assertEquals(0, $b->getSize());
+ $this->assertEquals('', $b->getContents());
+ $this->assertEquals(0, $b->tell());
+
+ $this->assertTrue($b->isReadable());
+ $this->assertTrue($b->isWritable());
+ $this->assertTrue($b->isSeekable());
+ $this->assertFalse($b->seek(10));
+
+ $this->assertTrue($b->eof());
+ $b->detach();
+ $this->assertTrue($b->eof());
+ $b->close();
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = new NullStream();
+ $p->attach('a');
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/PumpStreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/PumpStreamTest.php
new file mode 100644
index 0000000..2d20ce9
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/PumpStreamTest.php
@@ -0,0 +1,77 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\LimitStream;
+use GuzzleHttp\Stream\PumpStream;
+use GuzzleHttp\Stream\Stream;
+
+class PumpStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadataAndSize()
+ {
+ $p = new PumpStream(function () {}, [
+ 'metadata' => ['foo' => 'bar'],
+ 'size' => 100
+ ]);
+
+ $this->assertEquals('bar', $p->getMetadata('foo'));
+ $this->assertEquals(['foo' => 'bar'], $p->getMetadata());
+ $this->assertEquals(100, $p->getSize());
+ }
+
+ public function testCanReadFromCallable()
+ {
+ $p = Stream::factory(function ($size) {
+ return 'a';
+ });
+ $this->assertEquals('a', $p->read(1));
+ $this->assertEquals(1, $p->tell());
+ $this->assertEquals('aaaaa', $p->read(5));
+ $this->assertEquals(6, $p->tell());
+ }
+
+ public function testStoresExcessDataInBuffer()
+ {
+ $called = [];
+ $p = Stream::factory(function ($size) use (&$called) {
+ $called[] = $size;
+ return 'abcdef';
+ });
+ $this->assertEquals('a', $p->read(1));
+ $this->assertEquals('b', $p->read(1));
+ $this->assertEquals('cdef', $p->read(4));
+ $this->assertEquals('abcdefabc', $p->read(9));
+ $this->assertEquals([1, 9, 3], $called);
+ }
+
+ public function testInifiniteStreamWrappedInLimitStream()
+ {
+ $p = Stream::factory(function () { return 'a'; });
+ $s = new LimitStream($p, 5);
+ $this->assertEquals('aaaaa', (string) $s);
+ }
+
+ public function testDescribesCapabilities()
+ {
+ $p = Stream::factory(function () {});
+ $this->assertTrue($p->isReadable());
+ $this->assertFalse($p->isSeekable());
+ $this->assertFalse($p->isWritable());
+ $this->assertNull($p->getSize());
+ $this->assertFalse($p->write('aa'));
+ $this->assertEquals('', $p->getContents());
+ $this->assertEquals('', (string) $p);
+ $p->close();
+ $this->assertEquals('', $p->read(10));
+ $this->assertTrue($p->eof());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = Stream::factory(function () {});
+ $p->attach('a');
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php
new file mode 100644
index 0000000..2ba79ad
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php
@@ -0,0 +1,147 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\StreamDecoratorTrait;
+
+class Str implements StreamInterface
+{
+ use StreamDecoratorTrait;
+}
+
+/**
+ * @covers GuzzleHttp\Stream\StreamDecoratorTrait
+ */
+class StreamDecoratorTraitTest extends \PHPUnit_Framework_TestCase
+{
+ private $a;
+ private $b;
+ private $c;
+
+ public function setUp()
+ {
+ $this->c = fopen('php://temp', 'r+');
+ fwrite($this->c, 'foo');
+ fseek($this->c, 0);
+ $this->a = Stream::factory($this->c);
+ $this->b = new Str($this->a);
+ }
+
+ public function testCatchesExceptionsWhenCastingToString()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['read'])
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('read')
+ ->will($this->throwException(new \Exception('foo')));
+ $msg = '';
+ set_error_handler(function ($errNo, $str) use (&$msg) { $msg = $str; });
+ echo new Str($s);
+ restore_error_handler();
+ $this->assertContains('foo', $msg);
+ }
+
+ public function testToString()
+ {
+ $this->assertEquals('foo', (string) $this->b);
+ }
+
+ public function testHasSize()
+ {
+ $this->assertEquals(3, $this->b->getSize());
+ $this->assertSame($this->b, $this->b->setSize(2));
+ $this->assertEquals(2, $this->b->getSize());
+ }
+
+ public function testReads()
+ {
+ $this->assertEquals('foo', $this->b->read(10));
+ }
+
+ public function testCheckMethods()
+ {
+ $this->assertEquals($this->a->isReadable(), $this->b->isReadable());
+ $this->assertEquals($this->a->isWritable(), $this->b->isWritable());
+ $this->assertEquals($this->a->isSeekable(), $this->b->isSeekable());
+ }
+
+ public function testSeeksAndTells()
+ {
+ $this->assertTrue($this->b->seek(1));
+ $this->assertEquals(1, $this->a->tell());
+ $this->assertEquals(1, $this->b->tell());
+ $this->assertTrue($this->b->seek(0));
+ $this->assertEquals(0, $this->a->tell());
+ $this->assertEquals(0, $this->b->tell());
+ $this->assertTrue($this->b->seek(0, SEEK_END));
+ $this->assertEquals(3, $this->a->tell());
+ $this->assertEquals(3, $this->b->tell());
+ }
+
+ public function testGetsContents()
+ {
+ $this->assertEquals('foo', $this->b->getContents());
+ $this->assertEquals('', $this->b->getContents());
+ $this->b->seek(1);
+ $this->assertEquals('oo', $this->b->getContents(1));
+ }
+
+ public function testCloses()
+ {
+ $this->b->close();
+ $this->assertFalse(is_resource($this->c));
+ }
+
+ public function testDetaches()
+ {
+ $this->b->detach();
+ $this->assertFalse($this->b->isReadable());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttachByDefault()
+ {
+ $this->b->attach('a');
+ }
+
+ public function testWrapsMetadata()
+ {
+ $this->assertSame($this->b->getMetadata(), $this->a->getMetadata());
+ $this->assertSame($this->b->getMetadata('uri'), $this->a->getMetadata('uri'));
+ }
+
+ public function testWrapsWrites()
+ {
+ $this->b->seek(0, SEEK_END);
+ $this->b->write('foo');
+ $this->assertEquals('foofoo', (string) $this->a);
+ }
+
+ /**
+ * @expectedException \UnexpectedValueException
+ */
+ public function testThrowsWithInvalidGetter()
+ {
+ $this->b->foo;
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testThrowsWhenGetterNotImplemented()
+ {
+ $s = new BadStream();
+ $s->stream;
+ }
+}
+
+class BadStream
+{
+ use StreamDecoratorTrait;
+
+ public function __construct() {}
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/StreamTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/StreamTest.php
new file mode 100644
index 0000000..2985bfb
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/StreamTest.php
@@ -0,0 +1,252 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+
+/**
+ * @covers GuzzleHttp\Stream\Stream
+ */
+class StreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorThrowsExceptionOnInvalidArgument()
+ {
+ new Stream(true);
+ }
+
+ public function testConstructorInitializesProperties()
+ {
+ $handle = fopen('php://temp', 'r+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertTrue($stream->isReadable());
+ $this->assertTrue($stream->isWritable());
+ $this->assertTrue($stream->isSeekable());
+ $this->assertEquals('php://temp', $stream->getMetadata('uri'));
+ $this->assertInternalType('array', $stream->getMetadata());
+ $this->assertEquals(4, $stream->getSize());
+ $this->assertFalse($stream->eof());
+ $stream->close();
+ }
+
+ public function testStreamClosesHandleOnDestruct()
+ {
+ $handle = fopen('php://temp', 'r');
+ $stream = new Stream($handle);
+ unset($stream);
+ $this->assertFalse(is_resource($handle));
+ }
+
+ public function testConvertsToString()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertEquals('data', (string) $stream);
+ $this->assertEquals('data', (string) $stream);
+ $stream->close();
+ }
+
+ public function testGetsContents()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertEquals('', $stream->getContents());
+ $stream->seek(0);
+ $this->assertEquals('data', $stream->getContents());
+ $this->assertEquals('', $stream->getContents());
+ }
+
+ public function testChecksEof()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertFalse($stream->eof());
+ $stream->read(4);
+ $this->assertTrue($stream->eof());
+ $stream->close();
+ }
+
+ public function testAllowsSettingManualSize()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $stream->setSize(10);
+ $this->assertEquals(10, $stream->getSize());
+ $stream->close();
+ }
+
+ public function testGetSize()
+ {
+ $size = filesize(__FILE__);
+ $handle = fopen(__FILE__, 'r');
+ $stream = new Stream($handle);
+ $this->assertEquals($size, $stream->getSize());
+ // Load from cache
+ $this->assertEquals($size, $stream->getSize());
+ $stream->close();
+ }
+
+ public function testEnsuresSizeIsConsistent()
+ {
+ $h = fopen('php://temp', 'w+');
+ $this->assertEquals(3, fwrite($h, 'foo'));
+ $stream = new Stream($h);
+ $this->assertEquals(3, $stream->getSize());
+ $this->assertEquals(4, $stream->write('test'));
+ $this->assertEquals(7, $stream->getSize());
+ $this->assertEquals(7, $stream->getSize());
+ $stream->close();
+ }
+
+ public function testProvidesStreamPosition()
+ {
+ $handle = fopen('php://temp', 'w+');
+ $stream = new Stream($handle);
+ $this->assertEquals(0, $stream->tell());
+ $stream->write('foo');
+ $this->assertEquals(3, $stream->tell());
+ $stream->seek(1);
+ $this->assertEquals(1, $stream->tell());
+ $this->assertSame(ftell($handle), $stream->tell());
+ $stream->close();
+ }
+
+ public function testKeepsPositionOfResource()
+ {
+ $h = fopen(__FILE__, 'r');
+ fseek($h, 10);
+ $stream = Stream::factory($h);
+ $this->assertEquals(10, $stream->tell());
+ $stream->close();
+ }
+
+ public function testCanDetachAndAttachStream()
+ {
+ $r = fopen('php://temp', 'w+');
+ $stream = new Stream($r);
+ $stream->write('foo');
+ $this->assertTrue($stream->isReadable());
+ $this->assertSame($r, $stream->detach());
+ $this->assertNull($stream->detach());
+
+ $this->assertFalse($stream->isReadable());
+ $this->assertFalse($stream->read(10));
+ $this->assertFalse($stream->isWritable());
+ $this->assertFalse($stream->write('bar'));
+ $this->assertFalse($stream->isSeekable());
+ $this->assertFalse($stream->seek(10));
+ $this->assertFalse($stream->tell());
+ $this->assertTrue($stream->eof());
+ $this->assertNull($stream->getSize());
+ $this->assertSame('', (string) $stream);
+ $this->assertSame('', $stream->getContents());
+
+ $stream->attach($r);
+ $stream->seek(0);
+ $this->assertEquals('foo', $stream->getContents());
+ $this->assertTrue($stream->isReadable());
+ $this->assertTrue($stream->isWritable());
+ $this->assertTrue($stream->isSeekable());
+
+ $stream->close();
+ }
+
+ public function testCloseClearProperties()
+ {
+ $handle = fopen('php://temp', 'r+');
+ $stream = new Stream($handle);
+ $stream->close();
+
+ $this->assertEmpty($stream->getMetadata());
+ $this->assertFalse($stream->isSeekable());
+ $this->assertFalse($stream->isReadable());
+ $this->assertFalse($stream->isWritable());
+ $this->assertNull($stream->getSize());
+ }
+
+ public function testCreatesWithFactory()
+ {
+ $stream = Stream::factory('foo');
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $stream);
+ $this->assertEquals('foo', $stream->getContents());
+ $stream->close();
+ }
+
+ public function testFactoryCreatesFromEmptyString()
+ {
+ $s = Stream::factory();
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
+ }
+
+ public function testFactoryCreatesFromResource()
+ {
+ $r = fopen(__FILE__, 'r');
+ $s = Stream::factory($r);
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
+ $this->assertSame(file_get_contents(__FILE__), (string) $s);
+ }
+
+ public function testFactoryCreatesFromObjectWithToString()
+ {
+ $r = new HasToString();
+ $s = Stream::factory($r);
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
+ $this->assertEquals('foo', (string) $s);
+ }
+
+ public function testCreatePassesThrough()
+ {
+ $s = Stream::factory('foo');
+ $this->assertSame($s, Stream::factory($s));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testThrowsExceptionForUnknown()
+ {
+ Stream::factory(new \stdClass());
+ }
+
+ public function testReturnsCustomMetadata()
+ {
+ $s = Stream::factory('foo', ['metadata' => ['hwm' => 3]]);
+ $this->assertEquals(3, $s->getMetadata('hwm'));
+ $this->assertArrayHasKey('hwm', $s->getMetadata());
+ }
+
+ public function testCanSetSize()
+ {
+ $s = Stream::factory('', ['size' => 10]);
+ $this->assertEquals(10, $s->getSize());
+ }
+
+ public function testCanCreateIteratorBasedStream()
+ {
+ $a = new \ArrayIterator(['foo', 'bar', '123']);
+ $p = Stream::factory($a);
+ $this->assertInstanceOf('GuzzleHttp\Stream\PumpStream', $p);
+ $this->assertEquals('foo', $p->read(3));
+ $this->assertFalse($p->eof());
+ $this->assertEquals('b', $p->read(1));
+ $this->assertEquals('a', $p->read(1));
+ $this->assertEquals('r12', $p->read(3));
+ $this->assertFalse($p->eof());
+ $this->assertEquals('3', $p->getContents());
+ $this->assertTrue($p->eof());
+ $this->assertEquals(9, $p->tell());
+ }
+}
+
+class HasToString
+{
+ public function __toString() {
+ return 'foo';
+ }
+}
diff --git a/public/system/storage/vendor/guzzlehttp/streams/tests/UtilsTest.php b/public/system/storage/vendor/guzzlehttp/streams/tests/UtilsTest.php
new file mode 100644
index 0000000..6e3e3b2
--- /dev/null
+++ b/public/system/storage/vendor/guzzlehttp/streams/tests/UtilsTest.php
@@ -0,0 +1,155 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\NoSeekStream;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\Utils;
+
+class UtilsTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCopiesToString()
+ {
+ $s = Stream::factory('foobaz');
+ $this->assertEquals('foobaz', Utils::copyToString($s));
+ $s->seek(0);
+ $this->assertEquals('foo', Utils::copyToString($s, 3));
+ $this->assertEquals('baz', Utils::copyToString($s, 3));
+ $this->assertEquals('', Utils::copyToString($s));
+ }
+
+ public function testCopiesToStringStopsWhenReadFails()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s1 = FnStream::decorate($s1, [
+ 'read' => function () {
+ return false;
+ }
+ ]);
+ $result = Utils::copyToString($s1);
+ $this->assertEquals('', $result);
+ }
+
+ public function testCopiesToStream()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s2 = Stream::factory('');
+ Utils::copyToStream($s1, $s2);
+ $this->assertEquals('foobaz', (string) $s2);
+ $s2 = Stream::factory('');
+ $s1->seek(0);
+ Utils::copyToStream($s1, $s2, 3);
+ $this->assertEquals('foo', (string) $s2);
+ Utils::copyToStream($s1, $s2, 3);
+ $this->assertEquals('foobaz', (string) $s2);
+ }
+
+ public function testStopsCopyToStreamWhenWriteFails()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s2 = Stream::factory('');
+ $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
+ Utils::copyToStream($s1, $s2);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testStopsCopyToSteamWhenWriteFailsWithMaxLen()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s2 = Stream::factory('');
+ $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
+ Utils::copyToStream($s1, $s2, 10);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testStopsCopyToSteamWhenReadFailsWithMaxLen()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s1 = FnStream::decorate($s1, ['read' => function () { return ''; }]);
+ $s2 = Stream::factory('');
+ Utils::copyToStream($s1, $s2, 10);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testReadsLines()
+ {
+ $s = Stream::factory("foo\nbaz\nbar");
+ $this->assertEquals("foo\n", Utils::readline($s));
+ $this->assertEquals("baz\n", Utils::readline($s));
+ $this->assertEquals("bar", Utils::readline($s));
+ }
+
+ public function testReadsLinesUpToMaxLength()
+ {
+ $s = Stream::factory("12345\n");
+ $this->assertEquals("123", Utils::readline($s, 4));
+ $this->assertEquals("45\n", Utils::readline($s));
+ }
+
+ public function testReadsLineUntilFalseReturnedFromRead()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\Stream')
+ ->setMethods(['read', 'eof'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $s->expects($this->exactly(2))
+ ->method('read')
+ ->will($this->returnCallback(function () {
+ static $c = false;
+ if ($c) {
+ return false;
+ }
+ $c = true;
+ return 'h';
+ }));
+ $s->expects($this->exactly(2))
+ ->method('eof')
+ ->will($this->returnValue(false));
+ $this->assertEquals("h", Utils::readline($s));
+ }
+
+ public function testCalculatesHash()
+ {
+ $s = Stream::factory('foobazbar');
+ $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\SeekException
+ */
+ public function testCalculatesHashThrowsWhenSeekFails()
+ {
+ $s = new NoSeekStream(Stream::factory('foobazbar'));
+ $s->read(2);
+ Utils::hash($s, 'md5');
+ }
+
+ public function testCalculatesHashSeeksToOriginalPosition()
+ {
+ $s = Stream::factory('foobazbar');
+ $s->seek(4);
+ $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
+ $this->assertEquals(4, $s->tell());
+ }
+
+ public function testOpensFilesSuccessfully()
+ {
+ $r = Utils::open(__FILE__, 'r');
+ $this->assertInternalType('resource', $r);
+ fclose($r);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Unable to open /path/to/does/not/exist using mode r
+ */
+ public function testThrowsExceptionNotWarning()
+ {
+ Utils::open('/path/to/does/not/exist', 'r');
+ }
+
+ public function testProxiesToFactory()
+ {
+ $this->assertEquals('foo', (string) Utils::create('foo'));
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/.coveralls.yml b/public/system/storage/vendor/klarna/kco_rest/.coveralls.yml
new file mode 100644
index 0000000..09bbb25
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/.coveralls.yml
@@ -0,0 +1,3 @@
+src_dir: src
+coverage_clover: build/logs/clover.xml
+json_path: build/logs/coveralls-upload.json
diff --git a/public/system/storage/vendor/klarna/kco_rest/.gitignore b/public/system/storage/vendor/klarna/kco_rest/.gitignore
new file mode 100644
index 0000000..b529433
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/.gitignore
@@ -0,0 +1,3 @@
+/vendor/
+/build/
+/docs/reference
diff --git a/public/system/storage/vendor/klarna/kco_rest/.travis.yml b/public/system/storage/vendor/klarna/kco_rest/.travis.yml
new file mode 100644
index 0000000..5932d30
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/.travis.yml
@@ -0,0 +1,29 @@
+language: php
+php:
+ - 7.0
+ - 5.6
+ - 5.5
+ - 5.4
+ - hhvm
+
+matrix:
+ allow_failures:
+ - php: 7.0
+
+branches:
+ only:
+ - /^v\d\.\d/
+cache:
+ directories:
+ - vendor
+
+before_script:
+ - composer install --no-interaction
+
+script:
+ - composer run test
+
+after_script:
+ - php vendor/bin/coveralls -v
+
+sudo: false
diff --git a/public/system/storage/vendor/klarna/kco_rest/CHANGELOG.md b/public/system/storage/vendor/klarna/kco_rest/CHANGELOG.md
new file mode 100644
index 0000000..42ca1f2
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/CHANGELOG.md
@@ -0,0 +1,17 @@
+## v2.2.0 - 2015-12-7
+- **NEW META-13** Allow for 201 response on refund - *Joakim.L*
+
+## v2.1.0 - 2015-07-29
+- **NEW MINT-2262** Support Guzzle 5.x versions - *Omer.K, Joakim.L*
+
+## v2.0.0 - 2015-06-10
+- **NEW MINT-2203** Use order id instead of URL for checkout orders - *Joakim.L*
+- **NEW MINT-2214** Add base URLs for North America - *Joakim.L*
+
+## v1.0.1 - 2015-03-30
+- **FIX MINT-2002** Handle errors with an empty payload - *David.K*
+- **NEW MINT-2097** Add apigen and custom styling - *Petros.G*
+
+## v1.0.0 - 2014-10-16
+- **NEW MINT-1804** Support checkout v3 and ordermanagement v1 APIs - *Joakim.L*
+
diff --git a/public/system/storage/vendor/klarna/kco_rest/README.md b/public/system/storage/vendor/klarna/kco_rest/README.md
new file mode 100644
index 0000000..537f4c9
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/README.md
@@ -0,0 +1,67 @@
+# Klarna Checkout REST PHP SDK
+[![Packagist Version][packagist-image]](https://packagist.org/packages/klarna/kco_rest)
+[![Build Status][travis-image]](https://travis-ci.org/klarna/kco_rest_php)
+[![Coverage Status][coveralls-image]](https://coveralls.io/r/klarna/kco_rest_php?branch=v2.2)
+
+Klarna Checkout is a revolutionary new payment solution that is changing the way
+people shop online. First, consumers verify their purchase with a minimal
+amount of information through intelligent identification, securing your order
+immediately, and then complete their payment afterwards – separating buying
+from paying and dramatically increasing conversion. Klarna Checkout also allows
+merchants to offer all payment methods through one supplier, minimizing
+administration, costs and integration time.
+
+
+## Get started
+
+### Prerequisites
+* PHP 5.4 or above
+* API credentials
+
+
+### Usage
+Example files can be found in the [docs/](docs/) directory.
+
+
+## Documentation
+Additional documentation can be found at https://developers.klarna.com.
+
+
+## Questions and feedback
+If you have any questions concerning this product or the implementation,
+please contact [integration@klarna.com](mailto:integration@klarna.com).
+
+
+## How to contribute
+At Klarna, we strive toward achieving the highest possible quality for our
+products. Therefore, we require you to follow these guidelines if you wish
+to contribute.
+
+To contribute, the following criteria needs to be fulfilled:
+
+* Description regarding what has been changed and why
+* Pull requests should implement a boxed change
+* All code and documentation must follow the [PSR-2 standard](http://www.php-fig.org/psr/psr-2/)
+* New features and bug fixes must have accompanying unit tests:
+ * Positive tests
+ * Negative tests
+ * Boundary tests (if possible)
+ * No less than 90% decision coverage
+* All tests should pass
+
+
+## Acknowledgements
+* Christer Gustavsson ([@ChristerGustavsson](https://github.com/ChristerGustavsson))
+* David Keijser ([@keis](https://github.com/keis))
+* Joakim Löfgren ([@JoakimLofgren](https://github.com/JoakimLofgren))
+* Majid Garmaroudi ([@dijam](https://github.com/dijam))
+* Omer Karadagli ([@ockcyp](https://github.com/ockcyp))
+
+
+## License
+Klarna Checkout REST PHP SDK is licensed under
+[Apache License, Version 2.0](http://www.apache.org/LICENSE-2.0)
+
+[packagist-image]: https://img.shields.io/packagist/v/klarna/kco_rest.svg?style=flat
+[travis-image]: https://img.shields.io/travis/klarna/kco_rest_php/v2.2.svg?style=flat
+[coveralls-image]: https://img.shields.io/coveralls/klarna/kco_rest_php/v2.2.svg?style=flat
diff --git a/public/system/storage/vendor/klarna/kco_rest/composer.json b/public/system/storage/vendor/klarna/kco_rest/composer.json
new file mode 100644
index 0000000..d34e36b
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/composer.json
@@ -0,0 +1,46 @@
+{
+ "name": "klarna/kco_rest",
+ "description": "Klarna Checkout PHP SDK",
+ "homepage": "http://developers.klarna.com",
+ "license": "Apache-2.0",
+ "type": "library",
+ "authors": [
+ {
+ "name": "Klarna AB",
+ "email": "integration@klarna.com"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "": "src/"
+ }
+ },
+ "minimum-stability": "stable",
+ "require": {
+ "php": ">=5.4.0",
+ "guzzlehttp/guzzle": ">=4.2,<6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.2.*",
+ "squizlabs/php_codesniffer": "1.5.*",
+ "phpmd/phpmd": "2.1.*",
+ "phploc/phploc": "2.0.*",
+ "sebastian/phpcpd": "2.0.*",
+ "satooshi/php-coveralls": "0.6.*",
+ "apigen/apigen": "4.0.*",
+ "klarna/apigen-theme": "~1.0"
+ },
+ "scripts": {
+ "test": "vendor/bin/phpunit --colors",
+ "reference": "vendor/bin/apigen generate -s src -d docs/reference --template-config='vendor/klarna/apigen-theme/src/config.neon'",
+ "analyze": [
+ "mkdir -p build/logs",
+ "vendor/bin/phploc --log-csv build/logs/phploc.csv src/ tests/",
+ "mkdir -p build/pdepend",
+ "vendor/bin/pdepend --jdepend-xml=build/logs/jdepend.xml --jdepend-chart=build/pdepend/dependencies.svg --overview-pyramid=build/pdepend/overview-pyramid.svg src/",
+ "vendor/bin/phpmd src/,tests/ xml phpmd.xml --reportfile build/logs/pmd.xml || true",
+ "vendor/bin/phpcs --standard=PSR2 --report=checkstyle --report-file=build/logs/checkstyle.xml --extensions=php src/ tests/",
+ "vendor/bin/phpcpd --log-pmd build/logs/pmd-cpd.xml src/ tests/ || true"
+ ]
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/composer.lock b/public/system/storage/vendor/klarna/kco_rest/composer.lock
new file mode 100644
index 0000000..f6bb9a8
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/composer.lock
@@ -0,0 +1,3569 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "faa4d6f172d4f9991cf2583e57f9b43c",
+ "packages": [
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "5.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "f3c8c22471cb55475105c14769644a49c3262b93"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93",
+ "reference": "f3c8c22471cb55475105c14769644a49c3262b93",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/ringphp": "^1.1",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.0",
+ "psr/log": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2015-05-20 03:47:55"
+ },
+ {
+ "name": "guzzlehttp/ringphp",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/RingPHP.git",
+ "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
+ "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/streams": "~3.0",
+ "php": ">=5.4.0",
+ "react/promise": "~2.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0"
+ },
+ "suggest": {
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Ring\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
+ "time": "2015-05-20 03:37:09"
+ },
+ {
+ "name": "guzzlehttp/streams",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/streams.git",
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
+ "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Stream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Provides a simple abstraction over streams of data",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "Guzzle",
+ "stream"
+ ],
+ "time": "2014-10-12 19:18:40"
+ },
+ {
+ "name": "react/promise",
+ "version": "v2.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/promise.git",
+ "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627",
+ "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com"
+ }
+ ],
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "time": "2015-07-03 13:48:55"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "andrewsville/php-token-reflection",
+ "version": "1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Andrewsville/PHP-Token-Reflection.git",
+ "reference": "e6d0ac2baf66cdf154be34c3d2a2aa1bd4b426ee"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Andrewsville/PHP-Token-Reflection/zipball/e6d0ac2baf66cdf154be34c3d2a2aa1bd4b426ee",
+ "reference": "e6d0ac2baf66cdf154be34c3d2a2aa1bd4b426ee",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "TokenReflection": "./"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3"
+ ],
+ "authors": [
+ {
+ "name": "Ondřej Nešpor",
+ "homepage": "https://github.com/andrewsville"
+ },
+ {
+ "name": "Jaroslav Hanslík",
+ "homepage": "https://github.com/kukulich"
+ }
+ ],
+ "description": "Library emulating the PHP internal reflection using just the tokenized source code.",
+ "homepage": "http://andrewsville.github.com/PHP-Token-Reflection/",
+ "keywords": [
+ "library",
+ "reflection",
+ "tokenizer"
+ ],
+ "time": "2014-08-06 16:37:08"
+ },
+ {
+ "name": "apigen/apigen",
+ "version": "v4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ApiGen/ApiGen.git",
+ "reference": "b719a6ad49107b5bc0bdf9fc8fae219a9a6dd5f1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ApiGen/ApiGen/zipball/b719a6ad49107b5bc0bdf9fc8fae219a9a6dd5f1",
+ "reference": "b719a6ad49107b5bc0bdf9fc8fae219a9a6dd5f1",
+ "shasum": ""
+ },
+ "require": {
+ "andrewsville/php-token-reflection": "~1.4",
+ "herrera-io/phar-update": "~2.0",
+ "kdyby/events": "~2.0",
+ "kukulich/fshl": "~2.1",
+ "latte/latte": "~2.2",
+ "michelf/php-markdown": "~1.4",
+ "nette/application": "~2.2",
+ "nette/bootstrap": "~2.2",
+ "nette/di": "~2.2",
+ "nette/mail": "~2.2",
+ "nette/neon": "~2.2",
+ "nette/robot-loader": "~2.2",
+ "nette/safe-stream": "~2.2",
+ "php": ">=5.4",
+ "symfony/console": "~2.6",
+ "symfony/options-resolver": "~2.6.1",
+ "tracy/tracy": "~2.2"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "~0.8",
+ "mockery/mockery": "~0.9",
+ "phpunit/phpunit": "~4.4",
+ "zenify/coding-standard": "~3.0"
+ },
+ "bin": [
+ "bin/apigen"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "ApiGen\\": "src/ApiGen"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Ondřej Nešpor",
+ "homepage": "https://github.com/andrewsville"
+ },
+ {
+ "name": "Jaroslav Hanslík",
+ "homepage": "https://github.com/kukulich"
+ },
+ {
+ "name": "Tomáš Votruba",
+ "email": "tomas.vot@gmail.com"
+ },
+ {
+ "name": "Olivier Laviale",
+ "homepage": "https://github.com/olvlvl"
+ }
+ ],
+ "description": "PHP source code API generator",
+ "homepage": "http://apigen.org/",
+ "keywords": [
+ "api",
+ "documentation",
+ "generator",
+ "phpdoc"
+ ],
+ "time": "2015-03-09 11:03:45"
+ },
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3,<8.0-DEV"
+ },
+ "require-dev": {
+ "athletic/athletic": "~0.1.8",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://github.com/doctrine/instantiator",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2015-06-14 21:17:01"
+ },
+ {
+ "name": "guzzle/guzzle",
+ "version": "v3.9.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle3.git",
+ "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
+ "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.3.3",
+ "symfony/event-dispatcher": "~2.1"
+ },
+ "replace": {
+ "guzzle/batch": "self.version",
+ "guzzle/cache": "self.version",
+ "guzzle/common": "self.version",
+ "guzzle/http": "self.version",
+ "guzzle/inflection": "self.version",
+ "guzzle/iterator": "self.version",
+ "guzzle/log": "self.version",
+ "guzzle/parser": "self.version",
+ "guzzle/plugin": "self.version",
+ "guzzle/plugin-async": "self.version",
+ "guzzle/plugin-backoff": "self.version",
+ "guzzle/plugin-cache": "self.version",
+ "guzzle/plugin-cookie": "self.version",
+ "guzzle/plugin-curlauth": "self.version",
+ "guzzle/plugin-error-response": "self.version",
+ "guzzle/plugin-history": "self.version",
+ "guzzle/plugin-log": "self.version",
+ "guzzle/plugin-md5": "self.version",
+ "guzzle/plugin-mock": "self.version",
+ "guzzle/plugin-oauth": "self.version",
+ "guzzle/service": "self.version",
+ "guzzle/stream": "self.version"
+ },
+ "require-dev": {
+ "doctrine/cache": "~1.3",
+ "monolog/monolog": "~1.0",
+ "phpunit/phpunit": "3.7.*",
+ "psr/log": "~1.0",
+ "symfony/class-loader": "~2.1",
+ "zendframework/zend-cache": "2.*,<2.3",
+ "zendframework/zend-log": "2.*,<2.3"
+ },
+ "suggest": {
+ "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.9-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Guzzle": "src/",
+ "Guzzle\\Tests": "tests/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Guzzle Community",
+ "homepage": "https://github.com/guzzle/guzzle/contributors"
+ }
+ ],
+ "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2015-03-18 18:23:50"
+ },
+ {
+ "name": "herrera-io/json",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/kherge-abandoned/php-json.git",
+ "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1",
+ "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "justinrainbow/json-schema": ">=1.0,<2.0-dev",
+ "php": ">=5.3.3",
+ "seld/jsonlint": ">=1.0,<2.0-dev"
+ },
+ "require-dev": {
+ "herrera-io/phpunit-test-case": "1.*",
+ "mikey179/vfsstream": "1.1.0",
+ "phpunit/phpunit": "3.7.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/lib/json_version.php"
+ ],
+ "psr-0": {
+ "Herrera\\Json": "src/lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kevin Herrera",
+ "email": "kevin@herrera.io",
+ "homepage": "http://kevin.herrera.io"
+ }
+ ],
+ "description": "A library for simplifying JSON linting and validation.",
+ "homepage": "http://herrera-io.github.com/php-json",
+ "keywords": [
+ "json",
+ "lint",
+ "schema",
+ "validate"
+ ],
+ "time": "2013-10-30 16:51:34"
+ },
+ {
+ "name": "herrera-io/phar-update",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/kherge-abandoned/php-phar-update.git",
+ "reference": "15643c90d3d43620a4f45c910e6afb7a0ad4b488"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/kherge-abandoned/php-phar-update/zipball/15643c90d3d43620a4f45c910e6afb7a0ad4b488",
+ "reference": "15643c90d3d43620a4f45c910e6afb7a0ad4b488",
+ "shasum": ""
+ },
+ "require": {
+ "herrera-io/json": "1.*",
+ "herrera-io/version": "1.*",
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "herrera-io/phpunit-test-case": "1.*",
+ "mikey179/vfsstream": "1.1.0",
+ "phpunit/phpunit": "3.7.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/lib/constants.php"
+ ],
+ "psr-0": {
+ "Herrera\\Phar\\Update": "src/lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kevin Herrera",
+ "email": "kevin@herrera.io",
+ "homepage": "http://kevin.herrera.io"
+ }
+ ],
+ "description": "A library for self-updating Phars.",
+ "homepage": "http://herrera-io.github.com/php-phar-update",
+ "keywords": [
+ "phar",
+ "update"
+ ],
+ "time": "2013-11-09 17:13:13"
+ },
+ {
+ "name": "herrera-io/version",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/kherge-abandoned/php-version.git",
+ "reference": "d39d9642b92a04d8b8a28b871b797a35a2545e85"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/kherge-abandoned/php-version/zipball/d39d9642b92a04d8b8a28b871b797a35a2545e85",
+ "reference": "d39d9642b92a04d8b8a28b871b797a35a2545e85",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "herrera-io/phpunit-test-case": "1.*",
+ "phpunit/phpunit": "3.7.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Herrera\\Version": "src/lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kevin Herrera",
+ "email": "kevin@herrera.io",
+ "homepage": "http://kevin.herrera.io"
+ }
+ ],
+ "description": "A library for creating, editing, and comparing semantic versioning numbers.",
+ "homepage": "http://github.com/herrera-io/php-version",
+ "keywords": [
+ "semantic",
+ "version"
+ ],
+ "time": "2014-05-27 05:29:25"
+ },
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "1.4.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/justinrainbow/json-schema.git",
+ "reference": "8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce",
+ "reference": "8dc9b9d85ab639ca60ab4608b34c1279d6ae7bce",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "json-schema/json-schema-test-suite": "1.1.0",
+ "phpdocumentor/phpdocumentor": "~2",
+ "phpunit/phpunit": "~3.7"
+ },
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "JsonSchema": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/justinrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ],
+ "time": "2015-07-14 16:29:50"
+ },
+ {
+ "name": "kdyby/events",
+ "version": "v2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Kdyby/Events.git",
+ "reference": "8049e0fc7abb48178b4a2a9af230eceebe1a83bc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Kdyby/Events/zipball/8049e0fc7abb48178b4a2a9af230eceebe1a83bc",
+ "reference": "8049e0fc7abb48178b4a2a9af230eceebe1a83bc",
+ "shasum": ""
+ },
+ "require": {
+ "nette/di": "~2.3@dev",
+ "nette/utils": "~2.3@dev"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "~0.7",
+ "latte/latte": "~2.3@dev",
+ "nette/application": "~2.3@dev",
+ "nette/bootstrap": "~2.3@dev",
+ "nette/caching": "~2.3@dev",
+ "nette/component-model": "~2.2@dev",
+ "nette/database": "~2.3@dev",
+ "nette/deprecated": "~2.3@dev",
+ "nette/di": "~2.3@dev",
+ "nette/finder": "~2.3@dev",
+ "nette/forms": "~2.3@dev",
+ "nette/http": "~2.3@dev",
+ "nette/mail": "~2.3@dev",
+ "nette/neon": "~2.3@dev",
+ "nette/nette": "~2.3@dev",
+ "nette/php-generator": "~2.3@dev",
+ "nette/reflection": "~2.3@dev",
+ "nette/robot-loader": "~2.3@dev",
+ "nette/safe-stream": "~2.3@dev",
+ "nette/security": "~2.3@dev",
+ "nette/tester": "~1.4@rc",
+ "nette/tokenizer": "~2.2@dev",
+ "nette/utils": "~2.3@dev",
+ "symfony/event-dispatcher": "~2.5",
+ "tracy/tracy": "~2.3@dev"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Kdyby\\Events\\": "src/"
+ },
+ "classmap": [
+ "src/Kdyby/Events/exceptions.php"
+ ],
+ "files": [
+ "src/Doctrine/compatibility.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Filip Procházka",
+ "email": "filip@prochazka.su",
+ "homepage": "http://filip-prochazka.com"
+ }
+ ],
+ "description": "Events for Nette Framework",
+ "homepage": "http://kdyby.org",
+ "keywords": [
+ "kdyby",
+ "nette"
+ ],
+ "time": "2015-04-04 16:29:31"
+ },
+ {
+ "name": "klarna/apigen-theme",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/klarna/klarna-apigen-theme.git",
+ "reference": "1ffcd0e4ea5620d50dbfb74639e4aa4113924911"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/klarna/klarna-apigen-theme/zipball/1ffcd0e4ea5620d50dbfb74639e4aa4113924911",
+ "reference": "1ffcd0e4ea5620d50dbfb74639e4aa4113924911",
+ "shasum": ""
+ },
+ "require": {
+ "latte/latte": "~2.2"
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Tomáš Votruba",
+ "email": "tomas.vot@gmail.com"
+ },
+ {
+ "name": "Olivier Laviale",
+ "homepage": "https://github.com/olvlvl"
+ },
+ {
+ "name": "David Keijser",
+ "email": "david.keijser@klarna.com"
+ },
+ {
+ "name": "Petros Gkourasas",
+ "email": "petros.gkourasas@klarna.com"
+ }
+ ],
+ "description": "Klarna theme for ApiGen",
+ "homepage": "http://klarna.com/",
+ "time": "2015-03-30 15:27:12"
+ },
+ {
+ "name": "kukulich/fshl",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/kukulich/fshl.git",
+ "reference": "974c294ade5d76c0c16b6fe3fd3a584ba999b24f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/kukulich/fshl/zipball/974c294ade5d76c0c16b6fe3fd3a584ba999b24f",
+ "reference": "974c294ade5d76c0c16b6fe3fd3a584ba999b24f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "FSHL": "./"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Jaroslav Hanslík",
+ "homepage": "https://github.com/kukulich"
+ }
+ ],
+ "description": "FSHL is a free, open source, universal, fast syntax highlighter written in PHP.",
+ "homepage": "http://fshl.kukulich.cz/",
+ "keywords": [
+ "highlight",
+ "library",
+ "syntax"
+ ],
+ "time": "2012-09-08 19:00:07"
+ },
+ {
+ "name": "latte/latte",
+ "version": "v2.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/latte.git",
+ "reference": "025883a04b3a5ca48995246e8d82e6ff323d941e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/latte/zipball/025883a04b3a5ca48995246e8d82e6ff323d941e",
+ "reference": "025883a04b3a5ca48995246e8d82e6ff323d941e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.3.1"
+ },
+ "require-dev": {
+ "nette/tester": "~1.3"
+ },
+ "suggest": {
+ "ext-fileinfo": "to use filter |datastream",
+ "ext-mbstring": "to use filters like lower, upper, capitalize, ..."
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Latte: the amazing template engine for PHP",
+ "homepage": "http://latte.nette.org",
+ "keywords": [
+ "templating",
+ "twig"
+ ],
+ "time": "2015-07-03 13:37:59"
+ },
+ {
+ "name": "michelf/php-markdown",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/michelf/php-markdown.git",
+ "reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/e1aabe18173231ebcefc90e615565742fc1c7fd9",
+ "reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-lib": "1.4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Michelf": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "John Gruber",
+ "homepage": "http://daringfireball.net/"
+ },
+ {
+ "name": "Michel Fortin",
+ "email": "michel.fortin@michelf.ca",
+ "homepage": "https://michelf.ca/",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Markdown",
+ "homepage": "https://michelf.ca/projects/php-markdown/",
+ "keywords": [
+ "markdown"
+ ],
+ "time": "2015-03-01 12:03:08"
+ },
+ {
+ "name": "nette/application",
+ "version": "v2.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/application.git",
+ "reference": "785801e441ef83fa4d75cc47c292afedee9b3e4e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/application/zipball/785801e441ef83fa4d75cc47c292afedee9b3e4e",
+ "reference": "785801e441ef83fa4d75cc47c292afedee9b3e4e",
+ "shasum": ""
+ },
+ "require": {
+ "nette/component-model": "~2.2",
+ "nette/http": "~2.2",
+ "nette/reflection": "~2.2",
+ "nette/security": "~2.2",
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "latte/latte": "~2.3.0",
+ "nette/di": "~2.3",
+ "nette/forms": "~2.2",
+ "nette/robot-loader": "~2.2",
+ "nette/tester": "~1.3"
+ },
+ "suggest": {
+ "latte/latte": "Allows using Latte in templates",
+ "nette/forms": "Allows to use Nette\\Application\\UI\\Form"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Application MVC Component",
+ "homepage": "http://nette.org",
+ "time": "2015-07-01 15:54:47"
+ },
+ {
+ "name": "nette/bootstrap",
+ "version": "v2.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/bootstrap.git",
+ "reference": "8e2db45c39a1fa24f88e94c7b2a62ad09e9a306e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/bootstrap/zipball/8e2db45c39a1fa24f88e94c7b2a62ad09e9a306e",
+ "reference": "8e2db45c39a1fa24f88e94c7b2a62ad09e9a306e",
+ "shasum": ""
+ },
+ "require": {
+ "nette/di": "~2.3",
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "latte/latte": "~2.2",
+ "nette/application": "~2.3",
+ "nette/caching": "~2.3",
+ "nette/database": "~2.3",
+ "nette/forms": "~2.3",
+ "nette/http": "~2.3",
+ "nette/mail": "~2.3",
+ "nette/robot-loader": "~2.2",
+ "nette/safe-stream": "~2.2",
+ "nette/security": "~2.3",
+ "nette/tester": "~1.3",
+ "tracy/tracy": "~2.3"
+ },
+ "suggest": {
+ "nette/robot-loader": "to use Configurator::createRobotLoader()",
+ "tracy/tracy": "to use Configurator::enableDebugger()"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Bootstrap",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:07:11"
+ },
+ {
+ "name": "nette/caching",
+ "version": "v2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/caching.git",
+ "reference": "1523a0d2596193dd792045a07e89795eeef435db"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/caching/zipball/1523a0d2596193dd792045a07e89795eeef435db",
+ "reference": "1523a0d2596193dd792045a07e89795eeef435db",
+ "shasum": ""
+ },
+ "require": {
+ "nette/finder": "~2.2",
+ "nette/utils": "~2.2",
+ "php": ">=5.4.4"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "latte/latte": "~2.4",
+ "nette/di": "~2.3",
+ "nette/tester": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Caching Component",
+ "homepage": "http://nette.org",
+ "time": "2015-06-15 16:32:59"
+ },
+ {
+ "name": "nette/component-model",
+ "version": "v2.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/component-model.git",
+ "reference": "fe13e630a307ef4585b3573eae0a161dc1c3d428"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/component-model/zipball/fe13e630a307ef4585b3573eae0a161dc1c3d428",
+ "reference": "fe13e630a307ef4585b3573eae0a161dc1c3d428",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Component Model",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:11:20"
+ },
+ {
+ "name": "nette/di",
+ "version": "v2.3.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/di.git",
+ "reference": "c3e726f8bef49033ba78efe19e999e5fac63f433"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/di/zipball/c3e726f8bef49033ba78efe19e999e5fac63f433",
+ "reference": "c3e726f8bef49033ba78efe19e999e5fac63f433",
+ "shasum": ""
+ },
+ "require": {
+ "nette/neon": "~2.3",
+ "nette/php-generator": "~2.3",
+ "nette/utils": "~2.3",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Dependency Injection Component",
+ "homepage": "http://nette.org",
+ "time": "2015-07-13 22:28:49"
+ },
+ {
+ "name": "nette/finder",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/finder.git",
+ "reference": "38f803a03f4cddf352e28af70294c71f7026e516"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/finder/zipball/38f803a03f4cddf352e28af70294c71f7026e516",
+ "reference": "38f803a03f4cddf352e28af70294c71f7026e516",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.4"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Finder: Files Searching",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:13:50"
+ },
+ {
+ "name": "nette/http",
+ "version": "v2.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/http.git",
+ "reference": "ff2e4608391bca2444df9af6eaf8666ac853eb02"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/http/zipball/ff2e4608391bca2444df9af6eaf8666ac853eb02",
+ "reference": "ff2e4608391bca2444df9af6eaf8666ac853eb02",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "~2.2, >=2.2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/di": "~2.3",
+ "nette/tester": "~1.4"
+ },
+ "suggest": {
+ "ext-fileinfo": "to detect type of uploaded files"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette HTTP Component",
+ "homepage": "http://nette.org",
+ "time": "2015-07-19 16:17:50"
+ },
+ {
+ "name": "nette/mail",
+ "version": "v2.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/mail.git",
+ "reference": "2c6c64787edf8131ec5e1b514ecc4a80a6477f80"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/mail/zipball/2c6c64787edf8131ec5e1b514ecc4a80a6477f80",
+ "reference": "2c6c64787edf8131ec5e1b514ecc4a80a6477f80",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/di": "~2.3",
+ "nette/tester": "~1.3"
+ },
+ "suggest": {
+ "ext-fileinfo": "to detect type of attached files"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Mail: Sending E-mails",
+ "homepage": "http://nette.org",
+ "time": "2015-07-03 13:31:38"
+ },
+ {
+ "name": "nette/neon",
+ "version": "v2.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/neon.git",
+ "reference": "48b25e0962d70e9125797e67a144f3e057243d9d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/neon/zipball/48b25e0962d70e9125797e67a144f3e057243d9d",
+ "reference": "48b25e0962d70e9125797e67a144f3e057243d9d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "php": ">=5.3.1"
+ },
+ "require-dev": {
+ "nette/tester": "~1.4"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette NEON: parser & generator for Nette Object Notation",
+ "homepage": "http://ne-on.org",
+ "time": "2015-07-13 22:29:08"
+ },
+ {
+ "name": "nette/php-generator",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/php-generator.git",
+ "reference": "c47ad59b972e8a5f4bb00299951bd8053a8fc074"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/php-generator/zipball/c47ad59b972e8a5f4bb00299951bd8053a8fc074",
+ "reference": "c47ad59b972e8a5f4bb00299951bd8053a8fc074",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.4"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette PHP Generator",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:19:33"
+ },
+ {
+ "name": "nette/reflection",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/reflection.git",
+ "reference": "9c2ed2a29f1f58125a0f19ffc987812d6b17d3e6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/reflection/zipball/9c2ed2a29f1f58125a0f19ffc987812d6b17d3e6",
+ "reference": "9c2ed2a29f1f58125a0f19ffc987812d6b17d3e6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "nette/caching": "~2.2",
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/di": "~2.3",
+ "nette/tester": "~1.4"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette PHP Reflection Component",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:34:53"
+ },
+ {
+ "name": "nette/robot-loader",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/robot-loader.git",
+ "reference": "69331d359bbc9e5f911c12b82187cac914d983fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/robot-loader/zipball/69331d359bbc9e5f911c12b82187cac914d983fb",
+ "reference": "69331d359bbc9e5f911c12b82187cac914d983fb",
+ "shasum": ""
+ },
+ "require": {
+ "nette/caching": "~2.2",
+ "nette/finder": "~2.3",
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.4"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette RobotLoader: comfortable autoloading",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:20:57"
+ },
+ {
+ "name": "nette/safe-stream",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/safe-stream.git",
+ "reference": "bf30db367b51a0932c44dcb9a378927644d48b2e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/safe-stream/zipball/bf30db367b51a0932c44dcb9a378927644d48b2e",
+ "reference": "bf30db367b51a0932c44dcb9a378927644d48b2e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/loader.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette SafeStream: Atomic Operations",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 20:59:15"
+ },
+ {
+ "name": "nette/security",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/security.git",
+ "reference": "744264a42b506d63009d7e3853ed72b04c99e964"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/security/zipball/744264a42b506d63009d7e3853ed72b04c99e964",
+ "reference": "744264a42b506d63009d7e3853ed72b04c99e964",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "~2.2",
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/di": "~2.3",
+ "nette/http": "~2.3",
+ "nette/tester": "~1.4"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Security: Access Control Component",
+ "homepage": "http://nette.org",
+ "time": "2015-07-11 21:22:53"
+ },
+ {
+ "name": "nette/utils",
+ "version": "v2.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/utils.git",
+ "reference": "ff80fce39fdc381e7e0db6cc5ffc82162e59f6bb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/utils/zipball/ff80fce39fdc381e7e0db6cc5ffc82162e59f6bb",
+ "reference": "ff80fce39fdc381e7e0db6cc5ffc82162e59f6bb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.1"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~1.0"
+ },
+ "suggest": {
+ "ext-gd": "to use Image",
+ "ext-iconv": "to use Strings::webalize() and toAscii()",
+ "ext-intl": "for script transliteration in Strings::webalize() and toAscii()",
+ "ext-mbstring": "to use Strings::lower() etc..."
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Utility Classes",
+ "homepage": "http://nette.org",
+ "time": "2015-07-13 22:30:00"
+ },
+ {
+ "name": "pdepend/pdepend",
+ "version": "2.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pdepend/pdepend.git",
+ "reference": "a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pdepend/pdepend/zipball/a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4",
+ "reference": "a15ffcbfbcc4570d4a733ca7b76e9cac0a56c3f4",
+ "shasum": ""
+ },
+ "require": {
+ "symfony/config": ">=2.4",
+ "symfony/dependency-injection": ">=2.4",
+ "symfony/filesystem": ">=2.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*@stable",
+ "squizlabs/php_codesniffer": "@stable"
+ },
+ "bin": [
+ "src/bin/pdepend"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "PDepend\\": "src/main/php/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Official version of pdepend to be handled with Composer",
+ "time": "2015-03-02 08:06:43"
+ },
+ {
+ "name": "phploc/phploc",
+ "version": "2.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phploc.git",
+ "reference": "322ad07c112d5c6832abed4269d648cacff5959b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/322ad07c112d5c6832abed4269d648cacff5959b",
+ "reference": "322ad07c112d5c6832abed4269d648cacff5959b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/finder-facade": "~1.1",
+ "sebastian/git": "~1.0",
+ "sebastian/version": "~1.0",
+ "symfony/console": "~2.2"
+ },
+ "bin": [
+ "phploc"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "A tool for quickly measuring the size of a PHP project.",
+ "homepage": "https://github.com/sebastianbergmann/phploc",
+ "time": "2014-06-25 08:11:02"
+ },
+ {
+ "name": "phpmd/phpmd",
+ "version": "2.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpmd/phpmd.git",
+ "reference": "1a485d9db869137af5e9678bd844568c92998b25"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpmd/phpmd/zipball/1a485d9db869137af5e9678bd844568c92998b25",
+ "reference": "1a485d9db869137af5e9678bd844568c92998b25",
+ "shasum": ""
+ },
+ "require": {
+ "pdepend/pdepend": "2.0.*",
+ "php": ">=5.3.0",
+ "symfony/config": "2.5.*",
+ "symfony/dependency-injection": "2.5.*",
+ "symfony/filesystem": "2.5.*"
+ },
+ "bin": [
+ "src/bin/phpmd"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "PHPMD\\": "src/main/php"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Official version of PHPMD handled with Composer.",
+ "time": "2014-09-25 15:56:22"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "2.1.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "5bd48b86cd282da411bb80baac1398ce3fefac41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5bd48b86cd282da411bb80baac1398ce3fefac41",
+ "reference": "5bd48b86cd282da411bb80baac1398ce3fefac41",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "phpunit/php-file-iterator": "~1.3",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-token-stream": "~1.3",
+ "sebastian/environment": "~1.0",
+ "sebastian/version": "~1.0"
+ },
+ "require-dev": {
+ "ext-xdebug": ">=2.1.4",
+ "phpunit/phpunit": "~4"
+ },
+ "suggest": {
+ "ext-dom": "*",
+ "ext-xdebug": ">=2.2.1",
+ "ext-xmlwriter": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "time": "2015-07-26 12:54:47"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "1.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
+ "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "File/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ ""
+ ],
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "time": "2013-10-10 15:34:57"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "time": "2015-06-21 13:50:34"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "1.0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
+ "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "time": "2015-06-21 08:01:12"
+ },
+ {
+ "name": "phpunit/php-token-stream",
+ "version": "1.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+ "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/7a9b0969488c3c54fd62b4d504b3ec758fd005d9",
+ "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Wrapper around PHP's tokenizer extension.",
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+ "keywords": [
+ "tokenizer"
+ ],
+ "time": "2015-06-19 03:43:16"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "4.2.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "c28a790620fe30b049bb693be1ef9cd4e0fe906c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c28a790620fe30b049bb693be1ef9cd4e0fe906c",
+ "reference": "c28a790620fe30b049bb693be1ef9cd4e0fe906c",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-pcre": "*",
+ "ext-reflection": "*",
+ "ext-spl": "*",
+ "php": ">=5.3.3",
+ "phpunit/php-code-coverage": "~2.0",
+ "phpunit/php-file-iterator": "~1.3.1",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-timer": "~1.0.2",
+ "phpunit/phpunit-mock-objects": "~2.2",
+ "sebastian/comparator": "~1.0",
+ "sebastian/diff": "~1.1",
+ "sebastian/environment": "~1.0",
+ "sebastian/exporter": "~1.0",
+ "sebastian/version": "~1.0",
+ "symfony/yaml": "~2.0"
+ },
+ "suggest": {
+ "phpunit/php-invoker": "~1.1"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ "",
+ "../../symfony/yaml/"
+ ],
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "http://www.phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "time": "2014-09-14 09:31:24"
+ },
+ {
+ "name": "phpunit/phpunit-mock-objects",
+ "version": "2.3.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+ "reference": "18dfbcb81d05e2296c0bcddd4db96cade75e6f42"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/18dfbcb81d05e2296c0bcddd4db96cade75e6f42",
+ "reference": "18dfbcb81d05e2296c0bcddd4db96cade75e6f42",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "~1.0,>=1.0.2",
+ "php": ">=5.3.3",
+ "phpunit/php-text-template": "~1.2",
+ "sebastian/exporter": "~1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "suggest": {
+ "ext-soap": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Mock Object library for PHPUnit",
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
+ "keywords": [
+ "mock",
+ "xunit"
+ ],
+ "time": "2015-07-10 06:54:24"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Psr\\Log\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "time": "2012-12-21 11:40:51"
+ },
+ {
+ "name": "satooshi/php-coveralls",
+ "version": "v0.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/satooshi/php-coveralls.git",
+ "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760",
+ "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "ext-simplexml": "*",
+ "guzzle/guzzle": ">=3.0",
+ "php": ">=5.3",
+ "psr/log": "1.0.0",
+ "symfony/config": ">=2.0",
+ "symfony/console": ">=2.0",
+ "symfony/stopwatch": ">=2.2",
+ "symfony/yaml": ">=2.0"
+ },
+ "require-dev": {
+ "apigen/apigen": "2.8.*@stable",
+ "pdepend/pdepend": "dev-master",
+ "phpmd/phpmd": "dev-master",
+ "phpunit/php-invoker": ">=1.1.0,<1.2.0",
+ "phpunit/phpunit": "3.7.*@stable",
+ "sebastian/finder-facade": "dev-master",
+ "sebastian/phpcpd": "1.4.*@stable",
+ "squizlabs/php_codesniffer": "1.4.*@stable",
+ "theseer/fdomdocument": "dev-master"
+ },
+ "bin": [
+ "composer/bin/coveralls"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Contrib\\Component": "src/",
+ "Contrib\\Bundle": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kitamura Satoshi",
+ "email": "with.no.parachute@gmail.com",
+ "homepage": "https://www.facebook.com/satooshi.jp"
+ }
+ ],
+ "description": "PHP client library for Coveralls API",
+ "homepage": "https://github.com/satooshi/php-coveralls",
+ "keywords": [
+ "ci",
+ "coverage",
+ "github",
+ "test"
+ ],
+ "time": "2013-05-04 08:07:33"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/diff": "~1.2",
+ "sebastian/exporter": "~1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "http://www.github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "time": "2015-07-26 15:48:44"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3",
+ "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "http://www.github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff"
+ ],
+ "time": "2015-02-22 15:13:53"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "4fe0a44cddd8cc19583a024bdc7374eb2fef0b87"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4fe0a44cddd8cc19583a024bdc7374eb2fef0b87",
+ "reference": "4fe0a44cddd8cc19583a024bdc7374eb2fef0b87",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "time": "2015-07-26 06:42:57"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/recursion-context": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "time": "2015-06-21 07:55:53"
+ },
+ {
+ "name": "sebastian/finder-facade",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/finder-facade.git",
+ "reference": "a520dcc3dd39160eea480daa3426f4fd419a327b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/a520dcc3dd39160eea480daa3426f4fd419a327b",
+ "reference": "a520dcc3dd39160eea480daa3426f4fd419a327b",
+ "shasum": ""
+ },
+ "require": {
+ "symfony/finder": "~2.3",
+ "theseer/fdomdocument": "~1.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.",
+ "homepage": "https://github.com/sebastianbergmann/finder-facade",
+ "time": "2015-06-04 08:11:58"
+ },
+ {
+ "name": "sebastian/git",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/git.git",
+ "reference": "a99fbc102e982c1404041ef3e4d431562b29bcba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/git/zipball/a99fbc102e982c1404041ef3e4d431562b29bcba",
+ "reference": "a99fbc102e982c1404041ef3e4d431562b29bcba",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple wrapper for Git",
+ "homepage": "http://www.github.com/sebastianbergmann/git",
+ "keywords": [
+ "git"
+ ],
+ "time": "2013-08-04 09:35:29"
+ },
+ {
+ "name": "sebastian/phpcpd",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpcpd.git",
+ "reference": "d3ad100fdf15805495f6ff19f473f4314c99390c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/d3ad100fdf15805495f6ff19f473f4314c99390c",
+ "reference": "d3ad100fdf15805495f6ff19f473f4314c99390c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "phpunit/php-timer": "~1.0",
+ "sebastian/finder-facade": "~1.1",
+ "sebastian/version": "~1.0",
+ "symfony/console": "~2.2",
+ "theseer/fdomdocument": "~1.4"
+ },
+ "bin": [
+ "phpcpd"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Copy/Paste Detector (CPD) for PHP code.",
+ "homepage": "https://github.com/sebastianbergmann/phpcpd",
+ "time": "2015-03-26 14:47:38"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "994d4a811bafe801fb06dccbee797863ba2792ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba",
+ "reference": "994d4a811bafe801fb06dccbee797863ba2792ba",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+ "time": "2015-06-21 08:04:50"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "1.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "time": "2015-06-21 13:59:46"
+ },
+ {
+ "name": "seld/jsonlint",
+ "version": "1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/jsonlint.git",
+ "reference": "863ae85c6d3ef60ca49cb12bd051c4a0648c40c4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/863ae85c6d3ef60ca49cb12bd051c4a0648c40c4",
+ "reference": "863ae85c6d3ef60ca49cb12bd051c4a0648c40c4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "bin": [
+ "bin/jsonlint"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Seld\\JsonLint\\": "src/Seld/JsonLint/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "JSON Linter",
+ "keywords": [
+ "json",
+ "linter",
+ "parser",
+ "validator"
+ ],
+ "time": "2015-01-04 21:18:15"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "1.5.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
+ "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5",
+ "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.1.2"
+ },
+ "suggest": {
+ "phpunit/php-timer": "dev-master"
+ },
+ "bin": [
+ "scripts/phpcs"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-phpcs-fixer": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "CodeSniffer.php",
+ "CodeSniffer/CLI.php",
+ "CodeSniffer/Exception.php",
+ "CodeSniffer/File.php",
+ "CodeSniffer/Report.php",
+ "CodeSniffer/Reporting.php",
+ "CodeSniffer/Sniff.php",
+ "CodeSniffer/Tokens.php",
+ "CodeSniffer/Reports/",
+ "CodeSniffer/CommentParser/",
+ "CodeSniffer/Tokenizers/",
+ "CodeSniffer/DocGenerators/",
+ "CodeSniffer/Standards/AbstractPatternSniff.php",
+ "CodeSniffer/Standards/AbstractScopeSniff.php",
+ "CodeSniffer/Standards/AbstractVariableSniff.php",
+ "CodeSniffer/Standards/IncorrectPatternException.php",
+ "CodeSniffer/Standards/Generic/Sniffs/",
+ "CodeSniffer/Standards/MySource/Sniffs/",
+ "CodeSniffer/Standards/PEAR/Sniffs/",
+ "CodeSniffer/Standards/PSR1/Sniffs/",
+ "CodeSniffer/Standards/PSR2/Sniffs/",
+ "CodeSniffer/Standards/Squiz/Sniffs/",
+ "CodeSniffer/Standards/Zend/Sniffs/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "lead"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "http://www.squizlabs.com/php-codesniffer",
+ "keywords": [
+ "phpcs",
+ "standards"
+ ],
+ "time": "2014-12-04 22:32:15"
+ },
+ {
+ "name": "symfony/config",
+ "version": "v2.5.12",
+ "target-dir": "Symfony/Component/Config",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Config.git",
+ "reference": "c7309e33b719433d5cf3845d0b5b9608609d8c8e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Config/zipball/c7309e33b719433d5cf3845d0b5b9608609d8c8e",
+ "reference": "c7309e33b719433d5cf3845d0b5b9608609d8c8e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/filesystem": "~2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Config\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ },
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Symfony Config Component",
+ "homepage": "http://symfony.com",
+ "time": "2015-01-03 08:01:13"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v2.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Console.git",
+ "reference": "8cf484449130cabfd98dcb4694ca9945802a21ed"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Console/zipball/8cf484449130cabfd98dcb4694ca9945802a21ed",
+ "reference": "8cf484449130cabfd98dcb4694ca9945802a21ed",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/event-dispatcher": "~2.1",
+ "symfony/phpunit-bridge": "~2.7",
+ "symfony/process": "~2.1"
+ },
+ "suggest": {
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/process": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "https://symfony.com",
+ "time": "2015-07-09 16:07:40"
+ },
+ {
+ "name": "symfony/dependency-injection",
+ "version": "v2.5.12",
+ "target-dir": "Symfony/Component/DependencyInjection",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/DependencyInjection.git",
+ "reference": "c42aee05b466cc9c66b87ddf7d263402befb6962"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/c42aee05b466cc9c66b87ddf7d263402befb6962",
+ "reference": "c42aee05b466cc9c66b87ddf7d263402befb6962",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/config": "~2.2",
+ "symfony/expression-language": "~2.4,>=2.4.10",
+ "symfony/yaml": "~2.1"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\DependencyInjection\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ },
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Symfony DependencyInjection Component",
+ "homepage": "http://symfony.com",
+ "time": "2015-01-25 04:37:39"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v2.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/EventDispatcher.git",
+ "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/9310b5f9a87ec2ea75d20fec0b0017c77c66dac3",
+ "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.0,>=2.0.5",
+ "symfony/dependency-injection": "~2.6",
+ "symfony/expression-language": "~2.6",
+ "symfony/phpunit-bridge": "~2.7",
+ "symfony/stopwatch": "~2.3"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "https://symfony.com",
+ "time": "2015-06-18 19:21:56"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v2.5.12",
+ "target-dir": "Symfony/Component/Filesystem",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Filesystem.git",
+ "reference": "d3c24d7d6e9c342008d8421b2fade460311647ea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Filesystem/zipball/d3c24d7d6e9c342008d8421b2fade460311647ea",
+ "reference": "d3c24d7d6e9c342008d8421b2fade460311647ea",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Filesystem\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ },
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Symfony Filesystem Component",
+ "homepage": "http://symfony.com",
+ "time": "2015-01-03 21:04:44"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v2.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Finder.git",
+ "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4",
+ "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "~2.7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Finder Component",
+ "homepage": "https://symfony.com",
+ "time": "2015-07-09 16:07:40"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v2.6.11",
+ "target-dir": "Symfony/Component/OptionsResolver",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/OptionsResolver.git",
+ "reference": "31e56594cee489e9a235b852228b0598b52101c1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/OptionsResolver/zipball/31e56594cee489e9a235b852228b0598b52101c1",
+ "reference": "31e56594cee489e9a235b852228b0598b52101c1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "~2.7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony OptionsResolver Component",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "time": "2015-05-13 11:33:56"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v2.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Stopwatch.git",
+ "reference": "b07a866719bbac5294c67773340f97b871733310"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/b07a866719bbac5294c67773340f97b871733310",
+ "reference": "b07a866719bbac5294c67773340f97b871733310",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "~2.7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Stopwatch Component",
+ "homepage": "https://symfony.com",
+ "time": "2015-07-01 18:23:16"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "v2.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Yaml.git",
+ "reference": "4bfbe0ed3909bfddd75b70c094391ec1f142f860"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Yaml/zipball/4bfbe0ed3909bfddd75b70c094391ec1f142f860",
+ "reference": "4bfbe0ed3909bfddd75b70c094391ec1f142f860",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "~2.7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Yaml\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Yaml Component",
+ "homepage": "https://symfony.com",
+ "time": "2015-07-01 11:25:50"
+ },
+ {
+ "name": "theseer/fdomdocument",
+ "version": "1.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/fDOMDocument.git",
+ "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d9ad139d6c2e8edf5e313ffbe37ff13344cf0684",
+ "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "lib-libxml": "*",
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.",
+ "homepage": "https://github.com/theseer/fDOMDocument",
+ "time": "2015-05-27 22:58:02"
+ },
+ {
+ "name": "tracy/tracy",
+ "version": "v2.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tracy.git",
+ "reference": "17d15b8dc83cab3bc5022a45d32c681a76cc19e1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tracy/zipball/17d15b8dc83cab3bc5022a45d32c681a76cc19e1",
+ "reference": "17d15b8dc83cab3bc5022a45d32c681a76cc19e1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.1"
+ },
+ "require-dev": {
+ "nette/di": "~2.3",
+ "nette/tester": "~1.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src"
+ ],
+ "files": [
+ "src/shortcuts.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "http://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "http://nette.org/contributors"
+ }
+ ],
+ "description": "Tracy: useful PHP debugger",
+ "homepage": "http://tracy.nette.org",
+ "keywords": [
+ "debug",
+ "debugger",
+ "nette"
+ ],
+ "time": "2015-07-03 12:52:35"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=5.4.0"
+ },
+ "platform-dev": []
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/add_shipping_info.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/add_shipping_info.php
new file mode 100644
index 0000000..5bbdc2c
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/add_shipping_info.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Appends shipping info to a capture.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+$captureId = getenv('CAPTURE_ID') ?: '34567';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+
+$capture = $order->fetchCapture($captureId);
+$capture->addShippingInfo([
+ "shipping_info" => [
+ [
+ "shipping_company" => "DHL",
+ "shipping_method" => "Home",
+ "tracking_uri" => "http://www.dhl.com/content/g0/en/express/tracking.shtml?brand=DHL&AWB=1234567890",
+ "tracking_number" => "1234567890",
+ "return_tracking_number" => "E-55-KL",
+ "return_shipping_company" => "DHL",
+ "return_tracking_uri" => "http://www.dhl.com/content/g0/en/express/tracking.shtml?brand=DHL&AWB=98389222"
+ ]
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/trigger_send_out.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/trigger_send_out.php
new file mode 100644
index 0000000..968d187
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/trigger_send_out.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Trigger a new send out of customer communication.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+$captureId = getenv('CAPTURE_ID') ?: '34567';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+
+$capture = $order->fetchCapture($captureId);
+$capture->triggerSendout();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/update_customer_details.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/update_customer_details.php
new file mode 100644
index 0000000..6cfe334
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/capture/update_customer_details.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Update the billing address for a capture. Shipping address can not be updated.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+$captureId = getenv('CAPTURE_ID') ?: '34567';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+
+$capture = $order->fetchCapture($captureId);
+$capture->updateCustomerDetails([
+ "billing_address" => [
+ "email" => "user@example.com",
+ "phone" => "57-3895734"
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout.php
new file mode 100644
index 0000000..f34b171
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Create a checkout order.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$checkout = new Klarna\Rest\Checkout\Order($connector);
+$checkout->create([
+ "purchase_country" => "gb",
+ "purchase_currency" => "gbp",
+ "locale" => "en-gb",
+ "order_amount" => 10000,
+ "order_tax_amount" => 2000,
+ "order_lines" => [
+ [
+ "type" => "physical",
+ "reference" => "123050",
+ "name" => "Tomatoes",
+ "quantity" => 10,
+ "quantity_unit" => "kg",
+ "unit_price" => 600,
+ "tax_rate" => 2500,
+ "total_amount" => 6000,
+ "total_tax_amount" => 1200
+ ],
+ [
+ "type" => "physical",
+ "reference" => "543670",
+ "name" => "Bananas",
+ "quantity" => 1,
+ "quantity_unit" => "bag",
+ "unit_price" => 5000,
+ "tax_rate" => 2500,
+ "total_amount" => 4000,
+ "total_discount_amount" => 1000,
+ "total_tax_amount" => 800
+ ]
+ ],
+ "merchant_urls" => [
+ "terms" => "http://www.merchant.com/toc",
+ "checkout" => "http://www.merchant.com/checkout?klarna_order_id={checkout.order.id}",
+ "confirmation" => "http://www.merchant.com/thank-you?klarna_order_id={checkout.order.id}",
+ "push" => "http://www.merchant.com/create_order?klarna_order_id={checkout.order.id}"
+ ]
+]);
+
+$checkout->fetch();
+
+// Store checkout order id
+$orderId = $checkout->getId();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout_attachment.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout_attachment.php
new file mode 100644
index 0000000..0299742
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/create_checkout_attachment.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Create a checkout order with a extra merchant data attachment.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+const EMD_FORMAT = 'Y-m-d\TH:m:s\Z';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$emd = [
+ "payment_history_full" => [
+ [
+ "unique_account_identifier" => "Test Testperson",
+ "payment_option" => "card",
+ "number_paid_purchases" => 1,
+ "total_amount_paid_purchases" => 10000,
+ "date_of_last_paid_purchase" => (new DateTime())->format(EMD_FORMAT),
+ "date_of_first_paid_purchase" => (new DateTime())->format(EMD_FORMAT)
+ ]
+ ]
+];
+
+$checkout = new Klarna\Rest\Checkout\Order($connector);
+$checkout->create([
+ "purchase_country" => "gb",
+ "purchase_currency" => "gbp",
+ "locale" => "en-gb",
+ "order_amount" => 10000,
+ "order_tax_amount" => 2000,
+ "order_lines" => [
+ [
+ "type" => "physical",
+ "reference" => "123050",
+ "name" => "Tomatoes",
+ "quantity" => 10,
+ "quantity_unit" => "kg",
+ "unit_price" => 600,
+ "tax_rate" => 2500,
+ "total_amount" => 6000,
+ "total_tax_amount" => 1200
+ ],
+ [
+ "type" => "physical",
+ "reference" => "543670",
+ "name" => "Bananas",
+ "quantity" => 1,
+ "quantity_unit" => "bag",
+ "unit_price" => 5000,
+ "tax_rate" => 2500,
+ "total_amount" => 4000,
+ "total_discount_amount" => 1000,
+ "total_tax_amount" => 800
+ ]
+ ],
+ "merchant_urls" => [
+ "terms" => "http://www.merchant.com/toc",
+ "checkout" => "http://www.merchant.com/checkout?klarna_order_id={checkout.order.id}",
+ "confirmation" => "http://www.merchant.com/thank-you?klarna_order_id={checkout.order.id}",
+ "push" => "http://www.merchant.com/create_order?klarna_order_id={checkout.order.id}"
+ ],
+ "attachment" => [
+ "content_type" => "application/vnd.klarna.internal.emd-v2+json",
+ "body" => json_encode($emd)
+ ]
+]);
+
+$checkout->fetch();
+
+// Store checkout order id
+$orderId = $checkout->getId();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/fetch_checkout.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/fetch_checkout.php
new file mode 100644
index 0000000..8e1df96
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/fetch_checkout.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Retrieve a checkout order.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$checkout = new Klarna\Rest\Checkout\Order($connector, $orderId);
+$checkout->fetch();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/update_checkout.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/update_checkout.php
new file mode 100644
index 0000000..6d42d59
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/checkout/update_checkout.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Update a checkout order.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$checkout = new Klarna\Rest\Checkout\Order($connector, $orderId);
+$checkout->update([
+ "order_amount" => 11000,
+ "order_tax_amount" => 2200,
+ "order_lines" => [
+ [
+ "type" => "physical",
+ "reference" => "123050",
+ "name" => "Tomatoes",
+ "quantity" => 10,
+ "quantity_unit" => "kg",
+ "unit_price" => 600,
+ "tax_rate" => 2500,
+ "total_amount" => 6000,
+ "total_tax_amount" => 1200
+ ],
+ [
+ "type" => "physical",
+ "reference" => "543670",
+ "name" => "Bananas",
+ "quantity" => 1,
+ "quantity_unit" => "bag",
+ "unit_price" => 5000,
+ "tax_rate" => 2500,
+ "total_amount" => 4000,
+ "total_discount_amount" => 1000,
+ "total_tax_amount" => 800
+ ],
+ [
+ "type" => "shipping_fee",
+ "name" => "Express delivery",
+ "quantity" => 1,
+ "unit_price" => 1000,
+ "tax_rate" => 2500,
+ "total_amount" => 1000,
+ "total_tax_amount" => 200
+ ]
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/acknowledge_order.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/acknowledge_order.php
new file mode 100644
index 0000000..359f628
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/acknowledge_order.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Acknowledge an authorized order.
+ *
+ * Merchants will receive the order confirmation push until the order
+ * has been acknowledged.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->acknowledge();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/cancel_order.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/cancel_order.php
new file mode 100644
index 0000000..ebd49eb
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/cancel_order.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Cancel an authorized order.
+ *
+ * For a cancellation to be successful, there must be no captures on the order.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->cancel();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/create_capture.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/create_capture.php
new file mode 100644
index 0000000..88f06f7
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/create_capture.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Capture the supplied amount.
+ *
+ * Use this call when fulfillment is completed, e.g. physical goods are
+ * being shipped to the customer.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->createCapture([
+ "captured_amount" => 6000,
+ "description" => "Shipped part of the order",
+ "order_lines" => [
+ [
+ "type" => "physical",
+ "reference" => "123050",
+ "name" => "Tomatoes",
+ "quantity" => 10,
+ "quantity_unit" => "kg",
+ "unit_price" => 600,
+ "tax_rate" => 2500,
+ "total_amount" => 6000,
+ "total_tax_amount" => 1200
+ ]
+ ],
+ "shipping_info" => [
+ [
+ "shipping_company" => "DHL",
+ "shipping_method" => "Home",
+ "tracking_uri" => "http://www.dhl.com/content/g0/en/express/tracking.shtml?brand=DHL&AWB=1234567890",
+ "tracking_number" => "1234567890",
+ "return_tracking_number" => "E-55-KL",
+ "return_shipping_company" => "DHL",
+ "return_tracking_uri" => "http://www.dhl.com/content/g0/en/express/tracking.shtml?brand=DHL&AWB=98389222"
+ ]
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/extend_authorization_time.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/extend_authorization_time.php
new file mode 100644
index 0000000..745d1be
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/extend_authorization_time.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Extend the order's authorization by default period according to merchant contract.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->extendAuthorizationTime();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_capture.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_capture.php
new file mode 100644
index 0000000..e0d0053
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_capture.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Retrieve a capture.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+$captureId = getenv('CAPTURE_ID') ?: '34567';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+
+$capture = $order->fetchCapture($captureId);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_order.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_order.php
new file mode 100644
index 0000000..e333dac
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/fetch_order.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Retrieve a order.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->fetch();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/refund_order.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/refund_order.php
new file mode 100644
index 0000000..aafb52f
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/refund_order.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Refund an amount of a captured order.
+ *
+ * The refunded amount will be credited to the customer.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->refund([
+ "refunded_amount" => 3000,
+ "description" => "Refunding half the tomatoes",
+ "order_lines" => [
+ [
+ "type" => "physical",
+ "reference" => "123050",
+ "name" => "Tomatoes",
+ "quantity" => 5,
+ "quantity_unit" => "kg",
+ "unit_price" => 600,
+ "tax_rate" => 2500,
+ "total_amount" => 3000,
+ "total_tax_amount" => 600
+ ]
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/release_remaining_authorization.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/release_remaining_authorization.php
new file mode 100644
index 0000000..fc51926
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/release_remaining_authorization.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Release the remaining authorization for an order.
+ *
+ * Signal that there is no intention to perform further captures.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->releaseRemainingAuthorization();
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_customer_details.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_customer_details.php
new file mode 100644
index 0000000..aa29e17
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_customer_details.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Update billing and/or shipping address for an order.
+ *
+ * This is subject to customer credit check.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->updateCustomerDetails([
+ "billing_address" => [
+ "email" => "user@example.com",
+ "phone" => "57-3895734"
+ ],
+ "shipping_address" => [
+ "email" => "user@example.com",
+ "phone" => "57-3895734"
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_merchant_references.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_merchant_references.php
new file mode 100644
index 0000000..5cd3bc3
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_merchant_references.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Update one or both merchant references.
+ *
+ * Only the reference(s) in the body will be updated. To clear a reference,
+ * set its value to "" (empty string).
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->updateMerchantReferences([
+ "merchant_reference1" => "15632423",
+ "merchant_reference2" => "special order"
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_order_lines.php b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_order_lines.php
new file mode 100644
index 0000000..b90ef11
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/docs/examples/order/update_order_lines.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Update the total order amount of an order.
+ *
+ * This is subject to a new customer credit check.
+ */
+
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+$merchantId = getenv('MERCHANT_ID') ?: '0';
+$sharedSecret = getenv('SHARED_SECRET') ?: 'sharedSecret';
+$orderId = getenv('ORDER_ID') ?: '12345';
+
+$connector = Klarna\Rest\Transport\Connector::create(
+ $merchantId,
+ $sharedSecret,
+ Klarna\Rest\Transport\ConnectorInterface::EU_TEST_BASE_URL
+);
+
+$order = new Klarna\Rest\OrderManagement\Order($connector, $orderId);
+$order->updateAuthorization([
+ "order_amount" => 6000,
+ "description" => "Removed bad bananas",
+ "order_lines" => [
+ [
+ "type" => "physical",
+ "reference" => "123050",
+ "name" => "Tomatoes",
+ "quantity" => 10,
+ "quantity_unit" => "kg",
+ "unit_price" => 600,
+ "tax_rate" => 2500,
+ "total_amount" => 6000,
+ "total_tax_amount" => 1200
+ ]
+ ]
+]);
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/README.md b/public/system/storage/vendor/klarna/kco_rest/git_hooks/README.md
new file mode 100644
index 0000000..cb38f17
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/README.md
@@ -0,0 +1,14 @@
+install
+-------
+
+ git remote add -f hooks ssh://git@stash.internal.machines:7999/mint/git-hooks.git
+ git merge -s ours --no-commit hooks/master
+ git read-tree --prefix=git_hooks -u hooks/master
+ git commit -m "imported git hooks"
+
+
+updating
+--------
+
+ git fetch hooks
+ git merge -s subtree hooks/master
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/coffeelint b/public/system/storage/vendor/klarna/kco_rest/git_hooks/coffeelint
new file mode 100644
index 0000000..e308470
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/coffeelint
@@ -0,0 +1,103 @@
+{
+ "arrow_spacing": {
+ "level": "ignore"
+ },
+ "camel_case_classes": {
+ "level": "error"
+ },
+ "coffeescript_error": {
+ "level": "error"
+ },
+ "colon_assignment_spacing": {
+ "level": "ignore",
+ "spacing": {
+ "left": 0,
+ "right": 0
+ }
+ },
+ "cyclomatic_complexity": {
+ "value": 10,
+ "level": "ignore"
+ },
+ "duplicate_key": {
+ "level": "error"
+ },
+ "empty_constructor_needs_parens": {
+ "level": "ignore"
+ },
+ "indentation": {
+ "value": 4,
+ "level": "error"
+ },
+ "line_endings": {
+ "level": "ignore",
+ "value": "unix"
+ },
+ "max_line_length": {
+ "value": 80,
+ "level": "error",
+ "limitComments": true
+ },
+ "missing_fat_arrows": {
+ "level": "ignore"
+ },
+ "newlines_after_classes": {
+ "value": 3,
+ "level": "ignore"
+ },
+ "no_backticks": {
+ "level": "error"
+ },
+ "no_debugger": {
+ "level": "warn"
+ },
+ "no_empty_functions": {
+ "level": "ignore"
+ },
+ "no_empty_param_list": {
+ "level": "ignore"
+ },
+ "no_implicit_braces": {
+ "level": "ignore",
+ "strict": true
+ },
+ "no_implicit_parens": {
+ "strict": true,
+ "level": "ignore"
+ },
+ "no_interpolation_in_single_quotes": {
+ "level": "ignore"
+ },
+ "no_plusplus": {
+ "level": "ignore"
+ },
+ "no_stand_alone_at": {
+ "level": "ignore"
+ },
+ "no_tabs": {
+ "level": "error"
+ },
+ "no_throwing_strings": {
+ "level": "error"
+ },
+ "no_trailing_semicolons": {
+ "level": "error"
+ },
+ "no_trailing_whitespace": {
+ "level": "error",
+ "allowed_in_comments": false,
+ "allowed_in_empty_lines": true
+ },
+ "no_unnecessary_double_quotes": {
+ "level": "ignore"
+ },
+ "no_unnecessary_fat_arrows": {
+ "level": "warn"
+ },
+ "non_empty_constructor_needs_parens": {
+ "level": "ignore"
+ },
+ "space_operators": {
+ "level": "ignore"
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/message-format b/public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/message-format
new file mode 100644
index 0000000..c579f22
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/message-format
@@ -0,0 +1,34 @@
+#!/bin/bash
+# http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+
+case "${1}" in
+ --about )
+ echo "make sure commit message is within line width limits"
+ ;;
+ * )
+ awk '
+/^#/ {
+ NR--
+ next
+}
+
+NR == 1 {
+ if (length > 50) {
+ print "title too long"
+ exit 1
+ }
+}
+
+NR == 2 {
+ if (length != 0) {
+ print "2nd line should be empty"
+ exit 2
+ }
+}
+
+{
+ if (length > 72) {
+ print "line ", FNR, " is too long";
+ }
+}' "${1}"
+esac
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/ticket-number b/public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/ticket-number
new file mode 100644
index 0000000..a312756
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/commit-msg/ticket-number
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+function run_test
+{
+ if ! grep -qvE '^#.*|^$' $1 ; then
+ exit 0
+ fi
+
+ ticket=$(git symbolic-ref HEAD | grep -oP "([A-Z]+)-([0-9]+)")
+
+ if [ -z $ticket ]; then
+ exit 0
+ fi
+
+ if grep -q "^$ticket" $1; then
+ exit 0
+ fi
+
+ echo >> $1
+ echo $ticket >> $1
+}
+
+case "${1}" in
+ --about )
+ echo "Append ticket number to commit message"
+ ;;
+ * )
+ run_test "$@"
+ ;;
+esac
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/jshint b/public/system/storage/vendor/klarna/kco_rest/git_hooks/jshint
new file mode 100644
index 0000000..da2bb59
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/jshint
@@ -0,0 +1,69 @@
+{
+ // ENFORCE
+ "curly" : true, // Require {} around one-line blocks
+ "eqeqeq" : true, // Require ===
+ "forin" : true, // Require hasOwnProperty inside forins
+ "immed" : false, // Require immediate invocations to be wrapped in parenthesis
+ // eg. (fun(){}())
+ "latedef" : true, // Prohibit undefined variables (undef?!)
+ "newcap" : true, // Require capitalized constructors
+ "noarg" : true, // Prohibit arguments.callee and .caller
+ "noempty" : false, // Prohibit empty blocks "{}"
+ "nonew" : false, // Prohibit new
+ "plusplus" : false, // Prohibit ++ and --
+ "regexp" : false, // Prohibit . in RegExp
+ "strict" : true, // Require 'use strict'
+ "trailing" : true, // Prohibit trailing spaces
+ "undef" : true, // Prohibit undeclared variables
+ "unused" : "vars",// Prohibit unused variables
+
+ // RELAX
+ "asi" : false, // Allow missing semicolons due to automatic insertion
+ "bitwise" : false, // Allow bitwise operators
+ "boss" : false, // Allow advanced usage of assignments
+ "debug" : false, // Allow debugger statements
+ "eqnull" : false, // Allow "== null"
+ "esnext" : false, // Allow ES.next statements
+ "evil" : false, // Allow eval
+ "expr" : false, // Allow expressions instead of assignments/function calls
+ "funcscope" : false, // Allow vars declared in blocks (ie. if)
+ "globalstrict" : false, // Allow global 'use strict'
+ "iterator" : false, // Allow __iterator__
+ "lastsemic" : false, // Allow one-line blocks with no semicolon
+ "laxbreak" : false, // Allow unsafe line breaks
+ "loopfunc" : false, // Allow function creation inside loops
+ "multistr" : false, // Allow multiline strings
+ "nonstandard" : false, // Allow (un)escape
+ "onecase" : false, // Allow one-case switch statements (=if)
+ "proto" : false, // Allow __proto__
+ "regexdash" : false, // Allow RegExp to finish with a dash
+ "scripturl" : false, // Allow script-targeted URLs
+ "shadow" : false, // Allow variable shadowing (redeclaring in new scope)
+ "sub" : false, // Allow object['name'], not just object.name
+ "supernew" : false, // Allow "new function(){}" and "new Object"
+ "validthis" : false, // Allow this even inside a non-constructor
+
+ // LEGACY
+ "nomen" : false, // Enforce no dangling underscores
+ "onevar" : true, // Enforce one var per function scope
+ "passfail" : false, // Stop on first error
+ "white" : false, // Strict Douglas' whitespace rules
+
+ // MISC
+ "indent" : 4, // Check that indentation is X spaces
+ "maxlen" : 100, // Maximum characters/line
+
+ // ENVIRONMENT (GLOBALS)
+ "browser" : true, // Browser (setTimeout, document,..)
+ "couch" : false, // CouchDB
+ "devel" : false, // Development (console, alert,..)
+ "dojo" : false,
+ "jquery" : false,
+ "mootools" : false,
+ "node" : false,
+ "mocha" : true,
+ "prototypejs" : false,
+ "rhino" : false,
+ "wsh" : false // Window Scripting Host
+}
+
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-coffee b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-coffee
new file mode 100644
index 0000000..aa25de5
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-coffee
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+coffeelint_alt="node_modules/.bin/coffeelint coffeelint"
+
+for c in 'coffeelint.json' "`dirname $0`/../coffeelint"; do
+ if [ -e "$c" ]; then
+ config="$c"
+ fi
+done
+
+function run_coffeelint {
+ if [ -n "$config" ]; then
+ $coffeelint -f "${config}" ${@}
+ else
+ $coffeelint ${@}
+ fi
+}
+
+function changed_files {
+ git diff --cached --name-only --diff-filter=ACM
+}
+
+function write_staged {
+ while read file; do
+ name=`echo "$file" | sed 's:/:-:g'`
+ tmpfile=`mktemp /tmp/XXXXX-${name}`
+ git show ":$file" > $tmpfile
+ echo "$tmpfile"
+ done
+}
+
+case "${1}" in
+ --about )
+ if [ -z "$config" ]; then
+ config='default config'
+ fi
+ echo "Perform static analysis of coffee-script files (${config})"
+ ;;
+ * )
+ coffeelint=`which $jshint_alt 2>/dev/null | head -n 1`
+
+ # call out to tools
+ files=`changed_files | grep -e '\.coffee$' | write_staged`
+
+ if [ -z "$files" ]; then
+ exit 0
+ fi
+
+ if test -z "$coffeelint"; then
+ echo "Please install coffeelint: npm install -g coffeelint"
+ exit 0
+ fi
+
+ run_coffeelint $files
+ status=$?
+ rm $files
+ exit $status
+ ;;
+esac
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-js b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-js
new file mode 100644
index 0000000..3b8ce7e
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-js
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+jshint_alt="node_modules/.bin/jshint jshint"
+
+for c in '.jshintrc' "`dirname $0`/../jshint"; do
+ if [ -e "$c" ]; then
+ config="$c"
+ fi
+done
+
+function run_jshint {
+ if [ -n "$config" ]; then
+ $jshint --config "${config}" ${@}
+ else
+ $jshint ${@}
+ fi
+}
+
+function changed_files {
+ git diff --cached --name-only --diff-filter=ACM
+}
+
+function write_staged {
+ while read file; do
+ name=`basename $file`
+ tmpfile=`mktemp /tmp/XXXXX-${name}`
+ git show ":$file" > $tmpfile
+ echo "$tmpfile"
+ done
+}
+
+case "${1}" in
+ --about )
+ if [ -z "$config" ]; then
+ config='default config'
+ fi
+ echo "Perform static analysis of js source files (${config})"
+ ;;
+ * )
+ jshint=`which $jshint_alt 2>/dev/null | head -n 1`
+
+ # call out to tools
+ files=`changed_files | grep -e '\.js$' | write_staged`
+
+ if [ -z "$files" ]; then
+ exit 0
+ fi
+
+ if test -z "$jshint"; then
+ echo "Please install jshint: npm install -g jshint"
+ exit 0
+ fi
+
+ run_jshint $files
+ status=$?
+ rm $files
+ exit $status
+ ;;
+esac
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-php b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-php
new file mode 100644
index 0000000..8f591ed
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-php
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+phpcs_alt="vendor/bin/phpcs bin/phpcs ~/.composer/vendor/bin/phpcs phpcs"
+phpmd_alt="vendor/bin/phpmd bin/phpmd ~/.composer/vendor/bin/phpmd phpmd"
+
+phpcs_standard='PSR2'
+if [ -e "phpcs.xml" ]; then
+ phpcs_standard="./phpcs.xml"
+fi
+
+phpmd_output=text
+phpmd_rules='phpmd.xml'
+if [ ! -e "$phpmd_rules" ]; then
+ phpmd_rules='codesize,design,naming,unusedcode'
+fi
+
+function run_phpcs {
+ $phpcs --report-emacs --standard="$phpcs_standard" ${@}
+}
+
+function run_phpmd {
+ $phpmd "`echo $1 | tr ' ' ','`" "$phpmd_output" "$phpmd_rules"
+}
+
+function changed_files {
+ git diff --cached --name-only --diff-filter=ACM
+}
+
+function write_staged {
+ while read file; do
+ name=`basename $file`
+ tmpfile=`mktemp /tmp/XXXXX-${name}`
+ git show ":$file" > $tmpfile
+ echo "$tmpfile"
+ done
+}
+
+case "${1}" in
+ --about )
+ echo "Perform static analysis of php source files"
+ ;;
+ * )
+ phpcs=`which $phpcs_alt 2>/dev/null | head -n 1`
+ phpmd=`which $phpmd_alt 2>/dev/null | head -n 1`
+
+ # call out to tools
+ files=`changed_files | grep -e '\.php$' | write_staged`
+ if [ -z "$files" ]; then
+ exit 0
+ fi
+
+ if test -z "$phpcs" -o -z "$phpmd"; then
+ echo "Please install phpcs and phpmd: composer global require squizlabs/php_codesniffer phpmd/phpmd"
+ exit 0
+ fi
+
+ run_phpcs $files
+ phpcs_status=$?
+ run_phpmd $files
+ phpmd_status=$?
+ rm $files
+ test "$phpcs_status" -eq 0 -a "$phpmd_status" -eq 0
+ exit $?
+ ;;
+esac
diff --git a/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-python b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-python
new file mode 100644
index 0000000..aa93567
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/git_hooks/pre-commit/check-python
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+function run_pep8 {
+ pep8 ${@}
+}
+
+function run_pyflakes {
+ pyflakes ${@}
+}
+
+function changed_files {
+ git diff --cached --name-only --diff-filter=ACM
+}
+
+function write_staged {
+ while read file; do
+ name=`basename $file`
+ tmpfile=`mktemp /tmp/XXXXX-${name}`
+ git show ":$file" > $tmpfile
+ echo "$tmpfile"
+ done
+}
+
+case "${1}" in
+ --about )
+ echo "Perform static analysis of python source files"
+ ;;
+ * )
+ # call out to tools
+ files=`changed_files | grep -e '\.py$' | write_staged`
+ if [ -z "$files" ]; then
+ exit 0
+ fi
+
+ if ! which pep8 pyflakes > /dev/null; then
+ echo "Please install pep8 and pyflakes: pip install pep8 pyflakes"
+ exit 0
+ fi
+
+ run_pep8 $files
+ pep8_status=$?
+ run_pyflakes $files
+ pyflakes_status=$?
+ rm $files
+ test "$pep8_status" -eq 0 -a "$pyflakes_status" -eq 0
+ exit $?
+ ;;
+esac
diff --git a/public/system/storage/vendor/klarna/kco_rest/phpmd.xml b/public/system/storage/vendor/klarna/kco_rest/phpmd.xml
new file mode 100644
index 0000000..2348e78
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/phpmd.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<ruleset name="Klarna PHPMD Ruleset"
+ xmlns="http://pmd.sf.net/ruleset/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
+ xsi:noNamespaceSchemaLocation=" http://pmd.sf.net/ruleset_xml_schema.xsd"
+>
+ <description>Klarna PHPMD ruleset</description>
+
+ <rule ref="rulesets/cleancode.xml"/>
+
+ <rule ref="rulesets/codesize.xml">
+ <exclude name="TooManyMethods"/>
+ </rule>
+
+ <rule ref="rulesets/codesize.xml/TooManyMethods">
+ <priority>1</priority>
+ <properties>
+ <property name="maxmethods" value="15" />
+ </properties>
+ </rule>
+
+ <rule ref="rulesets/controversial.xml"/>
+
+ <rule ref="rulesets/design.xml"/>
+
+ <rule ref="rulesets/naming.xml">
+ <exclude name="ShortVariable"/>
+ </rule>
+
+ <rule ref="rulesets/unusedcode.xml"/>
+</ruleset>
diff --git a/public/system/storage/vendor/klarna/kco_rest/phpunit.xml.dist b/public/system/storage/vendor/klarna/kco_rest/phpunit.xml.dist
new file mode 100644
index 0000000..133de98
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/phpunit.xml.dist
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit
+ backupGlobals="false"
+ backupStaticAttributes="false"
+ bootstrap="tests/bootstrap.php"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false"
+ verbose="true"
+ strict="true">
+
+ <testsuites>
+ <testsuite name="Unit Tests">
+ <directory>tests/Unit</directory>
+ </testsuite>
+
+ <testsuite name="Component Tests">
+ <directory>tests/Component</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>src/</directory>
+ </whitelist>
+ </filter>
+
+ <logging>
+ <log type="coverage-html" target="build/coverage" title="kco_rest_php"
+ charset="UTF-8" yui="true" highlight="true"
+ lowUpperBound="35" highLowerBound="70"/>
+ <log type="coverage-clover" target="build/logs/clover.xml"/>
+ <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
+ </logging>
+</phpunit>
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Checkout/Order.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Checkout/Order.php
new file mode 100644
index 0000000..798f309
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Checkout/Order.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the Order class.
+ */
+
+namespace Klarna\Rest\Checkout;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Resource;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Checkout order resource.
+ *
+ * @example docs/examples/checkout/create_checkout.php Create the checkout order
+ * @example docs/examples/checkout/create_checkout_attachment.php EMD attachment
+ * @example docs/examples/checkout/fetch_checkout.php Retrieve a checkout order
+ * @example docs/examples/checkout/update_checkout.php Update a checkout order
+ */
+class Order extends Resource
+{
+ /**
+ * {@inheritDoc}
+ */
+ const ID_FIELD = 'order_id';
+
+ /**
+ * {@inheritDoc}
+ */
+ public static $path = '/checkout/v3/orders';
+
+ /**
+ * Constructs an order instance.
+ *
+ * @param Connector $connector HTTP transport connector
+ * @param string $orderId Order ID
+ */
+ public function __construct(Connector $connector, $orderId = null)
+ {
+ parent::__construct($connector);
+
+ if ($orderId !== null) {
+ $this->setLocation(self::$path . "/{$orderId}");
+ $this[static::ID_FIELD] = $orderId;
+ }
+ }
+
+ /**
+ * Creates the resource.
+ *
+ * @param array $data Creation data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the location header is missing
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function create(array $data)
+ {
+ $url = $this->post(self::$path, $data)
+ ->status('201')
+ ->getLocation();
+
+ $this->setLocation($url);
+
+ return $this;
+ }
+
+ /**
+ * Updates the resource.
+ *
+ * @param array $data Update data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException On an unexpected API response
+ * @throws \RuntimeException If the response content type is not JSON
+ * @throws \InvalidArgumentException If the JSON cannot be parsed
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function update(array $data)
+ {
+ $data = $this->post($this->getLocation(), $data)
+ ->status('200')
+ ->contentType('application/json')
+ ->getJson();
+
+ $this->exchangeArray($data);
+
+ return $this;
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Capture.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Capture.php
new file mode 100644
index 0000000..6f1a85b
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Capture.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the Capture class.
+ */
+
+namespace Klarna\Rest\OrderManagement;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Resource;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Capture resource.
+ *
+ * @example docs/examples/order/fetch_capture.php
+ * @example docs/examples/order/create_capture.php
+ * @example docs/examples/capture/append_shipping_info.php
+ * @example docs/examples/capture/trigger_send_out.php
+ * @example docs/examples/capture/update_customer_details.php
+ */
+class Capture extends Resource
+{
+ /**
+ * {@inheritDoc}
+ */
+ const ID_FIELD = 'capture_id';
+
+ /**
+ * {@inheritDoc}
+ */
+ public static $path = '/captures';
+
+ /**
+ * Constructs an order instance.
+ *
+ * @param Connector $connector HTTP transport connector
+ * @param string $orderUrl Parent order resource url
+ * @param string $captureId Capture ID
+ */
+ public function __construct(Connector $connector, $orderUrl, $captureId = null)
+ {
+ parent::__construct($connector);
+
+ $url = $orderUrl . self::$path;
+ if ($captureId !== null) {
+ $url = "{$url}/{$captureId}";
+ $this[static::ID_FIELD] = $captureId;
+ }
+
+ $this->setLocation($url);
+ }
+
+ /**
+ * Creates the resource.
+ *
+ * @param array $data Creation data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the location header is missing
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function create(array $data)
+ {
+ $url = $this->post($this->getLocation(), $data)
+ ->status('201')
+ ->getLocation();
+
+ $this->setLocation($url);
+
+ return $this;
+ }
+
+ /**
+ * Appends shipping information to the capture.
+ *
+ * @param array $data Shipping info data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function addShippingInfo(array $data)
+ {
+ $this->post($this->getLocation() . '/shipping-info', $data)
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Updates the customers details.
+ *
+ * @param array $data Customer details data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function updateCustomerDetails(array $data)
+ {
+ $this->patch($this->getLocation() . '/customer-details', $data)
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Trigger send outs for this capture.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function triggerSendout()
+ {
+ $this->post($this->getLocation() . '/trigger-send-out')
+ ->status('204');
+
+ return $this;
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Order.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Order.php
new file mode 100644
index 0000000..a13dfcb
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/OrderManagement/Order.php
@@ -0,0 +1,317 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the Order class.
+ */
+
+namespace Klarna\Rest\OrderManagement;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Resource;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Order management resource.
+ *
+ * @example docs/examples/order/acknowledge_order.php
+ * @example docs/examples/order/cancel_order.php
+ * @example docs/examples/order/extend_authorization_time.php
+ * @example docs/examples/order/fetch_order.php
+ * @example docs/examples/order/fetch_capture.php
+ * @example docs/examples/order/refund_order.php
+ * @example docs/examples/order/release_remaining_authorization.php
+ * @example docs/examples/order/update_customer_details.php
+ * @example docs/examples/order/update_merchant_references.php
+ * @example docs/examples/order/update_order_lines.php
+ */
+class Order extends Resource
+{
+ /**
+ * {@inheritDoc}
+ */
+ const ID_FIELD = 'order_id';
+
+ /**
+ * {@inheritDoc}
+ */
+ public static $path = '/ordermanagement/v1/orders';
+
+ /**
+ * Constructs an order instance.
+ *
+ * @param Connector $connector HTTP transport connector
+ * @param string $orderId Order ID
+ */
+ public function __construct(Connector $connector, $orderId)
+ {
+ parent::__construct($connector);
+
+ $this->setLocation(self::$path . "/{$orderId}");
+ $this[static::ID_FIELD] = $orderId;
+ }
+
+ /**
+ * Fetches the order.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException On an unexpected API response
+ * @throws \RuntimeException If the response content type is not JSON
+ * @throws \InvalidArgumentException If the JSON cannot be parsed
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function fetch()
+ {
+ parent::fetch();
+
+ // Convert captures data to Capture[]
+
+ $captures = [];
+ foreach ($this['captures'] as $capture) {
+ $captureId = $capture[Capture::ID_FIELD];
+
+ $object = new Capture(
+ $this->connector,
+ $this->getLocation(),
+ $captureId
+ );
+ $object->exchangeArray($capture);
+
+ $captures[] = $object;
+ }
+
+ $this['captures'] = $captures;
+
+ return $this;
+ }
+
+ /**
+ * Acknowledges the order.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function acknowledge()
+ {
+ $this->post($this->getLocation() . '/acknowledge')
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Cancels this order.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function cancel()
+ {
+ $this->post($this->getLocation() . '/cancel')
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Updates the authorization data.
+ *
+ * @param array $data Authorization data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function updateAuthorization(array $data)
+ {
+ $this->patch($this->getLocation() . '/authorization', $data)
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Extends the authorization time.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function extendAuthorizationTime()
+ {
+ $this->post($this->getLocation() . '/extend-authorization-time')
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Update the merchant references.
+ *
+ * @param array $data Merchant references
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function updateMerchantReferences(array $data)
+ {
+ $this->patch($this->getLocation() . '/merchant-references', $data)
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Updates the customer details.
+ *
+ * @param array $data Customer data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function updateCustomerDetails(array $data)
+ {
+ $this->patch($this->getLocation() . '/customer-details', $data)
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Refunds an amount of a captured order.
+ *
+ * @param array $data Refund data
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function refund(array $data)
+ {
+ $this->post($this->getLocation() . '/refunds', $data)
+ ->status(['201', '204']);
+
+ return $this;
+ }
+
+ /**
+ * Release the remaining authorization for an order.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function releaseRemainingAuthorization()
+ {
+ $this->post($this->getLocation() . '/release-remaining-authorization')
+ ->status('204');
+
+ return $this;
+ }
+
+ /**
+ * Capture all or part of an order.
+ *
+ * @param array $data Capture data
+ *
+ * @see Capture::create() For more information on how to create a capture
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException If the location header is missing
+ * @throws \RuntimeException If the API replies with an unexpected response
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return Capture
+ */
+ public function createCapture(array $data)
+ {
+ $capture = new Capture($this->connector, $this->getLocation());
+
+ $capture->create($data);
+
+ $this['captures'][] = $capture;
+
+ return $capture;
+ }
+
+ /**
+ * Fetches the specified capture.
+ *
+ * @param string $captureId Capture ID
+ *
+ * @see Capture::fetch() For more information on how to fetch a capture
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException On an unexpected API response
+ * @throws \RuntimeException If the response content type is not JSON
+ * @throws \InvalidArgumentException If the JSON cannot be parsed
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return Capture
+ */
+ public function fetchCapture($captureId)
+ {
+ if ($this->offsetExists('captures')) {
+ foreach ($this['captures'] as $capture) {
+ if ($capture->getId() !== $captureId) {
+ continue;
+ }
+
+ return $capture->fetch();
+ }
+ }
+
+ $capture = new Capture($this->connector, $this->getLocation(), $captureId);
+ $capture->fetch();
+
+ $this['captures'][] = $capture;
+
+ return $capture;
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Resource.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Resource.php
new file mode 100644
index 0000000..f1f96ce
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Resource.php
@@ -0,0 +1,200 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the abstract base resource class.
+ */
+
+namespace Klarna\Rest;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+use Klarna\Rest\Transport\ResponseValidator;
+
+/**
+ * Abstract resource class.
+ */
+abstract class Resource extends \ArrayObject
+{
+ /**
+ * Id property field name.
+ */
+ const ID_FIELD = 'id';
+
+ /**
+ * Path to the resource endpoint.
+ *
+ * @var string
+ */
+ public static $path;
+
+ /**
+ * HTTP transport connector instance.
+ *
+ * @var Connector
+ */
+ protected $connector;
+
+ /**
+ * Url to the resource.
+ *
+ * @var string
+ */
+ protected $url;
+
+ /**
+ * Constructs a resource instance.
+ *
+ * @param Connector $connector HTTP transport instance.
+ */
+ public function __construct(Connector $connector)
+ {
+ $this->connector = $connector;
+ }
+
+ /**
+ * Gets the resource id.
+ *
+ * @return string|null
+ */
+ public function getId()
+ {
+ return isset($this[static::ID_FIELD]) ? $this[static::ID_FIELD] : null;
+ }
+
+ /**
+ * Gets the resource location.
+ *
+ * @return string|null
+ */
+ public function getLocation()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Sets the resource location.
+ *
+ * @param string $url Url to the resource
+ *
+ * @return self
+ */
+ public function setLocation($url)
+ {
+ $this->url = $url;
+
+ return $this;
+ }
+
+ /**
+ * Fetches the resource.
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \RuntimeException On an unexpected API response
+ * @throws \RuntimeException If the response content type is not JSON
+ * @throws \InvalidArgumentException If the JSON cannot be parsed
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return self
+ */
+ public function fetch()
+ {
+ $data = $this->get($this->getLocation())
+ ->status('200')
+ ->contentType('application/json')
+ ->getJson();
+
+ $this->exchangeArray($data);
+
+ return $this;
+ }
+
+ /**
+ * Sends a HTTP request to the specified url.
+ *
+ * @param string $method HTTP method, e.g. 'GET'
+ * @param string $url Request destination
+ * @param array $options Request options
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return ResponseValidator
+ */
+ protected function request($method, $url, array $options = [])
+ {
+ $request = $this->connector->createRequest($url, $method, $options);
+
+ return new ResponseValidator($this->connector->send($request));
+ }
+
+ /**
+ * Sends a HTTP GET request to the specified url.
+ *
+ * @param string $url Request destination
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return ResponseValidator
+ */
+ protected function get($url)
+ {
+ return $this->request('GET', $url);
+ }
+
+ /**
+ * Sends a HTTP PATCH request to the specified url.
+ *
+ * @param string $url Request destination
+ * @param array $data Data to be JSON encoded
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return ResponseValidator
+ */
+ protected function patch($url, array $data)
+ {
+ return $this->request('PATCH', $url, ['json' => $data]);
+ }
+
+ /**
+ * Sends a HTTP POST request to the specified url.
+ *
+ * @param string $url Request destination
+ * @param array $data Data to be JSON encoded
+ *
+ * @throws ConnectorException When the API replies with an error response
+ * @throws RequestException When an error is encountered
+ * @throws \LogicException When Guzzle cannot populate the response
+ *
+ * @return ResponseValidator
+ */
+ protected function post($url, array $data = null)
+ {
+ $options = [];
+ if ($data !== null) {
+ $options['json'] = $data;
+ }
+
+ return $this->request('POST', $url, $options);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Connector.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Connector.php
new file mode 100644
index 0000000..8a7ebd4
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Connector.php
@@ -0,0 +1,186 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the Connector class.
+ */
+
+namespace Klarna\Rest\Transport;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Transport connector used to authenticate and make HTTP requests against the
+ * Klarna APIs.
+ */
+class Connector implements ConnectorInterface
+{
+ /**
+ * HTTP transport client.
+ *
+ * @var ClientInterface
+ */
+ protected $client;
+
+ /**
+ * Merchant ID.
+ *
+ * @var string
+ */
+ protected $merchantId;
+
+ /**
+ * Shared secret.
+ *
+ * @var string
+ */
+ protected $sharedSecret;
+
+ /**
+ * HTTP user agent.
+ *
+ * @var UserAgent
+ */
+ protected $userAgent;
+
+ /**
+ * Constructs a connector instance.
+ *
+ * Example usage:
+ *
+ * $client = new \GuzzleHttp\Client(['base_url' => 'https://api.klarna.com']);
+ * $connector = new \Klarna\Transport\Connector($client, '0', 'sharedSecret');
+ *
+ *
+ * @param ClientInterface $client HTTP transport client
+ * @param string $merchantId Merchant ID
+ * @param string $sharedSecret Shared secret
+ * @param UserAgentInterface $userAgent HTTP user agent to identify the client
+ */
+ public function __construct(
+ ClientInterface $client,
+ $merchantId,
+ $sharedSecret,
+ UserAgentInterface $userAgent = null
+ ) {
+ $this->client = $client;
+ $this->merchantId = $merchantId;
+ $this->sharedSecret = $sharedSecret;
+
+ if ($userAgent === null) {
+ $userAgent = UserAgent::createDefault();
+ }
+ $this->userAgent = $userAgent;
+ }
+
+ /**
+ * Creates a request object.
+ *
+ * @param string $url URL
+ * @param string $method HTTP method
+ * @param array $options Request options
+ *
+ * @return RequestInterface
+ */
+ public function createRequest($url, $method = 'GET', array $options = [])
+ {
+ $options['auth'] = [$this->merchantId, $this->sharedSecret];
+ $options['headers']['User-Agent'] = strval($this->userAgent);
+
+ return $this->client->createRequest($method, $url, $options);
+ }
+
+ /**
+ * Sends the request.
+ *
+ * @param RequestInterface $request Request to send
+ *
+ * @throws ConnectorException If the API returned an error response
+ * @throws RequestException When an error is encountered
+ * @throws \LogicException When the adapter does not populate a response
+ *
+ * @return ResponseInterface
+ */
+ public function send(RequestInterface $request)
+ {
+ try {
+ return $this->client->send($request);
+ } catch (RequestException $e) {
+ if (!$e->hasResponse()) {
+ throw $e;
+ }
+
+ $response = $e->getResponse();
+
+ if ($response->getHeader('Content-Type') !== 'application/json') {
+ throw $e;
+ }
+
+ $data = $response->json();
+
+ if (!is_array($data) || !array_key_exists('error_code', $data)) {
+ throw $e;
+ }
+
+ throw new ConnectorException($data, $e);
+ }
+ }
+
+ /**
+ * Gets the HTTP transport client.
+ *
+ * @return ClientInterface
+ */
+ public function getClient()
+ {
+ return $this->client;
+ }
+
+ /**
+ * Gets the user agent.
+ *
+ * @return UserAgentInterface
+ */
+ public function getUserAgent()
+ {
+ return $this->userAgent;
+ }
+
+ /**
+ * Factory method to create a connector instance.
+ *
+ * @param string $merchantId Merchant ID
+ * @param string $sharedSecret Shared secret
+ * @param string $baseUrl Base URL for HTTP requests
+ * @param UserAgentInterface $userAgent HTTP user agent to identify the client
+ *
+ * @return self
+ */
+ public static function create(
+ $merchantId,
+ $sharedSecret,
+ $baseUrl = self::EU_BASE_URL,
+ UserAgentInterface $userAgent = null
+ ) {
+ $client = new Client(['base_url' => $baseUrl]);
+
+ return new static($client, $merchantId, $sharedSecret, $userAgent);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ConnectorInterface.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ConnectorInterface.php
new file mode 100644
index 0000000..4c625fd
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ConnectorInterface.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the Connector interface.
+ */
+
+namespace Klarna\Rest\Transport;
+
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Message\ResponseInterface;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * HTTP transport connector interface used to authenticate and make HTTP requests
+ * against the Klarna APIs.
+ *
+ * The HTTP communication is handled by
+ * {@link http://guzzle.readthedocs.org/en/guzzle4/ Guzzle}.
+ */
+interface ConnectorInterface
+{
+ /**
+ * API base URL for Europe.
+ */
+ const EU_BASE_URL = 'https://api.klarna.com';
+
+ /**
+ * Testing API base URL for Europe.
+ */
+ const EU_TEST_BASE_URL = 'https://api.playground.klarna.com';
+
+ /**
+ * API base URL for North America.
+ */
+ const NA_BASE_URL = 'https://api-na.klarna.com';
+
+ /**
+ * Testing API base URL for North America.
+ */
+ const NA_TEST_BASE_URL = 'https://api-na.playground.klarna.com';
+
+ /**
+ * Creates a request object.
+ *
+ * @param string $url URL
+ * @param string $method HTTP method
+ * @param array $options Request options
+ *
+ * @return RequestInterface
+ */
+ public function createRequest($url, $method = 'GET', array $options = []);
+
+ /**
+ * Sends the request.
+ *
+ * @param RequestInterface $request Request to send
+ *
+ * @throws ConnectorException If the API returned an error response
+ * @throws RequestException When an error is encountered
+ * @throws \LogicException When the adapter does not populate a response
+ *
+ * @return ResponseInterface
+ */
+ public function send(RequestInterface $request);
+
+ /**
+ * Gets the HTTP transport client.
+ *
+ * @return ClientInterface
+ */
+ public function getClient();
+
+ /**
+ * Gets the user agent.
+ *
+ * @return UserAgentInterface
+ */
+ public function getUserAgent();
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Exception/ConnectorException.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Exception/ConnectorException.php
new file mode 100644
index 0000000..aa52c1b
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/Exception/ConnectorException.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the ConnectorException class.
+ */
+
+namespace Klarna\Rest\Transport\Exception;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * ConnectorException is used to represent a API error response.
+ */
+class ConnectorException extends \RuntimeException
+{
+ /**
+ * API response error code.
+ *
+ * @var string
+ */
+ protected $errorCode;
+
+ /**
+ * API response error messages.
+ *
+ * @var string[]
+ */
+ protected $messages;
+
+ /**
+ * API response error correlation ID.
+ *
+ * @var string
+ */
+ protected $correlationId;
+
+ /**
+ * Constructs a connector exception instance.
+ *
+ * @param array $data Error data
+ * @param RequestException $prev Previous exception
+ */
+ public function __construct(
+ array $data,
+ RequestException $prev
+ ) {
+ $messages = implode(', ', $data['error_messages']);
+ $message = "{$data['error_code']}: {$messages} (#{$data['correlation_id']})";
+
+ parent::__construct($message, $prev->getCode(), $prev);
+
+ $this->errorCode = $data['error_code'];
+ $this->messages = $data['error_messages'];
+ $this->correlationId = $data['correlation_id'];
+ }
+
+ /**
+ * Gets the API error code for this exception.
+ *
+ * @return string
+ */
+ public function getErrorCode()
+ {
+ return $this->errorCode;
+ }
+
+ /**
+ * Gets the API error messages for this exception.
+ *
+ * @return array
+ */
+ public function getMessages()
+ {
+ return $this->messages;
+ }
+
+ /**
+ * Gets the API correlation ID for this exception.
+ *
+ * @return string
+ */
+ public function getCorrelationId()
+ {
+ return $this->correlationId;
+ }
+
+ /**
+ * Gets the HTTP response for this API error.
+ *
+ * @return ResponseInterface
+ */
+ public function getResponse()
+ {
+ return $this->getPrevious()->getResponse();
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ResponseValidator.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ResponseValidator.php
new file mode 100644
index 0000000..f318a1a
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/ResponseValidator.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the ResponseValidator class.
+ */
+
+namespace Klarna\Rest\Transport;
+
+use GuzzleHttp\Message\ResponseInterface;
+
+/**
+ * HTTP response validator helper class.
+ */
+class ResponseValidator
+{
+ /**
+ * HTTP response to validate against.
+ *
+ * @var ResponseInterface
+ */
+ protected $response;
+
+ /**
+ * Constructs a response validator instance.
+ *
+ * @param ResponseInterface $response Response to validate
+ */
+ public function __construct(ResponseInterface $response)
+ {
+ $this->response = $response;
+ }
+
+ /**
+ * Gets the response object.
+ *
+ * @return ResponseInterface
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ /**
+ * Asserts the HTTP response status code.
+ *
+ * @param string|string[] $status Expected status code(s)
+ *
+ * @throws \RuntimeException If status code does not match
+ *
+ * @return self
+ */
+ public function status($status)
+ {
+ $httpStatus = (string) $this->response->getStatusCode();
+ if (is_array($status) && !in_array($httpStatus, $status)) {
+ throw new \RuntimeException(
+ "Unexpected response status code: {$httpStatus}"
+ );
+ }
+
+ if (is_string($status) && $httpStatus !== $status) {
+ throw new \RuntimeException(
+ "Unexpected response status code: {$httpStatus}"
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Asserts the Content-Type header.
+ *
+ * @param string $mediaType Expected media type
+ *
+ * @throws \RuntimeException If Content-Type header is missing
+ * @throws \RuntimeException If Content-Type header does not match
+ *
+ * @return self
+ */
+ public function contentType($mediaType)
+ {
+ if (!$this->response->hasHeader('Content-Type')) {
+ throw new \RuntimeException('Response is missing a Content-Type header');
+ }
+
+ $contentType = $this->response->getHeader('Content-Type');
+ if ($contentType !== $mediaType) {
+ throw new \RuntimeException(
+ "Unexpected Content-Type header received: {$contentType}"
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the decoded JSON response.
+ *
+ * @throws \RuntimeException If the response body is not in JSON format
+ * @throws \InvalidArgumentException If the JSON cannot be parsed
+ *
+ * @return array
+ */
+ public function getJson()
+ {
+ return $this->response->json();
+ }
+
+ /**
+ * Gets the Location header.
+ *
+ * @throws \RuntimeException If the Location header is missing
+ *
+ * @return string
+ */
+ public function getLocation()
+ {
+ if (!$this->response->hasHeader('Location')) {
+ throw new \RuntimeException('Response is missing a Location header');
+ }
+
+ return $this->response->getHeader('Location');
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgent.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgent.php
new file mode 100644
index 0000000..2a1d30e
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgent.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the UserAgent class.
+ */
+
+namespace Klarna\Rest\Transport;
+
+use GuzzleHttp\ClientInterface;
+
+/**
+ * HTTP user agent.
+ */
+class UserAgent implements UserAgentInterface
+{
+ /**
+ * Name of the SDK
+ */
+ const NAME = 'Klarna.kco_rest_php';
+
+ /**
+ * Version of the SDK.
+ */
+ const VERSION = '2.2.0';
+
+ /**
+ * Components of the user agent.
+ *
+ * @var array
+ */
+ protected $fields;
+
+ /**
+ * Constructs a user agent instance.
+ */
+ public function __construct()
+ {
+ $this->fields = [];
+ }
+
+ /**
+ * Sets the specified field.
+ *
+ * @param string $key Component key, e.g. 'Language'
+ * @param string $name Component name, e.g. 'PHP'
+ * @param string $version Version identifier, e.g. '5.4.10'
+ * @param array $options Additional information
+ *
+ * @return self
+ */
+ public function setField($key, $name, $version = '', array $options = [])
+ {
+ $field = [
+ 'name' => $name
+ ];
+
+ if (!empty($version)) {
+ $field['version'] = $version;
+ }
+
+ if (!empty($options)) {
+ $field['options'] = $options;
+ }
+
+ $this->fields[$key] = $field;
+
+ return $this;
+ }
+
+ /**
+ * Serialises the user agent.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $parts = [];
+
+ foreach ($this->fields as $key => $value) {
+ $component = "{$key}/{$value['name']}";
+ if (!empty($value['version'])) {
+ $component .= "_{$value['version']}";
+ }
+
+ $parts[] = $component;
+
+ if (empty($value['options'])) {
+ continue;
+ }
+
+ $opts = implode('; ', $value['options']);
+ $parts[] = "({$opts})";
+ }
+
+ return implode(' ', $parts);
+ }
+
+ /**
+ * Creates the default user agent.
+ *
+ * @return self
+ */
+ public static function createDefault()
+ {
+ $agent = new static();
+
+ $options = ['Guzzle/' . ClientInterface::VERSION];
+ if (extension_loaded('curl')) {
+ $options[] = 'curl/' . curl_version()['version'];
+ }
+
+ return $agent
+ ->setField('Library', static::NAME, static::VERSION, $options)
+ ->setField('OS', php_uname('s'), php_uname('r'))
+ ->setField('Language', 'PHP', phpversion());
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgentInterface.php b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgentInterface.php
new file mode 100644
index 0000000..7707d00
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/src/Klarna/Rest/Transport/UserAgentInterface.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the UserAgent interface.
+ */
+
+namespace Klarna\Rest\Transport;
+
+/**
+ * The user agent is used to help identify the client and provide additional
+ * information when assistance is needed with troubleshooting.
+ *
+ * In addition to following the User Agent as specified by RFC 2616, section 14.43,
+ * there are a number of predefined fields which should be used when applicable:
+ *
+ * Library:
+ * Information about the SDK and version being used.
+ *
+ * Library/[Library name]_[version]
+ *
+ * Examples:
+ * Library/Klarna.SDK_1.0.0
+ *
+ *
+ * Language:
+ * This is used to indicate which programming language and version is being used.
+ *
+ * Language/[Language]_[version]
+ *
+ * Example:
+ * Language/PHP_5.5.9-1ubuntu4.4
+ *
+ *
+ * OS:
+ * Information on what operating system the merchant is using for their web server.
+ *
+ * OS/[Operating system]_[version and architecture]
+ *
+ * Examples:
+ * OS/Linux_3.13.5-101.fc19.x86_64
+ *
+ *
+ * Partner:
+ * This is used to indicate if the integration is done using a partner.
+ *
+ * Partner/[Partner name]
+ *
+ * Examples:
+ * Partner/ShopPartnerName
+ *
+ *
+ * Platform:
+ * Information about which e-commerce platform is used to integrate.
+ *
+ * Platform/[Platform name]_[version]
+ *
+ * Examples:
+ * Platform/Magento_1.2.3
+ * Platform/Opencart_1.5.6.4
+ *
+ *
+ * Module:
+ * Used in conjunction with platform to provide information about the platform
+ * plugin.
+ *
+ * Module/[Module name]_[version]
+ *
+ * Examples:
+ * Module/Klarna.Module_1.0.0
+ *
+ *
+ * Webserver:
+ * Information about the web server being used.
+ *
+ * Webserver/[Webserver name]_[version]
+ *
+ * Examples:
+ * Webserver/Apache_2.4.1
+ * Webserver/Nginx_1.7.6
+ * Webserver/IIS_7.5
+ *
+ *
+ * Each component is written as key and name separated by slash, optionally followed
+ * by an underscore and the version. After which, separated by space, additional
+ * information can be added using parenthesis where individual elements inside are
+ * separated by semi-colon.
+ *
+ * All of the component strings are then combined using space as the delimiter.
+ *
+ * Specifying SDK dependencies for the Library field could be achieved as follows:
+ * Library/Klarna.SDK_1.0.0 (Guzzle/4.2.2 ; curl/7.35.0)
+ *
+ * Full user agent example:
+ * Library/Klarna.SDK_1.0.0 Language/PHP_5.5.9 OS/Linux_3.13.5-101.fc19.x86_64
+ */
+interface UserAgentInterface
+{
+ /**
+ * Serialises the user agent.
+ *
+ * @return string
+ */
+ public function __toString();
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Component/Checkout/OrderTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Component/Checkout/OrderTest.php
new file mode 100644
index 0000000..3e85a16
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Component/Checkout/OrderTest.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Order class.
+ */
+
+namespace Klarna\Rest\Tests\Component\Checkout;
+
+use GuzzleHttp\Message\Response;
+use GuzzleHttp\Stream\Stream;
+use Klarna\Rest\Checkout\Order;
+use Klarna\Rest\Tests\Component\ResourceTestCase;
+use Klarna\Rest\Transport\Connector;
+
+/**
+ * Component test cases for the checkout order resource.
+ */
+class OrderTest extends ResourceTestCase
+{
+ /**
+ * Make sure that the request sent is correct and that the location is updated.
+ *
+ * @return void
+ */
+ public function testCreate()
+ {
+ $this->mock->addResponse(
+ new Response(201, ['Location' => 'http://somewhere/a-path'])
+ );
+
+ $order = new Order($this->connector);
+ $location = $order->create(['data' => 'goes here'])
+ ->getLocation();
+
+ $this->assertEquals('http://somewhere/a-path', $location);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals('/checkout/v3/orders', $request->getPath());
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"goes here"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct and that the updated data
+ * is accessible.
+ *
+ * @return void
+ */
+ public function testUpdate()
+ {
+ $json = <<<JSON
+{
+ "order_id": "0001",
+ "updated": "from json"
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $order = new Order($this->connector, '0001');
+ $order['updated'] = 'not from json';
+
+ $order->update(['data' => 'sent in']);
+
+ $this->assertEquals('from json', $order['updated']);
+ $this->assertEquals('0001', $order->getId());
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals('/checkout/v3/orders/0001', $request->getPath());
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent and retrieved data is correct.
+ *
+ * @return void
+ */
+ public function testFetch()
+ {
+ $json = <<<JSON
+{
+ "order_id": "0002",
+ "updated": "from json"
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $order = new Order($this->connector, '0002');
+ $order['updated'] = 'not from json';
+
+ $order->fetch();
+
+ $this->assertEquals('from json', $order['updated']);
+ $this->assertEquals('0002', $order->getId());
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('GET', $request->getMethod());
+ $this->assertEquals('/checkout/v3/orders/0002', $request->getPath());
+
+ $this->assertAuthorization($request);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/CaptureTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/CaptureTest.php
new file mode 100644
index 0000000..7b38d83
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/CaptureTest.php
@@ -0,0 +1,168 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Capture class.
+ */
+
+namespace Klarna\Rest\Tests\Component\OrderManagement;
+
+use GuzzleHttp\Message\Response;
+use GuzzleHttp\Stream\Stream;
+use Klarna\Rest\OrderManagement\Capture;
+use Klarna\Rest\Tests\Component\ResourceTestCase;
+use Klarna\Rest\Transport\Connector;
+
+/**
+ * Component test cases for the capture resource.
+ */
+class CaptureTest extends ResourceTestCase
+{
+ /**
+ * Make sure that the request sent and retrieved data is correct.
+ *
+ * @return void
+ */
+ public function testFetch()
+ {
+ $json = <<<JSON
+{
+ "capture_id": "1002",
+ "updated": "from json"
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $capture = new Capture($this->connector, '/path', '1002');
+ $capture['updated'] = 'not from json';
+
+ $capture->fetch();
+
+ $this->assertEquals('from json', $capture['updated']);
+ $this->assertEquals('1002', $capture->getId());
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('GET', $request->getMethod());
+ $this->assertEquals('/path/captures/1002', $request->getPath());
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct and that the location is updated
+ * when creating the capture.
+ *
+ * @return void
+ */
+ public function testCreate()
+ {
+ $this->mock->addResponse(
+ new Response(201, ['Location' => 'http://somewhere/a-path'])
+ );
+
+ $capture = new Capture($this->connector, '/path/to/order');
+ $location = $capture->create(['data' => 'goes here'])
+ ->getLocation();
+
+ $this->assertEquals('http://somewhere/a-path', $location);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals('/path/to/order/captures', $request->getPath());
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"goes here"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when appending shipping info.
+ *
+ * @return void
+ */
+ public function testAddShippingInfo()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $capture = new Capture($this->connector, '/order/0002', '1002');
+ $capture->addShippingInfo(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/order/0002/captures/1002/shipping-info',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when updating customer details.
+ *
+ * @return void
+ */
+ public function testUpdateCustomerDetails()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $capture = new Capture($this->connector, '/order/0002', '1002');
+ $capture->updateCustomerDetails(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('PATCH', $request->getMethod());
+ $this->assertEquals(
+ '/order/0002/captures/1002/customer-details',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when triggering a send-out.
+ *
+ * @return void
+ */
+ public function testTriggerSendout()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $capture = new Capture($this->connector, '/order/0002', '1002');
+ $capture->triggerSendout();
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/order/0002/captures/1002/trigger-send-out',
+ $request->getPath()
+ );
+
+ $this->assertAuthorization($request);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/OrderTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/OrderTest.php
new file mode 100644
index 0000000..711d8d8
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Component/OrderManagement/OrderTest.php
@@ -0,0 +1,451 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Order class.
+ */
+
+namespace Klarna\Rest\Tests\Component\OrderManagement;
+
+use GuzzleHttp\Message\Response;
+use GuzzleHttp\Stream\Stream;
+use Klarna\Rest\OrderManagement\Capture;
+use Klarna\Rest\OrderManagement\Order;
+use Klarna\Rest\Tests\Component\ResourceTestCase;
+use Klarna\Rest\Transport\Connector;
+
+/**
+ * Component test cases for the order resource.
+ */
+class OrderTest extends ResourceTestCase
+{
+ /**
+ * Make sure that the request sent and retrieved data is correct when fetching
+ * the order.
+ *
+ * @return void
+ */
+ public function testFetch()
+ {
+ $json = <<<JSON
+{
+ "order_id": "0002",
+ "updated": "from json",
+ "captures": [
+ {
+ "capture_id": "1002",
+ "test": "data"
+ }
+ ]
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $order = new Order($this->connector, '0002');
+ $order['updated'] = 'not from json';
+
+ $order->fetch();
+
+ $this->assertEquals('from json', $order['updated']);
+ $this->assertEquals('0002', $order->getId());
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('GET', $request->getMethod());
+ $this->assertEquals('/ordermanagement/v1/orders/0002', $request->getPath());
+
+ $this->assertAuthorization($request);
+
+ $capture = $order['captures'][0];
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals($capture->getId(), $capture['capture_id']);
+ $this->assertEquals('1002', $capture->getId());
+ $this->assertEquals('data', $capture['test']);
+ }
+
+ /**
+ * Make sure that the request sent is correct when acknowledging an order.
+ *
+ * @return void
+ */
+ public function testAcknowledge()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->acknowledge();
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/acknowledge',
+ $request->getPath()
+ );
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when cancelling an order.
+ *
+ * @return void
+ */
+ public function testCancel()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->cancel();
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/cancel',
+ $request->getPath()
+ );
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when extending authorization time.
+ *
+ * @return void
+ */
+ public function testExtendAuthorizationTime()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->extendAuthorizationTime();
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/extend-authorization-time',
+ $request->getPath()
+ );
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when releasing remaining
+ * authorization.
+ *
+ * @return void
+ */
+ public function testReleaseRemainingAuthorization()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->releaseRemainingAuthorization();
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/release-remaining-authorization',
+ $request->getPath()
+ );
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when updating authorization.
+ *
+ * @return void
+ */
+ public function testUpdateAuthorization()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->updateAuthorization(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('PATCH', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/authorization',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when updating merchant references.
+ *
+ * @return void
+ */
+ public function testUpdateMerchantReferences()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->updateMerchantReferences(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('PATCH', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/merchant-references',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when updating customer details.
+ *
+ * @return void
+ */
+ public function testUpdateCustomerDetails()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->updateCustomerDetails(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('PATCH', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/customer-details',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when performing a refund.
+ *
+ * @return void
+ */
+ public function testRefund()
+ {
+ $this->mock->addResponse(new Response(204));
+
+ $order = new Order($this->connector, '0002');
+ $order->refund(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/refunds',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct when performing a refund.
+ *
+ * @return void
+ */
+ public function testRefund201()
+ {
+ $this->mock->addResponse(new Response(201));
+
+ $order = new Order($this->connector, '0002');
+ $order->refund(['data' => 'sent in']);
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/refunds',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"sent in"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent is correct and that the location is updated
+ * when creating an order.
+ *
+ * @return void
+ */
+ public function testCreateCapture()
+ {
+ $this->mock->addResponse(
+ new Response(201, ['Location' => 'http://somewhere/a-path'])
+ );
+
+ $order = new Order($this->connector, '0002');
+ $capture = $order->createCapture(['data' => 'goes here']);
+
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals('http://somewhere/a-path', $capture->getLocation());
+
+ $request = $this->history->getLastRequest();
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/captures',
+ $request->getPath()
+ );
+
+ $this->assertEquals('application/json', $request->getHeader('Content-Type'));
+ $this->assertEquals('{"data":"goes here"}', strval($request->getBody()));
+
+ $this->assertAuthorization($request);
+ }
+
+ /**
+ * Make sure that the request sent and retrieved data is correct when fetching
+ * a capture.
+ *
+ * @return void
+ */
+ public function testFetchCapture()
+ {
+ $json = <<<JSON
+{
+ "capture_id": "1002",
+ "updated": "from json"
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $order = new Order($this->connector, '0002');
+
+ $capture = $order->fetchCapture('1002');
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/captures/1002',
+ $capture->getLocation()
+ );
+
+ $this->assertEquals('from json', $capture['updated']);
+ $this->assertEquals('1002', $capture->getId());
+ $this->assertEquals($capture->getId(), $capture['capture_id']);
+ }
+
+ /**
+ * Make sure that the request sent and retrieved data is correct when fetching
+ * a capture that exists in the captures list.
+ *
+ * @return void
+ */
+ public function testFetchCaptureExisting()
+ {
+ $json = <<<JSON
+{
+ "capture_id": "1002",
+ "updated": "from json"
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $order = new Order($this->connector, '0002');
+
+ $capture = new Capture($this->connector, $order->getLocation(), '1002');
+ $capture['capture_id'] = '1002';
+ $capture['updated'] = 'not from json';
+
+ $order['captures'][] = $capture;
+
+ $capture = $order->fetchCapture('1002');
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/captures/1002',
+ $capture->getLocation()
+ );
+
+ $this->assertEquals('from json', $capture['updated']);
+ $this->assertEquals('1002', $capture->getId());
+ $this->assertEquals($capture->getId(), $capture['capture_id']);
+ }
+
+ /**
+ * Make sure that the request sent and retrieved data is correct when fetching
+ * a capture that is not already in the captures list.
+ *
+ * @return void
+ */
+ public function testFetchCaptureNew()
+ {
+ $json = <<<JSON
+{
+ "capture_id": "1003",
+ "updated": "from json"
+}
+JSON;
+
+ $this->mock->addResponse(
+ new Response(
+ 200,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ )
+ );
+
+ $order = new Order($this->connector, '0002');
+
+ $capture = new Capture($this->connector, $order->getLocation(), '1002');
+ $capture['capture_id'] = '1002';
+ $capture['updated'] = 'not from json';
+
+ $order['captures'][] = $capture;
+
+ $capture = $order->fetchCapture('1003');
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals(
+ '/ordermanagement/v1/orders/0002/captures/1003',
+ $capture->getLocation()
+ );
+
+ $this->assertEquals('from json', $capture['updated']);
+ $this->assertEquals('1003', $capture->getId());
+ $this->assertEquals($capture->getId(), $capture['capture_id']);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Component/ResourceTestCase.php b/public/system/storage/vendor/klarna/kco_rest/tests/Component/ResourceTestCase.php
new file mode 100644
index 0000000..eb0b1ae
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Component/ResourceTestCase.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the resource base test case class.
+ */
+
+namespace Klarna\Rest\Tests\Component;
+
+use GuzzleHttp\Message\RequestInterface;
+
+/**
+ * Resource base test case class.
+ */
+abstract class ResourceTestCase extends TestCase
+{
+ /**
+ * Asserts that the authorization header is correct.
+ *
+ * @param RequestInterface $request Request to test
+ *
+ * @return void
+ */
+ protected function assertAuthorization(RequestInterface $request)
+ {
+ list($alg, $digest) = explode(' ', $request->getHeader('Authorization'));
+
+ $this->assertEquals('Basic', $alg);
+
+ $expected = self::MERCHANT_ID . ':' . self::SHARED_SECRET;
+ $this->assertEquals($expected, base64_decode($digest));
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Component/TestCase.php b/public/system/storage/vendor/klarna/kco_rest/tests/Component/TestCase.php
new file mode 100644
index 0000000..06c5151
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Component/TestCase.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the TestCase class.
+ */
+
+namespace Klarna\Rest\Tests\Component;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Subscriber\History;
+use GuzzleHttp\Subscriber\Mock;
+use Klarna\Rest\Transport\Connector;
+
+/**
+ * Base component test case class.
+ */
+class TestCase extends \PHPUnit_Framework_TestCase
+{
+ const MERCHANT_ID = '1234';
+
+ const SHARED_SECRET = 'MySecret';
+
+ const BASE_URL = 'http://base-url.internal.machines';
+
+ const PATH = '/test/url';
+
+ /**
+ * @var Client
+ */
+ protected $client;
+
+ /**
+ * @var Connector
+ */
+ protected $connector;
+
+ /**
+ * @var Mock
+ */
+ protected $mock;
+
+ /**
+ * @var History
+ */
+ protected $history;
+
+ /**
+ * Sets up the test fixtures.
+ */
+ protected function setUp()
+ {
+ $this->client = new Client();
+ $this->mock = new Mock();
+ $this->history = new History();
+
+ // Add the mock subscriber to the client.
+ $this->client->getEmitter()->attach($this->mock);
+ $this->client->getEmitter()->attach($this->history);
+
+ $this->connector = new Connector(
+ $this->client,
+ self::MERCHANT_ID,
+ self::SHARED_SECRET
+ );
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Component/Transport/ConnectorTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Component/Transport/ConnectorTest.php
new file mode 100644
index 0000000..7dbe72e
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Component/Transport/ConnectorTest.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Connector class.
+ */
+
+namespace Klarna\Rest\Tests\Component\Transport;
+
+use GuzzleHttp\Message\Response;
+use GuzzleHttp\Stream\Stream;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Tests\Component\TestCase;
+
+/**
+ * Component test cases for the connector class.
+ */
+class ConnectorTest extends TestCase
+{
+ /**
+ * Make sure the request is created properly.
+ *
+ * @return void
+ */
+ public function testCreateRequest()
+ {
+ $request = $this->connector->createRequest(
+ 'https://localhost:8888/path-here',
+ 'POST',
+ ['query' => ['q' => '1']]
+ );
+
+ $this->assertInstanceOf('GuzzleHttp\Message\RequestInterface', $request);
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals(
+ 'https://localhost:8888/path-here?q=1',
+ $request->getUrl()
+ );
+
+ $this->assertEquals(self::MERCHANT_ID, $request->getConfig()['auth'][0]);
+ $this->assertEquals(self::SHARED_SECRET, $request->getConfig()['auth'][1]);
+
+ $this->assertEquals(
+ strval($this->connector->getUserAgent()),
+ $request->getHeader('User-Agent')
+ );
+ }
+
+ /**
+ * Make sure that the request sent returns an response.
+ *
+ * @return void
+ */
+ public function testSend()
+ {
+ $response = new Response(200);
+ $this->mock->addResponse($response);
+
+ $request = $this->connector->createRequest('http://somewhere/path', 'POST');
+ $this->assertSame($response, $this->connector->send($request));
+ }
+
+ /**
+ * Make sure that an API error response throws a connector exception.
+ *
+ * @return void
+ */
+ public function testSendError()
+ {
+ $json = <<<JSON
+{
+ "error_code": "ERR_1",
+ "error_messages": [
+ "msg1",
+ "msg2"
+ ],
+ "correlation_id": "cid_1"
+}
+JSON;
+ $response = new Response(
+ 500,
+ ['Content-Type' => 'application/json'],
+ Stream::factory($json)
+ );
+ $this->mock->addResponse($response);
+
+ $this->setExpectedException(
+ 'Klarna\Rest\Transport\Exception\ConnectorException',
+ 'ERR_1: msg1, msg2 (#cid_1)'
+ );
+
+ $request = $this->connector->createRequest('http://somewhere/path', 'POST');
+ $this->connector->send($request);
+ }
+
+ /**
+ * Make sure that an error response throws an exception.
+ *
+ * @return void
+ */
+ public function testSendGuzzleError()
+ {
+ $response = new Response(404);
+ $this->mock->addResponse($response);
+
+ $this->setExpectedException('GuzzleHttp\Exception\ClientException');
+
+ $request = $this->connector->createRequest('http://somewhere/path', 'POST');
+ $this->connector->send($request);
+ }
+
+ /**
+ * Make sure that the factory method creates a connector as expected.
+ *
+ * @return void
+ */
+ public function testCreate()
+ {
+ $userAgent = $this->getMockBuilder('Klarna\Rest\Transport\UserAgent')
+ ->getMock();
+
+ $connector = Connector::create(
+ self::MERCHANT_ID,
+ self::SHARED_SECRET,
+ self::BASE_URL,
+ $userAgent
+ );
+
+ $this->assertSame($userAgent, $connector->getUserAgent());
+ $this->assertEquals(self::BASE_URL, $connector->getClient()->getBaseUrl());
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Checkout/OrderTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Checkout/OrderTest.php
new file mode 100644
index 0000000..5e32cbb
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Checkout/OrderTest.php
@@ -0,0 +1,418 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Order class.
+ */
+
+namespace Klarna\Tests\Unit\Rest\Checkout;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Checkout\Order;
+use Klarna\Rest\Tests\Unit\TestCase;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Unit test cases for the checkout order resource.
+ */
+class OrderTest extends TestCase
+{
+ /**
+ * Make sure the identifier is retrievable.
+ *
+ * @return void
+ */
+ public function testGetId()
+ {
+ $order = new Order($this->connector);
+ $this->assertNull($order->getId());
+
+ $order = new Order($this->connector, '12345');
+ $order['order_id'] = '12345';
+ $this->assertEquals('12345', $order->getId());
+ $this->assertEquals('/checkout/v3/orders/12345', $order->getLocation());
+ }
+
+ /**
+ * Make sure the correct data is sent and location is updated.
+ *
+ * @return void
+ */
+ public function testCreate()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/checkout/v3/orders',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('201'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Location')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Location')
+ ->will($this->returnValue('http://somewhere/a-path'));
+
+ $order = new Order($this->connector);
+ $location = $order->create($data)
+ ->getLocation();
+
+ $this->assertEquals('http://somewhere/a-path', $location);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testCreateInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector);
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 204'
+ );
+
+ $order->create(['data' => 'goes here']);
+ }
+
+ /**
+ * Make sure a missing location header in the response results in an exception.
+ *
+ * @return void
+ */
+ public function testCreateNoLocation()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('201'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Location')
+ ->will($this->returnValue(false));
+
+ $order = new Order($this->connector);
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Response is missing a Location header'
+ );
+
+ $order->create(['data' => 'goes here']);
+ }
+
+ /**
+ * Make sure the correct data is sent and that the replied data is accessible.
+ *
+ * @return void
+ */
+ public function testUpdate()
+ {
+ $updateData = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/checkout/v3/orders/12345',
+ 'POST',
+ ['json' => $updateData]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'data' => 'from response json',
+ 'order_id' => '12345'
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $order = new Order($this->connector, '12345');
+ $order['order_id'] = '12345';
+ $order['data'] = 'is overwritten';
+
+ $order->update($updateData);
+
+ $this->assertEquals('from response json', $order['data']);
+ $this->assertEquals('12345', $order->getId());
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testUpdateInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector);
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 204'
+ );
+
+ $order->update(['data' => 'goes here']);
+ }
+
+ /**
+ * Make sure a non-JSON response results in an exception.
+ *
+ * @return void
+ */
+ public function testUpdateNotJson()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('text/plain'));
+
+ $order = new Order($this->connector);
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected Content-Type header received: text/plain'
+ );
+
+ $order->update(['data' => 'goes here']);
+ }
+
+ /**
+ * Make sure fetched data is accessible.
+ *
+ * @return void
+ */
+ public function testFetch()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/checkout/v3/orders/12345',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'data' => 'from response json',
+ 'order_id' => '12345'
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $order = new Order($this->connector, '12345');
+ $order['data'] = 'is overwritten';
+
+ $order->fetch();
+
+ $this->assertEquals('from response json', $order['data']);
+ $this->assertEquals('12345', $order->getId());
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testFetchInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/checkout/v3/orders/12345',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order['data'] = 'is overwritten';
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 204'
+ );
+
+ $order->fetch();
+ }
+
+ /**
+ * Make sure a non-JSON response results in an exception.
+ *
+ * @return void
+ */
+ public function testFetchNotJson()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/checkout/v3/orders/12345',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('text/plain'));
+
+ $order = new Order($this->connector, '12345');
+ $order['data'] = 'is overwritten';
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected Content-Type header received: text/plain'
+ );
+
+ $order->fetch();
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/CaptureTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/CaptureTest.php
new file mode 100644
index 0000000..ff665d9
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/CaptureTest.php
@@ -0,0 +1,512 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Capture class.
+ */
+
+namespace Klarna\Tests\Unit\Rest\OrderManagement;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\OrderManagement\Capture;
+use Klarna\Rest\Tests\Unit\TestCase;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Unit test cases for the capture resource.
+ */
+class CaptureTest extends TestCase
+{
+ /**
+ * Make sure the location is correct for create method.
+ *
+ * @return void
+ */
+ public function testConstructorNew()
+ {
+ $capture = new Capture($this->connector, '/orders/1');
+ $this->assertEquals('/orders/1/captures', $capture->getLocation());
+ }
+
+ /**
+ * Make sure the location is correct for fetch method.
+ *
+ * @return void
+ */
+ public function testConstructorExisting()
+ {
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $this->assertEquals('/orders/1/captures/2', $capture->getLocation());
+ }
+
+ /**
+ * Make sure the identifier is retrievable.
+ *
+ * @return void
+ */
+ public function testGetId()
+ {
+ $capture = new Capture($this->connector, '/orders/12345');
+ $this->assertNull($capture->getId());
+
+ $capture = new Capture($this->connector, '/orders/12345', '2');
+ $this->assertEquals('2', $capture->getId());
+ }
+
+ /**
+ * Make sure fetched data is accessible.
+ *
+ * @return void
+ */
+ public function testFetch()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'data' => 'from response json',
+ 'capture_id' => '2'
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $capture['data'] = 'is overwritten';
+
+ $capture->fetch();
+
+ $this->assertEquals('from response json', $capture['data']);
+ $this->assertEquals('2', $capture->getId());
+ }
+
+ /**
+ * Make sure that an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testFetchInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $capture['data'] = 'is overwritten';
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 204'
+ );
+
+ $capture->fetch();
+ }
+
+ /**
+ * Make sure a non-JSON response results in an exception.
+ *
+ * @return void
+ */
+ public function testFetchNotJson()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('text/plain'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $capture['data'] = 'is overwritten';
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected Content-Type header received: text/plain'
+ );
+
+ $capture->fetch();
+ }
+
+ /**
+ * Make sure the correct data is sent and location is updated.
+ *
+ * @return void
+ */
+ public function testCreate()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('201'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Location')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Location')
+ ->will($this->returnValue('http://somewhere/a-path'));
+
+ $capture = new Capture($this->connector, '/orders/1');
+ $location = $capture->create($data)
+ ->getLocation();
+
+ $this->assertEquals('http://somewhere/a-path', $location);
+ }
+
+ /**
+ * Make sure that an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testCreateInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $capture = new Capture($this->connector, '/orders/1');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 204'
+ );
+
+ $capture->create(['data' => 'goes here']);
+ }
+
+ /**
+ * Make sure a missing location header in the response results in an exception.
+ *
+ * @return void
+ */
+ public function testCreateNoLocation()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('201'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Location')
+ ->will($this->returnValue(false));
+
+ $capture = new Capture($this->connector, '/orders/1');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Response is missing a Location header'
+ );
+
+ $capture->create(['data' => 'goes here']);
+ }
+
+ /**
+ * Make sure the correct data is sent.
+ *
+ * @return void
+ */
+ public function testAddShippingInfo()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2/shipping-info',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $capture->addShippingInfo($data);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testAddShippingInfoInvalidStatusCode()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2/shipping-info',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $capture->addShippingInfo($data);
+ }
+
+ /**
+ * Make sure the correct data is sent.
+ *
+ * @return void
+ */
+ public function testUpdateCustomerDetails()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2/customer-details',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $capture->updateCustomerDetails($data);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testUpdateCustomerDetailsInvalidStatusCode()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2/customer-details',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $capture->updateCustomerDetails($data);
+ }
+
+ /**
+ * Make sure that the correct request is sent.
+ *
+ * @return void
+ */
+ public function testTriggerSendout()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2/trigger-send-out',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+ $capture->triggerSendout();
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testTriggerSendoutInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/orders/1/captures/2/trigger-send-out',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $capture = new Capture($this->connector, '/orders/1', '2');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $capture->triggerSendout();
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/OrderTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/OrderTest.php
new file mode 100644
index 0000000..44de858
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/OrderManagement/OrderTest.php
@@ -0,0 +1,921 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Order class.
+ */
+
+namespace Klarna\Tests\Unit\Rest\OrderManagement;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\OrderManagement\Order;
+use Klarna\Rest\Tests\Unit\TestCase;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Unit test cases for the order resource.
+ */
+class OrderTest extends TestCase
+{
+ /**
+ * Make sure the identifier is retrievable.
+ *
+ * @return void
+ */
+ public function testGetId()
+ {
+ $order = new Order($this->connector, '12345');
+ $this->assertEquals('12345', $order->getId());
+ $this->assertEquals('/ordermanagement/v1/orders/12345', $order->getLocation());
+ }
+
+ /**
+ * Make sure fetched data is accessible.
+ *
+ * @return void
+ */
+ public function testFetch()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'data' => 'from response json',
+ 'order_id' => '12345',
+ 'captures' => [
+ [
+ 'capture_id' => '1002',
+ 'data' => 'also from json'
+ ],
+ [
+ 'capture_id' => '1003',
+ 'data' => 'something else'
+ ]
+ ]
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $order = new Order($this->connector, '12345');
+ $order['data'] = 'is overwritten';
+ $order['captures'][] = new \ArrayObject();
+
+ $order->fetch();
+
+ $this->assertEquals('from response json', $order['data']);
+ $this->assertEquals('12345', $order->getId());
+
+ $this->assertCount(2, $order['captures']);
+ $this->assertContainsOnlyInstancesOf(
+ 'Klarna\Rest\OrderManagement\Capture',
+ $order['captures']
+ );
+
+ $this->assertEquals('1002', $order['captures'][0]->getId());
+ $this->assertEquals('also from json', $order['captures'][0]['data']);
+ $this->assertEquals('1003', $order['captures'][1]->getId());
+ $this->assertEquals('something else', $order['captures'][1]['data']);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testFetchInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order['data'] = 'is overwritten';
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 204'
+ );
+
+ $order->fetch();
+ }
+
+ /**
+ * Make sure a non-JSON response results in an exception.
+ *
+ * @return void
+ */
+ public function testFetchNotJson()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('text/plain'));
+
+ $order = new Order($this->connector, '12345');
+ $order['data'] = 'is overwritten';
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected Content-Type header received: text/plain'
+ );
+
+ $order->fetch();
+ }
+
+ /**
+ * Make sure that the correct request is sent.
+ *
+ * @return void
+ */
+ public function testAcknowledge()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/acknowledge',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->acknowledge();
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testAcknowledgeInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/acknowledge',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->acknowledge();
+ }
+
+ /**
+ * Make sure that the correct request is sent.
+ *
+ * @return void
+ */
+ public function testCancel()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/cancel',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->cancel();
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testCancelInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/cancel',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->cancel();
+ }
+
+ /**
+ * Make sure the correct data is sent.
+ *
+ * @return void
+ */
+ public function testUpdateAuthorization()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/authorization',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->updateAuthorization($data);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testUpdateAuthorizationInvalidStatusCode()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/authorization',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->updateAuthorization($data);
+ }
+
+ /**
+ * Make sure that the correct request is sent.
+ *
+ * @return void
+ */
+ public function testExtendAuthorizationTime()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/extend-authorization-time',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->extendAuthorizationTime();
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testExtendAuthorizationTimeInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/extend-authorization-time',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->extendAuthorizationTime();
+ }
+
+ /**
+ * Make sure the correct data is sent.
+ *
+ * @return void
+ */
+ public function testUpdateMerchantReferences()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/merchant-references',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->updateMerchantReferences($data);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testUpdateMerchantReferencesInvalidStatusCode()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/merchant-references',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->updateMerchantReferences($data);
+ }
+
+ /**
+ * Make sure the correct data is sent.
+ *
+ * @return void
+ */
+ public function testUpdateCustomerDetails()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/customer-details',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->updateCustomerDetails($data);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testUpdateCustomerDetailsInvalidStatusCode()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/customer-details',
+ 'PATCH',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->updateCustomerDetails($data);
+ }
+
+ /**
+ * Make sure the correct data is sent.
+ *
+ * @return void
+ */
+ public function testRefund()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/refunds',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->refund($data);
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testRefundInvalidStatusCode()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/refunds',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->refund($data);
+ }
+
+ /**
+ * Make sure that the correct request is sent.
+ *
+ * @return void
+ */
+ public function testReleaseRemainingAuthorization()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/release-remaining-authorization',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $order = new Order($this->connector, '12345');
+ $order->releaseRemainingAuthorization();
+ }
+
+ /**
+ * Make sure an unknown status code response results in an exception.
+ *
+ * @return void
+ */
+ public function testReleaseRemainingAuthorizationInvalidStatusCode()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/release-remaining-authorization',
+ 'POST',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $order = new Order($this->connector, '12345');
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $order->releaseRemainingAuthorization();
+ }
+
+ /**
+ * Make sure that a capture is created properly.
+ *
+ * @return void
+ */
+ public function testCreateCapture()
+ {
+ $data = ['data' => 'goes here'];
+
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/captures',
+ 'POST',
+ ['json' => $data]
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('201'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Location')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Location')
+ ->will($this->returnValue('http://somewhere/a-path'));
+
+ $order = new Order($this->connector, '12345');
+ $capture = $order->createCapture($data);
+
+ $this->assertEquals('http://somewhere/a-path', $capture->getLocation());
+ }
+
+ /**
+ * Make sure that a capture is fetched.
+ *
+ * @return void
+ */
+ public function testFetchCapture()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/captures/2',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'data' => 'from response json',
+ 'capture_id' => '2'
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $order = new Order($this->connector, '12345');
+ $capture = $order->fetchCapture('2');
+
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals('from response json', $capture['data']);
+ }
+
+ /**
+ * Make sure that an existing capture is refreshed before returned.
+ *
+ * @return void
+ */
+ public function testFetchCaptureExisting()
+ {
+ $this->connector->expects($this->never())
+ ->method('createRequest');
+
+ $order = new Order($this->connector, '12345');
+
+ $order['captures'][] = $this->getMockBuilder('Klarna\Rest\OrderManagement\Capture')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $order['captures'][0]->expects($this->once())
+ ->method('getId')
+ ->will($this->returnValue('1'));
+
+ $order['captures'][0]->expects($this->never())
+ ->method('fetch');
+
+ $order['captures'][] = $this->getMockBuilder('Klarna\Rest\OrderManagement\Capture')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $order['captures'][1]->expects($this->once())
+ ->method('getId')
+ ->will($this->returnValue('2'));
+
+ $order['captures'][1]->expects($this->once())
+ ->method('fetch')
+ ->will($this->returnValue($order['captures'][1]));
+
+ $this->assertSame($order['captures'][1], $order->fetchCapture('2'));
+ }
+
+ /**
+ * Make sure that a new capture is fetched if it is not in the resource.
+ *
+ * @return void
+ */
+ public function testFetchCaptureNoCache()
+ {
+ $this->connector->expects($this->once())
+ ->method('createRequest')
+ ->with(
+ '/ordermanagement/v1/orders/12345/captures/2',
+ 'GET',
+ []
+ )
+ ->will($this->returnValue($this->request));
+
+ $this->connector->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'data' => 'from response json',
+ 'capture_id' => '2'
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $order = new Order($this->connector, '12345');
+ $order['captures'][] = $this->getMockBuilder('Klarna\Rest\OrderManagement\Capture')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $order['captures'][0]->expects($this->once())
+ ->method('getId')
+ ->will($this->returnValue('1'));
+
+ $capture = $order->fetchCapture('2');
+
+ $this->assertInstanceOf('Klarna\Rest\OrderManagement\Capture', $capture);
+ $this->assertEquals('from response json', $capture['data']);
+ $this->assertEquals('2', $capture->getId());
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/TestCase.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/TestCase.php
new file mode 100644
index 0000000..72fdab1
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/TestCase.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the TestCase class.
+ */
+
+namespace Klarna\Rest\Tests\Unit;
+
+/**
+ * Base unit test case class.
+ */
+class TestCase extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @var \GuzzleHttp\Message\RequestInterface
+ */
+ protected $response;
+
+ /**
+ * @var \GuzzleHttp\Message\ResponseInterface
+ */
+ protected $request;
+
+ /**
+ * @var \Klarna\Rest\Transport\Connector
+ */
+ protected $connector;
+
+ /**
+ * Sets up the test fixtures.
+ */
+ protected function setUp()
+ {
+ $this->request = $this->getMockBuilder('GuzzleHttp\Message\RequestInterface')
+ ->getMock();
+
+ $this->response = $this->getMockBuilder('GuzzleHttp\Message\ResponseInterface')
+ ->getMock();
+
+ $this->connector = $this->getMockBuilder('Klarna\Rest\Transport\Connector')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ConnectorTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ConnectorTest.php
new file mode 100644
index 0000000..cdba5d1
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ConnectorTest.php
@@ -0,0 +1,343 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the Connector class.
+ */
+
+namespace Klarna\Rest\Tests\Unit\Transport;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Tests\Unit\TestCase;
+use Klarna\Rest\Transport\Connector;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Unit test cases for the connector class.
+ */
+class ConnectorTest extends TestCase
+{
+ const MERCHANT_ID = '1234';
+
+ const SHARED_SECRET = 'MySecret';
+
+ const BASE_URL = 'http://base-url.internal.machines';
+
+ const PATH = '/test/url';
+
+ /**
+ * @var Connector
+ */
+ protected $object;
+
+ /**
+ * @var \GuzzleHttp\ClientInterface
+ */
+ protected $client;
+
+ /**
+ * @var \Klarna\Rest\Transport\UserAgentInterface
+ */
+ protected $userAgent;
+
+ /**
+ * Set up the test fixtures.
+ */
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->client = $this->getMockBuilder('GuzzleHttp\ClientInterface')
+ ->getMock();
+
+ $this->userAgent = $this->getMockBuilder('Klarna\Rest\Transport\UserAgent')
+ ->getMock();
+
+ $this->userAgent->expects($this->any())
+ ->method('__toString')
+ ->will($this->returnValue('a-user-agent'));
+
+ $this->object = new Connector(
+ $this->client,
+ self::MERCHANT_ID,
+ self::SHARED_SECRET,
+ $this->userAgent
+ );
+ }
+
+ /**
+ * Make sure that the request is created as intended.
+ *
+ * @return void
+ */
+ public function testCreateRequest()
+ {
+ $options = [
+ 'opt' => 'val',
+ 'auth' => [self::MERCHANT_ID, self::SHARED_SECRET],
+ 'headers' => ['User-Agent' => 'a-user-agent']
+ ];
+
+ $this->client->expects($this->any())
+ ->method('createRequest')
+ ->with('uri', 'method', $options)
+ ->will($this->returnValue($this->request));
+
+ $request = $this->object->createRequest('method', 'uri', ['opt' => 'val']);
+ $this->assertSame($this->request, $request);
+ }
+
+ /**
+ * Make sure that the request is sent and a response is returned.
+ *
+ * @return void
+ */
+ public function testSend()
+ {
+ $this->client->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->returnValue($this->response));
+
+ $response = $this->object->send($this->request);
+
+ $this->assertSame($this->response, $response);
+ }
+
+ /**
+ * Make sure that an exception without a response is re-thrown.
+ *
+ * @return void
+ */
+ public function testSendRequestException()
+ {
+ $exception = new RequestException(
+ 'Something went terribly wrong',
+ $this->request
+ );
+
+ $this->client->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->throwException($exception));
+
+ $this->setExpectedException(
+ 'GuzzleHttp\Exception\RequestException',
+ 'Something went terribly wrong'
+ );
+
+ $this->object->send($this->request);
+ }
+
+ /**
+ * Make sure that an exception without a JSON response is re-thrown.
+ *
+ * @return void
+ */
+ public function testSendConnectorExceptionNoJson()
+ {
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(''));
+
+ $exception = new RequestException(
+ 'Something went terribly wrong',
+ $this->request,
+ $this->response
+ );
+
+ $this->client->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->throwException($exception));
+
+ $this->setExpectedException(
+ 'GuzzleHttp\Exception\RequestException',
+ 'Something went terribly wrong'
+ );
+
+ $this->object->send($this->request);
+ }
+
+ /**
+ * Make sure that an exception without data but with json content-type is
+ * re-thrown.
+ *
+ * @return void
+ */
+ public function testSendConnectorExceptionEmptyJson()
+ {
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $exception = new RequestException(
+ 'Something went terribly wrong',
+ $this->request,
+ $this->response
+ );
+
+ $this->client->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->throwException($exception));
+
+ $this->setExpectedException(
+ 'GuzzleHttp\Exception\RequestException',
+ 'Something went terribly wrong'
+ );
+
+ $this->object->send($this->request);
+ }
+
+ /**
+ * Make sure that an exception without a proper JSON response is re-thrown.
+ *
+ * @return void
+ */
+ public function testSendConnectorExceptionMissingFields()
+ {
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $exception = new RequestException(
+ 'Something went terribly wrong',
+ $this->request,
+ $this->response
+ );
+
+ $this->client->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->throwException($exception));
+
+ $this->setExpectedException(
+ 'GuzzleHttp\Exception\RequestException',
+ 'Something went terribly wrong'
+ );
+
+ $this->object->send($this->request);
+ }
+
+ /**
+ * Make sure that an exception with a error response is wrapped properly.
+ *
+ * @return void
+ */
+ public function testSendConnectorException()
+ {
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('application/json'));
+
+ $data = [
+ 'error_code' => 'ERROR_CODE_1',
+ 'error_messages' => [
+ 'Oh dear...',
+ 'Oh no...'
+ ],
+ 'correlation_id' => 'corr_id_1'
+ ];
+
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue($data));
+
+ $exception = new RequestException(
+ 'Something went terribly wrong',
+ $this->request,
+ $this->response
+ );
+
+ $this->client->expects($this->once())
+ ->method('send')
+ ->with($this->request)
+ ->will($this->throwException($exception));
+
+ $this->setExpectedException(
+ 'Klarna\Rest\Transport\Exception\ConnectorException',
+ 'ERROR_CODE_1: Oh dear..., Oh no... (#corr_id_1)'
+ );
+
+ $this->object->send($this->request);
+ }
+
+ /**
+ * Make sure that the factory method creates a connector properly.
+ *
+ * @return void
+ */
+ public function testCreate()
+ {
+ $connector = Connector::create(
+ self::MERCHANT_ID,
+ self::SHARED_SECRET,
+ self::BASE_URL,
+ $this->userAgent
+ );
+
+ $client = $connector->getClient();
+ $this->assertInstanceOf('GuzzleHttp\ClientInterface', $client);
+
+ $this->assertEquals(self::BASE_URL, $client->getBaseUrl());
+
+ $userAgent = $connector->getUserAgent();
+
+ $this->assertSame($this->userAgent, $userAgent);
+ $this->assertEquals('a-user-agent', strval($userAgent));
+ }
+
+ /**
+ * Make sure that the factory method uses the default user agent.
+ *
+ * @return void
+ */
+ public function testCreateDefaultUserAgent()
+ {
+ $connector = Connector::create(
+ self::MERCHANT_ID,
+ self::SHARED_SECRET,
+ self::BASE_URL
+ );
+
+ $userAgent = $connector->getUserAgent();
+ $this->assertInstanceOf('Klarna\Rest\Transport\UserAgent', $userAgent);
+ $this->assertContains('Library/Klarna.kco_rest_php', strval($userAgent));
+ }
+
+ /**
+ * Make sure that the client is retrievable.
+ *
+ * @return void
+ */
+ public function testGetClient()
+ {
+ $client = $this->object->getClient();
+
+ $this->assertInstanceOf('GuzzleHttp\ClientInterface', $client);
+ $this->assertSame($this->client, $client);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/Exception/ConnectorExceptionTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/Exception/ConnectorExceptionTest.php
new file mode 100644
index 0000000..11163fc
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/Exception/ConnectorExceptionTest.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the ConnectorException class.
+ */
+
+namespace Klarna\Rest\Tests\Unit\Transport\Exception;
+
+use GuzzleHttp\Exception\RequestException;
+use Klarna\Rest\Transport\Exception\ConnectorException;
+
+/**
+ * Unit test cases for the ConnectorException.
+ */
+class ConnectorExceptionTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * Make sure the getters work as intended.
+ *
+ * @return void
+ */
+ public function testGetters()
+ {
+ $data = [
+ 'error_code' => 'ERROR_CODE_1',
+ 'error_messages' => [
+ 'Oh dear...',
+ 'Oh no...'
+ ],
+ 'correlation_id' => 'corr_id_1'
+ ];
+
+ $request = $this->getMockBuilder('GuzzleHttp\Message\RequestInterface')
+ ->getMock();
+ $response = $this->getMockBuilder('GuzzleHttp\Message\ResponseInterface')
+ ->getMock();
+
+ $response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('500'));
+
+ $previous = new RequestException('Error', $request, $response);
+
+ $exception = new ConnectorException($data, $previous);
+
+ $this->assertEquals(500, $exception->getCode());
+ $this->assertSame($response, $exception->getResponse());
+
+ $this->assertContains(
+ $data['error_messages'][0],
+ $exception->getMessages()
+ );
+ $this->assertContains(
+ $data['error_messages'][1],
+ $exception->getMessages()
+ );
+
+ $this->assertEquals($data['error_code'], $exception->getErrorCode());
+ $this->assertEquals($data['correlation_id'], $exception->getCorrelationId());
+
+ $this->assertSame($previous, $exception->getPrevious());
+ $this->assertEquals(
+ 'ERROR_CODE_1: Oh dear..., Oh no... (#corr_id_1)',
+ $exception->getMessage()
+ );
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ResponseValidatorTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ResponseValidatorTest.php
new file mode 100644
index 0000000..09c4e78
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/ResponseValidatorTest.php
@@ -0,0 +1,249 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the ResponseValidator class.
+ */
+
+namespace Klarna\Rest\Tests\Unit\Transport;
+
+use Klarna\Rest\Transport\ResponseValidator;
+
+/**
+ * Unit test cases for the ResponseValidator class.
+ */
+class ResponseValidatorTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @var GuzzleHttp\Message\ResponseInterface
+ */
+ protected $response;
+
+ /**
+ * @var ResponseValidator
+ */
+ protected $validator;
+
+ /**
+ * Set up the test fixtures
+ */
+ protected function setUp()
+ {
+ $interface = 'GuzzleHttp\Message\ResponseInterface';
+ $this->response = $this->getMockBuilder($interface)
+ ->getMock();
+
+ $this->validator = new ResponseValidator($this->response);
+ }
+
+ /**
+ * Make sure the response is retrievable.
+ *
+ * @return void
+ */
+ public function testGetResponse()
+ {
+ $this->assertSame($this->response, $this->validator->getResponse());
+ }
+
+ /**
+ * Make sure that the JSON data is possible to retrieve.
+ *
+ * @return void
+ */
+ public function testGetJson()
+ {
+ $this->response->expects($this->once())
+ ->method('json')
+ ->will($this->returnValue('json response'));
+
+ $this->assertEquals('json response', $this->validator->getJson());
+ }
+
+ /**
+ * Make sure that the location header can be retrieved.
+ *
+ * @return void
+ */
+ public function testGetLocation()
+ {
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Location')
+ ->will($this->returnValue('a location'));
+
+ $this->assertEquals('a location', $this->validator->getLocation());
+ }
+
+ /**
+ * Make sure that a missing Location header throws an exception.
+ *
+ * @return void
+ */
+ public function testGetLocationException()
+ {
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Location')
+ ->will($this->returnValue(false));
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Response is missing a Location header'
+ );
+
+ $this->validator->getLocation();
+ }
+
+ /**
+ * Make sure that the content type is asserted properly.
+ *
+ * @return void
+ */
+ public function testContentType()
+ {
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('text/plain'));
+
+ $this->assertSame(
+ $this->validator,
+ $this->validator->contentType('text/plain')
+ );
+ }
+
+ /**
+ * Make sure that a missing Content-Type header throws an exception.
+ *
+ * @return void
+ */
+ public function testContentTypeMissingException()
+ {
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(false));
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Response is missing a Content-Type header'
+ );
+
+ $this->validator->contentType('text/plain');
+ }
+
+ /**
+ * Make sure that a different Content-Type header throws an exception.
+ *
+ * @return void
+ */
+ public function testContentTypeWrongException()
+ {
+ $this->response->expects($this->once())
+ ->method('hasHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue(true));
+
+ $this->response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->will($this->returnValue('text/plain'));
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected Content-Type header received: text/plain'
+ );
+
+ $this->validator->contentType('application/json');
+ }
+
+ /**
+ * Make sure that the status code is asserted properly.
+ *
+ * @return void
+ */
+ public function testStatus()
+ {
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->assertSame($this->validator, $this->validator->status('200'));
+ }
+
+ /**
+ * Make sure that multiple status codes are asserted properly.
+ *
+ * @return void
+ */
+ public function testStatuses()
+ {
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('204'));
+
+ $this->assertSame(
+ $this->validator,
+ $this->validator->status(['201', '204'])
+ );
+ }
+
+ /**
+ * Make sure that a different status code throws an exception.
+ *
+ * @return void
+ */
+ public function testStatusException()
+ {
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('201'));
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 201'
+ );
+
+ $this->validator->status('200');
+ }
+
+ /**
+ * Make sure that a different status code throws an exception.
+ *
+ * @return void
+ */
+ public function testStatusesException()
+ {
+ $this->response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue('200'));
+
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Unexpected response status code: 200'
+ );
+
+ $this->validator->status(['201', '204']);
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/UserAgentTest.php b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/UserAgentTest.php
new file mode 100644
index 0000000..b2e3903
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/Unit/Transport/UserAgentTest.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing tests for the UserAgent class.
+ */
+
+namespace Klarna\Rest\Tests\Unit\Transport;
+
+use Klarna\Rest\Transport\UserAgent;
+
+/**
+ * Unit test cases for the UserAgent class.
+ */
+class UserAgentTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @var UserAgent
+ */
+ protected $agent;
+
+ /**
+ * Set up the test fixtures
+ */
+ protected function setUp()
+ {
+ $this->agent = new UserAgent();
+ }
+
+ /**
+ * Make sure the default user agent components are present.
+ *
+ * @return void
+ */
+ public function testCreateDefault()
+ {
+ $agent = UserAgent::createDefault();
+ $text = $agent->__toString();
+
+ $this->assertContains(
+ 'Language/PHP_' . phpversion(),
+ $text,
+ 'No PHP language component present'
+ );
+
+ $this->assertContains(
+ 'OS/' . php_uname('s') . '_' . php_uname('r'),
+ $text,
+ 'No OS component present'
+ );
+
+ $this->assertContains(
+ 'Library/' . UserAgent::NAME . '_' . UserAgent::VERSION,
+ $text,
+ 'No Library component present',
+ false
+ );
+ }
+
+ /**
+ * Make sure the key and component are present in the user agent.
+ *
+ * @return void
+ */
+ public function testSetField()
+ {
+ $this->agent->setField('key', 'component');
+
+ $this->assertEquals('key/component', strval($this->agent));
+ }
+
+ /**
+ * Make sure the key, component and version are present.
+ *
+ * @return void
+ */
+ public function testSetFieldVersion()
+ {
+ $this->agent->setField('key', 'component', '1.0.0');
+
+ $this->assertEquals('key/component_1.0.0', strval($this->agent));
+ }
+
+ /**
+ * Make sure the key, component, version and options are present.
+ *
+ * @return void
+ */
+ public function testSetFieldOptions()
+ {
+ $this->agent->setField('key', 'component', '1.0.0', ['attr']);
+
+ $this->assertEquals(
+ 'key/component_1.0.0 (attr)',
+ strval($this->agent)
+ );
+ }
+
+ /**
+ * Make sure the key, component, version and multiple options are present.
+ *
+ * @return void
+ */
+ public function testSetFieldTwoOptions()
+ {
+ $this->agent->setField('key', 'component', '1.0.0', ['attr1', 'attr2']);
+
+ $this->assertEquals(
+ 'key/component_1.0.0 (attr1; attr2)',
+ strval($this->agent)
+ );
+ }
+}
diff --git a/public/system/storage/vendor/klarna/kco_rest/tests/bootstrap.php b/public/system/storage/vendor/klarna/kco_rest/tests/bootstrap.php
new file mode 100644
index 0000000..9065528
--- /dev/null
+++ b/public/system/storage/vendor/klarna/kco_rest/tests/bootstrap.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright 2014 Klarna AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * File containing the test bootstrap script.
+ */
+
+$loader = require dirname(__DIR__) . '/vendor/autoload.php';
+$loader->addPsr4('Klarna\\Rest\\Tests\\', __DIR__.'/');
+
+date_default_timezone_set('UTC');
diff --git a/public/system/storage/vendor/leafo/scssphp/.gitignore b/public/system/storage/vendor/leafo/scssphp/.gitignore
new file mode 100644
index 0000000..04d6f4b
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/.gitignore
@@ -0,0 +1,5 @@
+/*.scss
+/*.css
+.sass-cache
+/sass/
+/compass/
diff --git a/public/system/storage/vendor/leafo/scssphp/.travis.yml b/public/system/storage/vendor/leafo/scssphp/.travis.yml
new file mode 100644
index 0000000..202aa77
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/.travis.yml
@@ -0,0 +1,7 @@
+language: php
+script: phpunit tests
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - hhvm
diff --git a/public/system/storage/vendor/leafo/scssphp/LICENSE.md b/public/system/storage/vendor/leafo/scssphp/LICENSE.md
new file mode 100644
index 0000000..7eced06
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/LICENSE.md
@@ -0,0 +1,660 @@
+For ease of distribution, scssphp is available under a dual license.
+You are free to pick which one suits your needs.
+
+* * *
+
+
+MIT LICENSE
+
+
+
+
+Copyright (c) 2012 Leaf Corcoran, http://leafo.net/scssphp
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+* * *
+
+
+GPL VERSION 3
+
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
diff --git a/public/system/storage/vendor/leafo/scssphp/Makefile b/public/system/storage/vendor/leafo/scssphp/Makefile
new file mode 100644
index 0000000..7b72c70
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/Makefile
@@ -0,0 +1,3 @@
+
+test:
+ phpunit --colors tests \ No newline at end of file
diff --git a/public/system/storage/vendor/leafo/scssphp/README.md b/public/system/storage/vendor/leafo/scssphp/README.md
new file mode 100644
index 0000000..d99e4db
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/README.md
@@ -0,0 +1,34 @@
+# scssphp v0.0.12
+### <http://leafo.net/scssphp>
+
+[![Build Status](https://secure.travis-ci.org/leafo/scssphp.png)](http://travis-ci.org/leafo/scssphp)
+
+`scssphp` is a compiler for SCSS written in PHP.
+
+It implements SCSS 3.2.12. It does not implement the SASS syntax, only the SCSS
+syntax.
+
+Checkout the homepage, <http://leafo.net/scssphp>, for directions on how to use.
+
+## Running Tests
+
+`scssphp` uses [PHPUnit](https://github.com/sebastianbergmann/phpunit) for testing.
+
+Run the following command from the root directory to run every test:
+
+ phpunit tests
+
+There are two kinds of tests in the `tests/` directory:
+
+* `ApiTest.php` contains various unit tests that test the PHP interface.
+* `ExceptionTest.php` contains unit tests that test for exceptions thrown by the parser and compiler.
+* `InputTest.php` compiles every `.scss` file in the `tests/inputs` directory
+ then compares to the respective `.css` file in the `tests/outputs` directory.
+
+When changing any of the tests in `tests/inputs`, the tests will most likely
+fail because the output has changed. Once you verify that the output is correct
+you can run the following command to rebuild all the tests:
+
+ BUILD=true phpunit tests
+
+This will compile all the tests, and save results into `tests/outputs`.
diff --git a/public/system/storage/vendor/leafo/scssphp/composer.json b/public/system/storage/vendor/leafo/scssphp/composer.json
new file mode 100644
index 0000000..face95d
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "leafo/scssphp",
+ "type": "library",
+ "description": "scssphp is a compiler for SCSS written in PHP.",
+ "homepage": "http://leafo.net/scssphp/",
+ "license": [
+ "MIT",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Leaf Corcoran",
+ "email": "leafot@gmail.com",
+ "homepage": "http://leafo.net"
+ }
+ ],
+ "autoload": {
+ "classmap": ["scss.inc.php"]
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "php": ">=5.3.0",
+ "phpunit/phpunit": "3.7.*"
+ },
+ "bin": ["pscss"]
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/package.sh b/public/system/storage/vendor/leafo/scssphp/package.sh
new file mode 100644
index 0000000..02a528d
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/package.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# creates tar.gz for current version
+
+TARGET_DIR="site/www/src"
+
+VERSION=`./pscss -v | sed -n 's/^v\(.*\)$/\1/p'`
+OUT_DIR="tmp/scssphp"
+TMP=`dirname $OUT_DIR`
+
+mkdir -p $OUT_DIR
+tar -c `git ls-files` | tar -C $OUT_DIR -x
+
+rm $OUT_DIR/.gitignore
+rm $OUT_DIR/package.sh
+rm $OUT_DIR/todo
+rm -r $OUT_DIR/site
+
+OUT_PATH="$TARGET_DIR/scssphp-$VERSION.tar.gz"
+tar -czf "$OUT_PATH" -C $TMP scssphp/
+echo "Wrote $OUT_PATH"
+
+rm -r $TMP
+
diff --git a/public/system/storage/vendor/leafo/scssphp/phpunit.xml.dist b/public/system/storage/vendor/leafo/scssphp/phpunit.xml.dist
new file mode 100644
index 0000000..d320697
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/phpunit.xml.dist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
+<phpunit
+ backupGlobals = "false"
+ backupStaticAttributes = "false"
+ strict = "false"
+ colors = "true"
+ convertErrorsToExceptions = "true"
+ convertNoticesToExceptions = "true"
+ convertWarningsToExceptions = "true"
+ processIsolation = "false"
+ stopOnFailure = "false"
+ syntaxCheck = "false">
+
+ <testsuites>
+ <testsuite name="Project Test Suite">
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>.</directory>
+ </whitelist>
+ </filter>
+
+</phpunit>
diff --git a/public/system/storage/vendor/leafo/scssphp/pscss b/public/system/storage/vendor/leafo/scssphp/pscss
new file mode 100644
index 0000000..97cbf95
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/pscss
@@ -0,0 +1,53 @@
+#!/usr/bin/env php
+<?php
+error_reporting(E_ALL);
+
+require "scss.inc.php";
+
+$opts = getopt('hvTf:', array('help', 'version'));
+
+function has() {
+ global $opts;
+ foreach (func_get_args() as $arg) {
+ if (isset($opts[$arg])) return true;
+ }
+ return false;
+}
+
+if (has("h", "help")) {
+ $exe = array_shift($argv);
+
+$HELP = <<<EOT
+Usage: $exe [options] < input-file
+
+Options include:
+
+ -h, --help Show this message
+ -v, --version Print the version
+ -f=format Set the output format
+ -T Dump formatted parse tree
+
+EOT;
+ exit($HELP);
+}
+
+if (has("v", "version")) {
+ exit(scssc::$VERSION . "\n");
+}
+
+$data = "";
+while (!feof(STDIN)) {
+ $data .= fread(STDIN, 8192);
+}
+
+if (has("T")) {
+ $parser = new scss_parser("STDIN");
+ print_r($parser->parse($data));
+ exit();
+}
+
+$scss = new scssc();
+if (has("f")) {
+ $scss->setFormatter($opts["f"]);
+}
+echo $scss->compile($data, "STDIN");
diff --git a/public/system/storage/vendor/leafo/scssphp/scss.inc.php b/public/system/storage/vendor/leafo/scssphp/scss.inc.php
new file mode 100644
index 0000000..4ec86fb
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/scss.inc.php
@@ -0,0 +1,4574 @@
+<?php
+/**
+ * SCSS compiler written in PHP
+ *
+ * @copyright 2012-2013 Leaf Corcoran
+ *
+ * @license http://opensource.org/licenses/gpl-license GPL-3.0
+ * @license http://opensource.org/licenses/MIT MIT
+ *
+ * @link http://leafo.net/scssphp
+ */
+
+/**
+ * The scss compiler and parser.
+ *
+ * Converting SCSS to CSS is a three stage process. The incoming file is parsed
+ * by `scss_parser` into a syntax tree, then it is compiled into another tree
+ * representing the CSS structure by `scssc`. The CSS tree is fed into a
+ * formatter, like `scss_formatter` which then outputs CSS as a string.
+ *
+ * During the first compile, all values are *reduced*, which means that their
+ * types are brought to the lowest form before being dump as strings. This
+ * handles math equations, variable dereferences, and the like.
+ *
+ * The `parse` function of `scssc` is the entry point.
+ *
+ * In summary:
+ *
+ * The `scssc` class creates an instance of the parser, feeds it SCSS code,
+ * then transforms the resulting tree to a CSS tree. This class also holds the
+ * evaluation context, such as all available mixins and variables at any given
+ * time.
+ *
+ * The `scss_parser` class is only concerned with parsing its input.
+ *
+ * The `scss_formatter` takes a CSS tree, and dumps it to a formatted string,
+ * handling things like indentation.
+ */
+
+/**
+ * SCSS compiler
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scssc {
+ static public $VERSION = 'v0.0.11';
+
+ static protected $operatorNames = array(
+ '+' => "add",
+ '-' => "sub",
+ '*' => "mul",
+ '/' => "div",
+ '%' => "mod",
+
+ '==' => "eq",
+ '!=' => "neq",
+ '<' => "lt",
+ '>' => "gt",
+
+ '<=' => "lte",
+ '>=' => "gte",
+ );
+
+ static protected $namespaces = array(
+ "special" => "%",
+ "mixin" => "@",
+ "function" => "^",
+ );
+
+ static protected $unitTable = array(
+ "in" => array(
+ "in" => 1,
+ "pt" => 72,
+ "pc" => 6,
+ "cm" => 2.54,
+ "mm" => 25.4,
+ "px" => 96,
+ )
+ );
+
+ static public $true = array("keyword", "true");
+ static public $false = array("keyword", "false");
+ static public $null = array("null");
+
+ static public $defaultValue = array("keyword", "");
+ static public $selfSelector = array("self");
+
+ protected $importPaths = array("");
+ protected $importCache = array();
+
+ protected $userFunctions = array();
+ protected $registeredVars = array();
+
+ protected $numberPrecision = 5;
+
+ protected $formatter = "scss_formatter_nested";
+
+ /**
+ * Compile scss
+ *
+ * @param string $code
+ * @param string $name
+ *
+ * @return string
+ */
+ public function compile($code, $name = null)
+ {
+ $this->indentLevel = -1;
+ $this->commentsSeen = array();
+ $this->extends = array();
+ $this->extendsMap = array();
+ $this->parsedFiles = array();
+ $this->env = null;
+ $this->scope = null;
+
+ $locale = setlocale(LC_NUMERIC, 0);
+ setlocale(LC_NUMERIC, "C");
+
+ $this->parser = new scss_parser($name);
+
+ $tree = $this->parser->parse($code);
+
+ $this->formatter = new $this->formatter();
+
+ $this->pushEnv($tree);
+ $this->injectVariables($this->registeredVars);
+ $this->compileRoot($tree);
+ $this->popEnv();
+
+ $out = $this->formatter->format($this->scope);
+
+ setlocale(LC_NUMERIC, $locale);
+
+ return $out;
+ }
+
+ protected function isSelfExtend($target, $origin) {
+ foreach ($origin as $sel) {
+ if (in_array($target, $sel)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected function pushExtends($target, $origin) {
+ if ($this->isSelfExtend($target, $origin)) {
+ return;
+ }
+
+ $i = count($this->extends);
+ $this->extends[] = array($target, $origin);
+
+ foreach ($target as $part) {
+ if (isset($this->extendsMap[$part])) {
+ $this->extendsMap[$part][] = $i;
+ } else {
+ $this->extendsMap[$part] = array($i);
+ }
+ }
+ }
+
+ protected function makeOutputBlock($type, $selectors = null) {
+ $out = new stdClass;
+ $out->type = $type;
+ $out->lines = array();
+ $out->children = array();
+ $out->parent = $this->scope;
+ $out->selectors = $selectors;
+ $out->depth = $this->env->depth;
+
+ return $out;
+ }
+
+ protected function matchExtendsSingle($single, &$outOrigin) {
+ $counts = array();
+ foreach ($single as $part) {
+ if (!is_string($part)) return false; // hmm
+
+ if (isset($this->extendsMap[$part])) {
+ foreach ($this->extendsMap[$part] as $idx) {
+ $counts[$idx] =
+ isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
+ }
+ }
+ }
+
+ $outOrigin = array();
+ $found = false;
+
+ foreach ($counts as $idx => $count) {
+ list($target, $origin) = $this->extends[$idx];
+
+ // check count
+ if ($count != count($target)) continue;
+
+ // check if target is subset of single
+ if (array_diff(array_intersect($single, $target), $target)) continue;
+
+ $rem = array_diff($single, $target);
+
+ foreach ($origin as $j => $new) {
+ // prevent infinite loop when target extends itself
+ foreach ($new as $new_selector) {
+ if (!array_diff($single, $new_selector)) {
+ continue 2;
+ }
+ }
+
+ $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
+ }
+
+ $outOrigin = array_merge($outOrigin, $origin);
+
+ $found = true;
+ }
+
+ return $found;
+ }
+
+ protected function combineSelectorSingle($base, $other) {
+ $tag = null;
+ $out = array();
+
+ foreach (array($base, $other) as $single) {
+ foreach ($single as $part) {
+ if (preg_match('/^[^\[.#:]/', $part)) {
+ $tag = $part;
+ } else {
+ $out[] = $part;
+ }
+ }
+ }
+
+ if ($tag) {
+ array_unshift($out, $tag);
+ }
+
+ return $out;
+ }
+
+ protected function matchExtends($selector, &$out, $from = 0, $initial=true) {
+ foreach ($selector as $i => $part) {
+ if ($i < $from) continue;
+
+ if ($this->matchExtendsSingle($part, $origin)) {
+ $before = array_slice($selector, 0, $i);
+ $after = array_slice($selector, $i + 1);
+
+ foreach ($origin as $new) {
+ $k = 0;
+
+ // remove shared parts
+ if ($initial) {
+ foreach ($before as $k => $val) {
+ if (!isset($new[$k]) || $val != $new[$k]) {
+ break;
+ }
+ }
+ }
+
+ $result = array_merge(
+ $before,
+ $k > 0 ? array_slice($new, $k) : $new,
+ $after);
+
+
+ if ($result == $selector) continue;
+ $out[] = $result;
+
+ // recursively check for more matches
+ $this->matchExtends($result, $out, $i, false);
+
+ // selector sequence merging
+ if (!empty($before) && count($new) > 1) {
+ $result2 = array_merge(
+ array_slice($new, 0, -1),
+ $k > 0 ? array_slice($before, $k) : $before,
+ array_slice($new, -1),
+ $after);
+
+ $out[] = $result2;
+ }
+ }
+ }
+ }
+ }
+
+ protected function flattenSelectors($block, $parentKey = null) {
+ if ($block->selectors) {
+ $selectors = array();
+ foreach ($block->selectors as $s) {
+ $selectors[] = $s;
+ if (!is_array($s)) continue;
+ // check extends
+ if (!empty($this->extendsMap)) {
+ $this->matchExtends($s, $selectors);
+ }
+ }
+
+ $block->selectors = array();
+ $placeholderSelector = false;
+ foreach ($selectors as $selector) {
+ if ($this->hasSelectorPlaceholder($selector)) {
+ $placeholderSelector = true;
+ continue;
+ }
+ $block->selectors[] = $this->compileSelector($selector);
+ }
+
+ if ($placeholderSelector && 0 == count($block->selectors) && null !== $parentKey) {
+ unset($block->parent->children[$parentKey]);
+ return;
+ }
+ }
+
+ foreach ($block->children as $key => $child) {
+ $this->flattenSelectors($child, $key);
+ }
+ }
+
+ protected function compileRoot($rootBlock)
+ {
+ $this->scope = $this->makeOutputBlock('root');
+
+ $this->compileChildren($rootBlock->children, $this->scope);
+ $this->flattenSelectors($this->scope);
+ }
+
+ protected function compileMedia($media) {
+ $this->pushEnv($media);
+
+ $mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
+
+ if (!empty($mediaQuery)) {
+
+ $this->scope = $this->makeOutputBlock("media", array($mediaQuery));
+
+ $parentScope = $this->mediaParent($this->scope);
+
+ $parentScope->children[] = $this->scope;
+
+ // top level properties in a media cause it to be wrapped
+ $needsWrap = false;
+ foreach ($media->children as $child) {
+ $type = $child[0];
+ if ($type !== 'block' && $type !== 'media' && $type !== 'directive') {
+ $needsWrap = true;
+ break;
+ }
+ }
+
+ if ($needsWrap) {
+ $wrapped = (object)array(
+ "selectors" => array(),
+ "children" => $media->children
+ );
+ $media->children = array(array("block", $wrapped));
+ }
+
+ $this->compileChildren($media->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ }
+
+ $this->popEnv();
+ }
+
+ protected function mediaParent($scope) {
+ while (!empty($scope->parent)) {
+ if (!empty($scope->type) && $scope->type != "media") {
+ break;
+ }
+ $scope = $scope->parent;
+ }
+
+ return $scope;
+ }
+
+ // TODO refactor compileNestedBlock and compileMedia into same thing
+ protected function compileNestedBlock($block, $selectors) {
+ $this->pushEnv($block);
+
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->parent->children[] = $this->scope;
+ $this->compileChildren($block->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ /**
+ * Recursively compiles a block.
+ *
+ * A block is analogous to a CSS block in most cases. A single SCSS document
+ * is encapsulated in a block when parsed, but it does not have parent tags
+ * so all of its children appear on the root level when compiled.
+ *
+ * Blocks are made up of selectors and children.
+ *
+ * The children of a block are just all the blocks that are defined within.
+ *
+ * Compiling the block involves pushing a fresh environment on the stack,
+ * and iterating through the props, compiling each one.
+ *
+ * @see scss::compileChild()
+ *
+ * @param \StdClass $block
+ */
+ protected function compileBlock($block) {
+ $env = $this->pushEnv($block);
+
+ $env->selectors =
+ array_map(array($this, "evalSelector"), $block->selectors);
+
+ $out = $this->makeOutputBlock(null, $this->multiplySelectors($env));
+ $this->scope->children[] = $out;
+ $this->compileChildren($block->children, $out);
+
+ $this->popEnv();
+ }
+
+ // joins together .classes and #ids
+ protected function flattenSelectorSingle($single) {
+ $joined = array();
+ foreach ($single as $part) {
+ if (empty($joined) ||
+ !is_string($part) ||
+ preg_match('/[\[.:#%]/', $part))
+ {
+ $joined[] = $part;
+ continue;
+ }
+
+ if (is_array(end($joined))) {
+ $joined[] = $part;
+ } else {
+ $joined[count($joined) - 1] .= $part;
+ }
+ }
+
+ return $joined;
+ }
+
+ // replaces all the interpolates
+ protected function evalSelector($selector) {
+ return array_map(array($this, "evalSelectorPart"), $selector);
+ }
+
+ protected function evalSelectorPart($piece) {
+ foreach ($piece as &$p) {
+ if (!is_array($p)) continue;
+
+ switch ($p[0]) {
+ case "interpolate":
+ $p = $this->compileValue($p);
+ break;
+ case "string":
+ $p = $this->compileValue($p);
+ break;
+ }
+ }
+
+ return $this->flattenSelectorSingle($piece);
+ }
+
+ // compiles to string
+ // self(&) should have been replaced by now
+ protected function compileSelector($selector) {
+ if (!is_array($selector)) return $selector; // media and the like
+
+ return implode(" ", array_map(
+ array($this, "compileSelectorPart"), $selector));
+ }
+
+ protected function compileSelectorPart($piece) {
+ foreach ($piece as &$p) {
+ if (!is_array($p)) continue;
+
+ switch ($p[0]) {
+ case "self":
+ $p = "&";
+ break;
+ default:
+ $p = $this->compileValue($p);
+ break;
+ }
+ }
+
+ return implode($piece);
+ }
+
+ protected function hasSelectorPlaceholder($selector)
+ {
+ if (!is_array($selector)) return false;
+
+ foreach ($selector as $parts) {
+ foreach ($parts as $part) {
+ if ('%' == $part[0]) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected function compileChildren($stms, $out) {
+ foreach ($stms as $stm) {
+ $ret = $this->compileChild($stm, $out);
+ if (isset($ret)) return $ret;
+ }
+ }
+
+ protected function compileMediaQuery($queryList) {
+ $out = "@media";
+ $first = true;
+ foreach ($queryList as $query){
+ $type = null;
+ $parts = array();
+ foreach ($query as $q) {
+ switch ($q[0]) {
+ case "mediaType":
+ if ($type) {
+ $type = $this->mergeMediaTypes($type, array_map(array($this, "compileValue"), array_slice($q, 1)));
+ if (empty($type)) { // merge failed
+ return null;
+ }
+ } else {
+ $type = array_map(array($this, "compileValue"), array_slice($q, 1));
+ }
+ break;
+ case "mediaExp":
+ if (isset($q[2])) {
+ $parts[] = "(". $this->compileValue($q[1]) . $this->formatter->assignSeparator . $this->compileValue($q[2]) . ")";
+ } else {
+ $parts[] = "(" . $this->compileValue($q[1]) . ")";
+ }
+ break;
+ }
+ }
+ if ($type) {
+ array_unshift($parts, implode(' ', array_filter($type)));
+ }
+ if (!empty($parts)) {
+ if ($first) {
+ $first = false;
+ $out .= " ";
+ } else {
+ $out .= $this->formatter->tagSeparator;
+ }
+ $out .= implode(" and ", $parts);
+ }
+ }
+ return $out;
+ }
+
+ protected function mergeMediaTypes($type1, $type2) {
+ if (empty($type1)) {
+ return $type2;
+ }
+ if (empty($type2)) {
+ return $type1;
+ }
+ $m1 = '';
+ $t1 = '';
+ if (count($type1) > 1) {
+ $m1= strtolower($type1[0]);
+ $t1= strtolower($type1[1]);
+ } else {
+ $t1 = strtolower($type1[0]);
+ }
+ $m2 = '';
+ $t2 = '';
+ if (count($type2) > 1) {
+ $m2 = strtolower($type2[0]);
+ $t2 = strtolower($type2[1]);
+ } else {
+ $t2 = strtolower($type2[0]);
+ }
+ if (($m1 == 'not') ^ ($m2 == 'not')) {
+ if ($t1 == $t2) {
+ return null;
+ }
+ return array(
+ $m1 == 'not' ? $m2 : $m1,
+ $m1 == 'not' ? $t2 : $t1
+ );
+ } elseif ($m1 == 'not' && $m2 == 'not') {
+ # CSS has no way of representing "neither screen nor print"
+ if ($t1 != $t2) {
+ return null;
+ }
+ return array('not', $t1);
+ } elseif ($t1 != $t2) {
+ return null;
+ } else { // t1 == t2, neither m1 nor m2 are "not"
+ return array(empty($m1)? $m2 : $m1, $t1);
+ }
+ }
+
+ // returns true if the value was something that could be imported
+ protected function compileImport($rawPath, $out) {
+ if ($rawPath[0] == "string") {
+ $path = $this->compileStringContent($rawPath);
+ if ($path = $this->findImport($path)) {
+ $this->importFile($path, $out);
+ return true;
+ }
+ return false;
+ }
+ if ($rawPath[0] == "list") {
+ // handle a list of strings
+ if (count($rawPath[2]) == 0) return false;
+ foreach ($rawPath[2] as $path) {
+ if ($path[0] != "string") return false;
+ }
+
+ foreach ($rawPath[2] as $path) {
+ $this->compileImport($path, $out);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // return a value to halt execution
+ protected function compileChild($child, $out) {
+ $this->sourcePos = isset($child[-1]) ? $child[-1] : -1;
+ $this->sourceParser = isset($child[-2]) ? $child[-2] : $this->parser;
+
+ switch ($child[0]) {
+ case "import":
+ list(,$rawPath) = $child;
+ $rawPath = $this->reduce($rawPath);
+ if (!$this->compileImport($rawPath, $out)) {
+ $out->lines[] = "@import " . $this->compileValue($rawPath) . ";";
+ }
+ break;
+ case "directive":
+ list(, $directive) = $child;
+ $s = "@" . $directive->name;
+ if (!empty($directive->value)) {
+ $s .= " " . $this->compileValue($directive->value);
+ }
+ $this->compileNestedBlock($directive, array($s));
+ break;
+ case "media":
+ $this->compileMedia($child[1]);
+ break;
+ case "block":
+ $this->compileBlock($child[1]);
+ break;
+ case "charset":
+ $out->lines[] = "@charset ".$this->compileValue($child[1]).";";
+ break;
+ case "assign":
+ list(,$name, $value) = $child;
+ if ($name[0] == "var") {
+ $isDefault = !empty($child[3]);
+
+ if ($isDefault) {
+ $existingValue = $this->get($name[1], true);
+ $shouldSet = $existingValue === true || $existingValue == self::$null;
+ }
+
+ if (!$isDefault || $shouldSet) {
+ $this->set($name[1], $this->reduce($value));
+ }
+ break;
+ }
+
+ // if the value reduces to null from something else then
+ // the property should be discarded
+ if ($value[0] != "null") {
+ $value = $this->reduce($value);
+ if ($value[0] == "null") {
+ break;
+ }
+ }
+
+ $compiledValue = $this->compileValue($value);
+ $out->lines[] = $this->formatter->property(
+ $this->compileValue($name),
+ $compiledValue);
+ break;
+ case "comment":
+ $out->lines[] = $child[1];
+ break;
+ case "mixin":
+ case "function":
+ list(,$block) = $child;
+ $this->set(self::$namespaces[$block->type] . $block->name, $block);
+ break;
+ case "extend":
+ list(, $selectors) = $child;
+ foreach ($selectors as $sel) {
+ // only use the first one
+ $sel = current($this->evalSelector($sel));
+ $this->pushExtends($sel, $out->selectors);
+ }
+ break;
+ case "if":
+ list(, $if) = $child;
+ if ($this->isTruthy($this->reduce($if->cond, true))) {
+ return $this->compileChildren($if->children, $out);
+ } else {
+ foreach ($if->cases as $case) {
+ if ($case->type == "else" ||
+ $case->type == "elseif" && $this->isTruthy($this->reduce($case->cond)))
+ {
+ return $this->compileChildren($case->children, $out);
+ }
+ }
+ }
+ break;
+ case "return":
+ return $this->reduce($child[1], true);
+ case "each":
+ list(,$each) = $child;
+ $list = $this->coerceList($this->reduce($each->list));
+ foreach ($list[2] as $item) {
+ $this->pushEnv();
+ $this->set($each->var, $item);
+ // TODO: allow return from here
+ $this->compileChildren($each->children, $out);
+ $this->popEnv();
+ }
+ break;
+ case "while":
+ list(,$while) = $child;
+ while ($this->isTruthy($this->reduce($while->cond, true))) {
+ $ret = $this->compileChildren($while->children, $out);
+ if ($ret) return $ret;
+ }
+ break;
+ case "for":
+ list(,$for) = $child;
+ $start = $this->reduce($for->start, true);
+ $start = $start[1];
+ $end = $this->reduce($for->end, true);
+ $end = $end[1];
+ $d = $start < $end ? 1 : -1;
+
+ while (true) {
+ if ((!$for->until && $start - $d == $end) ||
+ ($for->until && $start == $end))
+ {
+ break;
+ }
+
+ $this->set($for->var, array("number", $start, ""));
+ $start += $d;
+
+ $ret = $this->compileChildren($for->children, $out);
+ if ($ret) return $ret;
+ }
+
+ break;
+ case "nestedprop":
+ list(,$prop) = $child;
+ $prefixed = array();
+ $prefix = $this->compileValue($prop->prefix) . "-";
+ foreach ($prop->children as $child) {
+ if ($child[0] == "assign") {
+ array_unshift($child[1][2], $prefix);
+ }
+ if ($child[0] == "nestedprop") {
+ array_unshift($child[1]->prefix[2], $prefix);
+ }
+ $prefixed[] = $child;
+ }
+ $this->compileChildren($prefixed, $out);
+ break;
+ case "include": // including a mixin
+ list(,$name, $argValues, $content) = $child;
+ $mixin = $this->get(self::$namespaces["mixin"] . $name, false);
+ if (!$mixin) {
+ $this->throwError("Undefined mixin $name");
+ }
+
+ $callingScope = $this->env;
+
+ // push scope, apply args
+ $this->pushEnv();
+ if ($this->env->depth > 0) {
+ $this->env->depth--;
+ }
+
+ if (isset($content)) {
+ $content->scope = $callingScope;
+ $this->setRaw(self::$namespaces["special"] . "content", $content);
+ }
+
+ if (isset($mixin->args)) {
+ $this->applyArguments($mixin->args, $argValues);
+ }
+
+ foreach ($mixin->children as $child) {
+ $this->compileChild($child, $out);
+ }
+
+ $this->popEnv();
+
+ break;
+ case "mixin_content":
+ $content = $this->get(self::$namespaces["special"] . "content");
+ if (!isset($content)) {
+ $this->throwError("Expected @content inside of mixin");
+ }
+
+ $strongTypes = array('include', 'block', 'for', 'while');
+ foreach ($content->children as $child) {
+ $this->storeEnv = (in_array($child[0], $strongTypes))
+ ? null
+ : $content->scope;
+
+ $this->compileChild($child, $out);
+ }
+
+ unset($this->storeEnv);
+ break;
+ case "debug":
+ list(,$value, $pos) = $child;
+ $line = $this->parser->getLineNo($pos);
+ $value = $this->compileValue($this->reduce($value, true));
+ fwrite(STDERR, "Line $line DEBUG: $value\n");
+ break;
+ default:
+ $this->throwError("unknown child type: $child[0]");
+ }
+ }
+
+ protected function expToString($exp) {
+ list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp;
+ $content = array($this->reduce($left));
+ if ($whiteLeft) $content[] = " ";
+ $content[] = $op;
+ if ($whiteRight) $content[] = " ";
+ $content[] = $this->reduce($right);
+ return array("string", "", $content);
+ }
+
+ protected function isTruthy($value) {
+ return $value != self::$false && $value != self::$null;
+ }
+
+ // should $value cause its operand to eval
+ protected function shouldEval($value) {
+ switch ($value[0]) {
+ case "exp":
+ if ($value[1] == "/") {
+ return $this->shouldEval($value[2], $value[3]);
+ }
+ case "var":
+ case "fncall":
+ return true;
+ }
+ return false;
+ }
+
+ protected function reduce($value, $inExp = false) {
+ list($type) = $value;
+ switch ($type) {
+ case "exp":
+ list(, $op, $left, $right, $inParens) = $value;
+ $opName = isset(self::$operatorNames[$op]) ? self::$operatorNames[$op] : $op;
+
+ $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right);
+
+ $left = $this->reduce($left, true);
+ $right = $this->reduce($right, true);
+
+ // only do division in special cases
+ if ($opName == "div" && !$inParens && !$inExp) {
+ if ($left[0] != "color" && $right[0] != "color") {
+ return $this->expToString($value);
+ }
+ }
+
+ $left = $this->coerceForExpression($left);
+ $right = $this->coerceForExpression($right);
+
+ $ltype = $left[0];
+ $rtype = $right[0];
+
+ // this tries:
+ // 1. op_[op name]_[left type]_[right type]
+ // 2. op_[left type]_[right type] (passing the op as first arg
+ // 3. op_[op name]
+ $fn = "op_${opName}_${ltype}_${rtype}";
+ if (is_callable(array($this, $fn)) ||
+ (($fn = "op_${ltype}_${rtype}") &&
+ is_callable(array($this, $fn)) &&
+ $passOp = true) ||
+ (($fn = "op_${opName}") &&
+ is_callable(array($this, $fn)) &&
+ $genOp = true))
+ {
+ $unitChange = false;
+ if (!isset($genOp) &&
+ $left[0] == "number" && $right[0] == "number")
+ {
+ if ($opName == "mod" && $right[2] != "") {
+ $this->throwError("Cannot modulo by a number with units: $right[1]$right[2].");
+ }
+
+ $unitChange = true;
+ $emptyUnit = $left[2] == "" || $right[2] == "";
+ $targetUnit = "" != $left[2] ? $left[2] : $right[2];
+
+ if ($opName != "mul") {
+ $left[2] = "" != $left[2] ? $left[2] : $targetUnit;
+ $right[2] = "" != $right[2] ? $right[2] : $targetUnit;
+ }
+
+ if ($opName != "mod") {
+ $left = $this->normalizeNumber($left);
+ $right = $this->normalizeNumber($right);
+ }
+
+ if ($opName == "div" && !$emptyUnit && $left[2] == $right[2]) {
+ $targetUnit = "";
+ }
+
+ if ($opName == "mul") {
+ $left[2] = "" != $left[2] ? $left[2] : $right[2];
+ $right[2] = "" != $right[2] ? $right[2] : $left[2];
+ } elseif ($opName == "div" && $left[2] == $right[2]) {
+ $left[2] = "";
+ $right[2] = "";
+ }
+ }
+
+ $shouldEval = $inParens || $inExp;
+ if (isset($passOp)) {
+ $out = $this->$fn($op, $left, $right, $shouldEval);
+ } else {
+ $out = $this->$fn($left, $right, $shouldEval);
+ }
+
+ if (isset($out)) {
+ if ($unitChange && $out[0] == "number") {
+ $out = $this->coerceUnit($out, $targetUnit);
+ }
+ return $out;
+ }
+ }
+
+ return $this->expToString($value);
+ case "unary":
+ list(, $op, $exp, $inParens) = $value;
+ $inExp = $inExp || $this->shouldEval($exp);
+
+ $exp = $this->reduce($exp);
+ if ($exp[0] == "number") {
+ switch ($op) {
+ case "+":
+ return $exp;
+ case "-":
+ $exp[1] *= -1;
+ return $exp;
+ }
+ }
+
+ if ($op == "not") {
+ if ($inExp || $inParens) {
+ if ($exp == self::$false) {
+ return self::$true;
+ } else {
+ return self::$false;
+ }
+ } else {
+ $op = $op . " ";
+ }
+ }
+
+ return array("string", "", array($op, $exp));
+ case "var":
+ list(, $name) = $value;
+ return $this->reduce($this->get($name));
+ case "list":
+ foreach ($value[2] as &$item) {
+ $item = $this->reduce($item);
+ }
+ return $value;
+ case "string":
+ foreach ($value[2] as &$item) {
+ if (is_array($item)) {
+ $item = $this->reduce($item);
+ }
+ }
+ return $value;
+ case "interpolate":
+ $value[1] = $this->reduce($value[1]);
+ return $value;
+ case "fncall":
+ list(,$name, $argValues) = $value;
+
+ // user defined function?
+ $func = $this->get(self::$namespaces["function"] . $name, false);
+ if ($func) {
+ $this->pushEnv();
+
+ // set the args
+ if (isset($func->args)) {
+ $this->applyArguments($func->args, $argValues);
+ }
+
+ // throw away lines and children
+ $tmp = (object)array(
+ "lines" => array(),
+ "children" => array()
+ );
+ $ret = $this->compileChildren($func->children, $tmp);
+ $this->popEnv();
+
+ return !isset($ret) ? self::$defaultValue : $ret;
+ }
+
+ // built in function
+ if ($this->callBuiltin($name, $argValues, $returnValue)) {
+ return $returnValue;
+ }
+
+ // need to flatten the arguments into a list
+ $listArgs = array();
+ foreach ((array)$argValues as $arg) {
+ if (empty($arg[0])) {
+ $listArgs[] = $this->reduce($arg[1]);
+ }
+ }
+ return array("function", $name, array("list", ",", $listArgs));
+ default:
+ return $value;
+ }
+ }
+
+ public function normalizeValue($value) {
+ $value = $this->coerceForExpression($this->reduce($value));
+ list($type) = $value;
+
+ switch ($type) {
+ case "list":
+ $value = $this->extractInterpolation($value);
+ if ($value[0] != "list") {
+ return array("keyword", $this->compileValue($value));
+ }
+ foreach ($value[2] as $key => $item) {
+ $value[2][$key] = $this->normalizeValue($item);
+ }
+ return $value;
+ case "number":
+ return $this->normalizeNumber($value);
+ default:
+ return $value;
+ }
+ }
+
+ // just does physical lengths for now
+ protected function normalizeNumber($number) {
+ list(, $value, $unit) = $number;
+ if (isset(self::$unitTable["in"][$unit])) {
+ $conv = self::$unitTable["in"][$unit];
+ return array("number", $value / $conv, "in");
+ }
+ return $number;
+ }
+
+ // $number should be normalized
+ protected function coerceUnit($number, $unit) {
+ list(, $value, $baseUnit) = $number;
+ if (isset(self::$unitTable[$baseUnit][$unit])) {
+ $value = $value * self::$unitTable[$baseUnit][$unit];
+ }
+
+ return array("number", $value, $unit);
+ }
+
+ protected function op_add_number_number($left, $right) {
+ return array("number", $left[1] + $right[1], $left[2]);
+ }
+
+ protected function op_mul_number_number($left, $right) {
+ return array("number", $left[1] * $right[1], $left[2]);
+ }
+
+ protected function op_sub_number_number($left, $right) {
+ return array("number", $left[1] - $right[1], $left[2]);
+ }
+
+ protected function op_div_number_number($left, $right) {
+ return array("number", $left[1] / $right[1], $left[2]);
+ }
+
+ protected function op_mod_number_number($left, $right) {
+ return array("number", $left[1] % $right[1], $left[2]);
+ }
+
+ // adding strings
+ protected function op_add($left, $right) {
+ if ($strLeft = $this->coerceString($left)) {
+ if ($right[0] == "string") {
+ $right[1] = "";
+ }
+ $strLeft[2][] = $right;
+ return $strLeft;
+ }
+
+ if ($strRight = $this->coerceString($right)) {
+ if ($left[0] == "string") {
+ $left[1] = "";
+ }
+ array_unshift($strRight[2], $left);
+ return $strRight;
+ }
+ }
+
+ protected function op_and($left, $right, $shouldEval) {
+ if (!$shouldEval) return;
+ if ($left != self::$false) return $right;
+ return $left;
+ }
+
+ protected function op_or($left, $right, $shouldEval) {
+ if (!$shouldEval) return;
+ if ($left != self::$false) return $left;
+ return $right;
+ }
+
+ protected function op_color_color($op, $left, $right) {
+ $out = array('color');
+ foreach (range(1, 3) as $i) {
+ $lval = isset($left[$i]) ? $left[$i] : 0;
+ $rval = isset($right[$i]) ? $right[$i] : 0;
+ switch ($op) {
+ case '+':
+ $out[] = $lval + $rval;
+ break;
+ case '-':
+ $out[] = $lval - $rval;
+ break;
+ case '*':
+ $out[] = $lval * $rval;
+ break;
+ case '%':
+ $out[] = $lval % $rval;
+ break;
+ case '/':
+ if ($rval == 0) {
+ $this->throwError("color: Can't divide by zero");
+ }
+ $out[] = $lval / $rval;
+ break;
+ case "==":
+ return $this->op_eq($left, $right);
+ case "!=":
+ return $this->op_neq($left, $right);
+ default:
+ $this->throwError("color: unknown op $op");
+ }
+ }
+
+ if (isset($left[4])) $out[4] = $left[4];
+ elseif (isset($right[4])) $out[4] = $right[4];
+
+ return $this->fixColor($out);
+ }
+
+ protected function op_color_number($op, $left, $right) {
+ $value = $right[1];
+ return $this->op_color_color($op, $left,
+ array("color", $value, $value, $value));
+ }
+
+ protected function op_number_color($op, $left, $right) {
+ $value = $left[1];
+ return $this->op_color_color($op,
+ array("color", $value, $value, $value), $right);
+ }
+
+ protected function op_eq($left, $right) {
+ if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
+ $lStr[1] = "";
+ $rStr[1] = "";
+ return $this->toBool($this->compileValue($lStr) == $this->compileValue($rStr));
+ }
+
+ return $this->toBool($left == $right);
+ }
+
+ protected function op_neq($left, $right) {
+ return $this->toBool($left != $right);
+ }
+
+ protected function op_gte_number_number($left, $right) {
+ return $this->toBool($left[1] >= $right[1]);
+ }
+
+ protected function op_gt_number_number($left, $right) {
+ return $this->toBool($left[1] > $right[1]);
+ }
+
+ protected function op_lte_number_number($left, $right) {
+ return $this->toBool($left[1] <= $right[1]);
+ }
+
+ protected function op_lt_number_number($left, $right) {
+ return $this->toBool($left[1] < $right[1]);
+ }
+
+ public function toBool($thing) {
+ return $thing ? self::$true : self::$false;
+ }
+
+ /**
+ * Compiles a primitive value into a CSS property value.
+ *
+ * Values in scssphp are typed by being wrapped in arrays, their format is
+ * typically:
+ *
+ * array(type, contents [, additional_contents]*)
+ *
+ * The input is expected to be reduced. This function will not work on
+ * things like expressions and variables.
+ *
+ * @param array $value
+ */
+ protected function compileValue($value) {
+ $value = $this->reduce($value);
+
+ list($type) = $value;
+ switch ($type) {
+ case "keyword":
+ return $value[1];
+ case "color":
+ // [1] - red component (either number for a %)
+ // [2] - green component
+ // [3] - blue component
+ // [4] - optional alpha component
+ list(, $r, $g, $b) = $value;
+
+ $r = round($r);
+ $g = round($g);
+ $b = round($b);
+
+ if (count($value) == 5 && $value[4] != 1) { // rgba
+ return 'rgba('.$r.', '.$g.', '.$b.', '.$value[4].')';
+ }
+
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
+
+ // Converting hex color to short notation (e.g. #003399 to #039)
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
+ $h = '#' . $h[1] . $h[3] . $h[5];
+ }
+
+ return $h;
+ case "number":
+ return round($value[1], $this->numberPrecision) . $value[2];
+ case "string":
+ return $value[1] . $this->compileStringContent($value) . $value[1];
+ case "function":
+ $args = !empty($value[2]) ? $this->compileValue($value[2]) : "";
+ return "$value[1]($args)";
+ case "list":
+ $value = $this->extractInterpolation($value);
+ if ($value[0] != "list") return $this->compileValue($value);
+
+ list(, $delim, $items) = $value;
+
+ $filtered = array();
+ foreach ($items as $item) {
+ if ($item[0] == "null") continue;
+ $filtered[] = $this->compileValue($item);
+ }
+
+ return implode("$delim ", $filtered);
+ case "interpolated": # node created by extractInterpolation
+ list(, $interpolate, $left, $right) = $value;
+ list(,, $whiteLeft, $whiteRight) = $interpolate;
+
+ $left = count($left[2]) > 0 ?
+ $this->compileValue($left).$whiteLeft : "";
+
+ $right = count($right[2]) > 0 ?
+ $whiteRight.$this->compileValue($right) : "";
+
+ return $left.$this->compileValue($interpolate).$right;
+
+ case "interpolate": # raw parse node
+ list(, $exp) = $value;
+
+ // strip quotes if it's a string
+ $reduced = $this->reduce($exp);
+ switch ($reduced[0]) {
+ case "string":
+ $reduced = array("keyword",
+ $this->compileStringContent($reduced));
+ break;
+ case "null":
+ $reduced = array("keyword", "");
+ }
+
+ return $this->compileValue($reduced);
+ case "null":
+ return "null";
+ default:
+ $this->throwError("unknown value type: $type");
+ }
+ }
+
+ protected function compileStringContent($string) {
+ $parts = array();
+ foreach ($string[2] as $part) {
+ if (is_array($part)) {
+ $parts[] = $this->compileValue($part);
+ } else {
+ $parts[] = $part;
+ }
+ }
+
+ return implode($parts);
+ }
+
+ // doesn't need to be recursive, compileValue will handle that
+ protected function extractInterpolation($list) {
+ $items = $list[2];
+ foreach ($items as $i => $item) {
+ if ($item[0] == "interpolate") {
+ $before = array("list", $list[1], array_slice($items, 0, $i));
+ $after = array("list", $list[1], array_slice($items, $i + 1));
+ return array("interpolated", $item, $before, $after);
+ }
+ }
+ return $list;
+ }
+
+ // find the final set of selectors
+ protected function multiplySelectors($env) {
+ $envs = array();
+ while (null !== $env) {
+ if (!empty($env->selectors)) {
+ $envs[] = $env;
+ }
+ $env = $env->parent;
+ };
+
+ $selectors = array();
+ $parentSelectors = array(array());
+ while ($env = array_pop($envs)) {
+ $selectors = array();
+ foreach ($env->selectors as $selector) {
+ foreach ($parentSelectors as $parent) {
+ $selectors[] = $this->joinSelectors($parent, $selector);
+ }
+ }
+ $parentSelectors = $selectors;
+ }
+
+ return $selectors;
+ }
+
+ // looks for & to replace, or append parent before child
+ protected function joinSelectors($parent, $child) {
+ $setSelf = false;
+ $out = array();
+ foreach ($child as $part) {
+ $newPart = array();
+ foreach ($part as $p) {
+ if ($p == self::$selfSelector) {
+ $setSelf = true;
+ foreach ($parent as $i => $parentPart) {
+ if ($i > 0) {
+ $out[] = $newPart;
+ $newPart = array();
+ }
+
+ foreach ($parentPart as $pp) {
+ $newPart[] = $pp;
+ }
+ }
+ } else {
+ $newPart[] = $p;
+ }
+ }
+
+ $out[] = $newPart;
+ }
+
+ return $setSelf ? $out : array_merge($parent, $child);
+ }
+
+ protected function multiplyMedia($env, $childQueries = null) {
+ if (!isset($env) ||
+ !empty($env->block->type) && $env->block->type != "media")
+ {
+ return $childQueries;
+ }
+
+ // plain old block, skip
+ if (empty($env->block->type)) {
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ $parentQueries = $env->block->queryList;
+ if ($childQueries == null) {
+ $childQueries = $parentQueries;
+ } else {
+ $originalQueries = $childQueries;
+ $childQueries = array();
+
+ foreach ($parentQueries as $parentQuery){
+ foreach ($originalQueries as $childQuery) {
+ $childQueries []= array_merge($parentQuery, $childQuery);
+ }
+ }
+ }
+
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ // convert something to list
+ protected function coerceList($item, $delim = ",") {
+ if (isset($item) && $item[0] == "list") {
+ return $item;
+ }
+
+ return array("list", $delim, !isset($item) ? array(): array($item));
+ }
+
+ protected function applyArguments($argDef, $argValues) {
+ $hasVariable = false;
+ $args = array();
+ foreach ($argDef as $i => $arg) {
+ list($name, $default, $isVariable) = $argDef[$i];
+ $args[$name] = array($i, $name, $default, $isVariable);
+ $hasVariable |= $isVariable;
+ }
+
+ $keywordArgs = array();
+ $deferredKeywordArgs = array();
+ $remaining = array();
+ // assign the keyword args
+ foreach ((array) $argValues as $arg) {
+ if (!empty($arg[0])) {
+ if (!isset($args[$arg[0][1]])) {
+ if ($hasVariable) {
+ $deferredKeywordArgs[$arg[0][1]] = $arg[1];
+ } else {
+ $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
+ }
+ } elseif ($args[$arg[0][1]][0] < count($remaining)) {
+ $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
+ } else {
+ $keywordArgs[$arg[0][1]] = $arg[1];
+ }
+ } elseif (count($keywordArgs)) {
+ $this->throwError('Positional arguments must come before keyword arguments.');
+ } elseif ($arg[2] == true) {
+ $val = $this->reduce($arg[1], true);
+ if ($val[0] == "list") {
+ foreach ($val[2] as $name => $item) {
+ if (!is_numeric($name)) {
+ $keywordArgs[$name] = $item;
+ } else {
+ $remaining[] = $item;
+ }
+ }
+ } else {
+ $remaining[] = $val;
+ }
+ } else {
+ $remaining[] = $arg[1];
+ }
+ }
+
+ foreach ($args as $arg) {
+ list($i, $name, $default, $isVariable) = $arg;
+ if ($isVariable) {
+ $val = array("list", ",", array());
+ for ($count = count($remaining); $i < $count; $i++) {
+ $val[2][] = $remaining[$i];
+ }
+ foreach ($deferredKeywordArgs as $itemName => $item) {
+ $val[2][$itemName] = $item;
+ }
+ } elseif (isset($remaining[$i])) {
+ $val = $remaining[$i];
+ } elseif (isset($keywordArgs[$name])) {
+ $val = $keywordArgs[$name];
+ } elseif (!empty($default)) {
+ $val = $default;
+ } else {
+ $this->throwError("Missing argument $name");
+ }
+
+ $this->set($name, $this->reduce($val, true), true);
+ }
+ }
+
+ protected function pushEnv($block=null) {
+ $env = new stdClass;
+ $env->parent = $this->env;
+ $env->store = array();
+ $env->block = $block;
+ $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
+
+ $this->env = $env;
+ return $env;
+ }
+
+ protected function normalizeName($name) {
+ return str_replace("-", "_", $name);
+ }
+
+ protected function getStoreEnv() {
+ return isset($this->storeEnv) ? $this->storeEnv : $this->env;
+ }
+
+ protected function set($name, $value, $shadow=false) {
+ $name = $this->normalizeName($name);
+
+ if ($shadow) {
+ $this->setRaw($name, $value);
+ } else {
+ $this->setExisting($name, $value);
+ }
+ }
+
+ protected function setExisting($name, $value, $env = null) {
+ if (!isset($env)) $env = $this->getStoreEnv();
+
+ if (isset($env->store[$name]) || !isset($env->parent)) {
+ $env->store[$name] = $value;
+ } else {
+ $this->setExisting($name, $value, $env->parent);
+ }
+ }
+
+ protected function setRaw($name, $value) {
+ $env = $this->getStoreEnv();
+ $env->store[$name] = $value;
+ }
+
+ public function get($name, $defaultValue = null, $env = null) {
+ $name = $this->normalizeName($name);
+
+ if (!isset($env)) $env = $this->getStoreEnv();
+ if (!isset($defaultValue)) $defaultValue = self::$defaultValue;
+
+ if (isset($env->store[$name])) {
+ return $env->store[$name];
+ } elseif (isset($env->parent)) {
+ return $this->get($name, $defaultValue, $env->parent);
+ }
+
+ return $defaultValue; // found nothing
+ }
+
+ protected function injectVariables(array $args)
+ {
+ if (empty($args)) {
+ return;
+ }
+
+ $parser = new scss_parser(__METHOD__, false);
+
+ foreach ($args as $name => $strValue) {
+ if ($name[0] === '$') {
+ $name = substr($name, 1);
+ }
+
+ $parser->env = null;
+ $parser->count = 0;
+ $parser->buffer = (string) $strValue;
+ $parser->inParens = false;
+ $parser->eatWhiteDefault = true;
+ $parser->insertComments = true;
+
+ if ( ! $parser->valueList($value)) {
+ throw new Exception("failed to parse passed in variable $name: $strValue");
+ }
+
+ $this->set($name, $value);
+ }
+ }
+
+ /**
+ * Set variables
+ *
+ * @param array $variables
+ */
+ public function setVariables(array $variables)
+ {
+ $this->registeredVars = array_merge($this->registeredVars, $variables);
+ }
+
+ /**
+ * Unset variable
+ *
+ * @param string $name
+ */
+ public function unsetVariable($name)
+ {
+ unset($this->registeredVars[$name]);
+ }
+
+ protected function popEnv() {
+ $env = $this->env;
+ $this->env = $this->env->parent;
+ return $env;
+ }
+
+ public function getParsedFiles() {
+ return $this->parsedFiles;
+ }
+
+ public function addImportPath($path) {
+ $this->importPaths[] = $path;
+ }
+
+ public function setImportPaths($path) {
+ $this->importPaths = (array)$path;
+ }
+
+ public function setNumberPrecision($numberPrecision) {
+ $this->numberPrecision = $numberPrecision;
+ }
+
+ public function setFormatter($formatterName) {
+ $this->formatter = $formatterName;
+ }
+
+ public function registerFunction($name, $func) {
+ $this->userFunctions[$this->normalizeName($name)] = $func;
+ }
+
+ public function unregisterFunction($name) {
+ unset($this->userFunctions[$this->normalizeName($name)]);
+ }
+
+ protected function importFile($path, $out) {
+ // see if tree is cached
+ $realPath = realpath($path);
+ if (isset($this->importCache[$realPath])) {
+ $tree = $this->importCache[$realPath];
+ } else {
+ $code = file_get_contents($path);
+ $parser = new scss_parser($path, false);
+ $tree = $parser->parse($code);
+ $this->parsedFiles[] = $path;
+
+ $this->importCache[$realPath] = $tree;
+ }
+
+ $pi = pathinfo($path);
+ array_unshift($this->importPaths, $pi['dirname']);
+ $this->compileChildren($tree->children, $out);
+ array_shift($this->importPaths);
+ }
+
+ // results the file path for an import url if it exists
+ public function findImport($url) {
+ $urls = array();
+
+ // for "normal" scss imports (ignore vanilla css and external requests)
+ if (!preg_match('/\.css|^http:\/\/$/', $url)) {
+ // try both normal and the _partial filename
+ $urls = array($url, preg_replace('/[^\/]+$/', '_\0', $url));
+ }
+
+ foreach ($this->importPaths as $dir) {
+ if (is_string($dir)) {
+ // check urls for normal import paths
+ foreach ($urls as $full) {
+ $full = $dir .
+ (!empty($dir) && substr($dir, -1) != '/' ? '/' : '') .
+ $full;
+
+ if ($this->fileExists($file = $full.'.scss') ||
+ $this->fileExists($file = $full))
+ {
+ return $file;
+ }
+ }
+ } else {
+ // check custom callback for import path
+ $file = call_user_func($dir,$url,$this);
+ if ($file !== null) {
+ return $file;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ protected function fileExists($name) {
+ return is_file($name);
+ }
+
+ protected function callBuiltin($name, $args, &$returnValue) {
+ // try a lib function
+ $name = $this->normalizeName($name);
+ $libName = "lib_".$name;
+ $f = array($this, $libName);
+ if (is_callable($f)) {
+ $prototype = isset(self::$$libName) ? self::$$libName : null;
+ $sorted = $this->sortArgs($prototype, $args);
+ foreach ($sorted as &$val) {
+ $val = $this->reduce($val, true);
+ }
+ $returnValue = call_user_func($f, $sorted, $this);
+ } elseif (isset($this->userFunctions[$name])) {
+ // see if we can find a user function
+ $fn = $this->userFunctions[$name];
+
+ foreach ($args as &$val) {
+ $val = $this->reduce($val[1], true);
+ }
+
+ $returnValue = call_user_func($fn, $args, $this);
+ }
+
+ if (isset($returnValue)) {
+ // coerce a php value into a scss one
+ if (is_numeric($returnValue)) {
+ $returnValue = array('number', $returnValue, "");
+ } elseif (is_bool($returnValue)) {
+ $returnValue = $returnValue ? self::$true : self::$false;
+ } elseif (!is_array($returnValue)) {
+ $returnValue = array('keyword', $returnValue);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // sorts any keyword arguments
+ // TODO: merge with apply arguments
+ protected function sortArgs($prototype, $args) {
+ $keyArgs = array();
+ $posArgs = array();
+
+ foreach ($args as $arg) {
+ list($key, $value) = $arg;
+ $key = $key[1];
+ if (empty($key)) {
+ $posArgs[] = $value;
+ } else {
+ $keyArgs[$key] = $value;
+ }
+ }
+
+ if (!isset($prototype)) return $posArgs;
+
+ $finalArgs = array();
+ foreach ($prototype as $i => $names) {
+ if (isset($posArgs[$i])) {
+ $finalArgs[] = $posArgs[$i];
+ continue;
+ }
+
+ $set = false;
+ foreach ((array)$names as $name) {
+ if (isset($keyArgs[$name])) {
+ $finalArgs[] = $keyArgs[$name];
+ $set = true;
+ break;
+ }
+ }
+
+ if (!$set) {
+ $finalArgs[] = null;
+ }
+ }
+
+ return $finalArgs;
+ }
+
+ protected function coerceForExpression($value) {
+ if ($color = $this->coerceColor($value)) {
+ return $color;
+ }
+
+ return $value;
+ }
+
+ protected function coerceColor($value) {
+ switch ($value[0]) {
+ case "color": return $value;
+ case "keyword":
+ $name = $value[1];
+ if (isset(self::$cssColors[$name])) {
+ $rgba = explode(',', self::$cssColors[$name]);
+ return isset($rgba[3])
+ ? array('color', (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3])
+ : array('color', (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]);
+ }
+ return null;
+ }
+
+ return null;
+ }
+
+ protected function coerceString($value) {
+ switch ($value[0]) {
+ case "string":
+ return $value;
+ case "keyword":
+ return array("string", "", array($value[1]));
+ }
+ return null;
+ }
+
+ public function assertList($value) {
+ if ($value[0] != "list")
+ $this->throwError("expecting list");
+ return $value;
+ }
+
+ public function assertColor($value) {
+ if ($color = $this->coerceColor($value)) return $color;
+ $this->throwError("expecting color");
+ }
+
+ public function assertNumber($value) {
+ if ($value[0] != "number")
+ $this->throwError("expecting number");
+ return $value[1];
+ }
+
+ protected function coercePercent($value) {
+ if ($value[0] == "number") {
+ if ($value[2] == "%") {
+ return $value[1] / 100;
+ }
+ return $value[1];
+ }
+ return 0;
+ }
+
+ // make sure a color's components don't go out of bounds
+ protected function fixColor($c) {
+ foreach (range(1, 3) as $i) {
+ if ($c[$i] < 0) $c[$i] = 0;
+ if ($c[$i] > 255) $c[$i] = 255;
+ }
+
+ return $c;
+ }
+
+ public function toHSL($red, $green, $blue) {
+ $min = min($red, $green, $blue);
+ $max = max($red, $green, $blue);
+
+ $l = $min + $max;
+
+ if ($min == $max) {
+ $s = $h = 0;
+ } else {
+ $d = $max - $min;
+
+ if ($l < 255)
+ $s = $d / $l;
+ else
+ $s = $d / (510 - $l);
+
+ if ($red == $max)
+ $h = 60 * ($green - $blue) / $d;
+ elseif ($green == $max)
+ $h = 60 * ($blue - $red) / $d + 120;
+ elseif ($blue == $max)
+ $h = 60 * ($red - $green) / $d + 240;
+ }
+
+ return array('hsl', fmod($h, 360), $s * 100, $l / 5.1);
+ }
+
+ public function hueToRGB($m1, $m2, $h) {
+ if ($h < 0)
+ $h += 1;
+ elseif ($h > 1)
+ $h -= 1;
+
+ if ($h * 6 < 1)
+ return $m1 + ($m2 - $m1) * $h * 6;
+
+ if ($h * 2 < 1)
+ return $m2;
+
+ if ($h * 3 < 2)
+ return $m1 + ($m2 - $m1) * (2/3 - $h) * 6;
+
+ return $m1;
+ }
+
+ // H from 0 to 360, S and L from 0 to 100
+ public function toRGB($hue, $saturation, $lightness) {
+ if ($hue < 0) {
+ $hue += 360;
+ }
+
+ $h = $hue / 360;
+ $s = min(100, max(0, $saturation)) / 100;
+ $l = min(100, max(0, $lightness)) / 100;
+
+ $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s;
+ $m1 = $l * 2 - $m2;
+
+ $r = $this->hueToRGB($m1, $m2, $h + 1/3) * 255;
+ $g = $this->hueToRGB($m1, $m2, $h) * 255;
+ $b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255;
+
+ $out = array('color', $r, $g, $b);
+ return $out;
+ }
+
+ // Built in functions
+
+ protected static $lib_if = array("condition", "if-true", "if-false");
+ protected function lib_if($args) {
+ list($cond,$t, $f) = $args;
+ if (!$this->isTruthy($cond)) return $f;
+ return $t;
+ }
+
+ protected static $lib_index = array("list", "value");
+ protected function lib_index($args) {
+ list($list, $value) = $args;
+ $list = $this->assertList($list);
+
+ $values = array();
+ foreach ($list[2] as $item) {
+ $values[] = $this->normalizeValue($item);
+ }
+ $key = array_search($this->normalizeValue($value), $values);
+
+ return false === $key ? false : $key + 1;
+ }
+
+ protected static $lib_rgb = array("red", "green", "blue");
+ protected function lib_rgb($args) {
+ list($r,$g,$b) = $args;
+ return array("color", $r[1], $g[1], $b[1]);
+ }
+
+ protected static $lib_rgba = array(
+ array("red", "color"),
+ "green", "blue", "alpha");
+ protected function lib_rgba($args) {
+ if ($color = $this->coerceColor($args[0])) {
+ $num = !isset($args[1]) ? $args[3] : $args[1];
+ $alpha = $this->assertNumber($num);
+ $color[4] = $alpha;
+ return $color;
+ }
+
+ list($r,$g,$b, $a) = $args;
+ return array("color", $r[1], $g[1], $b[1], $a[1]);
+ }
+
+ // helper function for adjust_color, change_color, and scale_color
+ protected function alter_color($args, $fn) {
+ $color = $this->assertColor($args[0]);
+
+ foreach (array(1,2,3,7) as $i) {
+ if (isset($args[$i])) {
+ $val = $this->assertNumber($args[$i]);
+ $ii = $i == 7 ? 4 : $i; // alpha
+ $color[$ii] =
+ $this->$fn(isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
+ }
+ }
+
+ if (isset($args[4]) || isset($args[5]) || isset($args[6])) {
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ foreach (array(4,5,6) as $i) {
+ if (isset($args[$i])) {
+ $val = $this->assertNumber($args[$i]);
+ $hsl[$i - 3] = $this->$fn($hsl[$i - 3], $val, $i);
+ }
+ }
+
+ $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
+ if (isset($color[4])) $rgb[4] = $color[4];
+ $color = $rgb;
+ }
+
+ return $color;
+ }
+
+ protected static $lib_adjust_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function adjust_color_helper($base, $alter, $i) {
+ return $base += $alter;
+ }
+ protected function lib_adjust_color($args) {
+ return $this->alter_color($args, "adjust_color_helper");
+ }
+
+ protected static $lib_change_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function change_color_helper($base, $alter, $i) {
+ return $alter;
+ }
+ protected function lib_change_color($args) {
+ return $this->alter_color($args, "change_color_helper");
+ }
+
+ protected static $lib_scale_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function scale_color_helper($base, $scale, $i) {
+ // 1,2,3 - rgb
+ // 4, 5, 6 - hsl
+ // 7 - a
+ switch ($i) {
+ case 1:
+ case 2:
+ case 3:
+ $max = 255; break;
+ case 4:
+ $max = 360; break;
+ case 7:
+ $max = 1; break;
+ default:
+ $max = 100;
+ }
+
+ $scale = $scale / 100;
+ if ($scale < 0) {
+ return $base * $scale + $base;
+ } else {
+ return ($max - $base) * $scale + $base;
+ }
+ }
+ protected function lib_scale_color($args) {
+ return $this->alter_color($args, "scale_color_helper");
+ }
+
+ protected static $lib_ie_hex_str = array("color");
+ protected function lib_ie_hex_str($args) {
+ $color = $this->coerceColor($args[0]);
+ $color[4] = isset($color[4]) ? round(255*$color[4]) : 255;
+
+ return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]);
+ }
+
+ protected static $lib_red = array("color");
+ protected function lib_red($args) {
+ $color = $this->coerceColor($args[0]);
+ return $color[1];
+ }
+
+ protected static $lib_green = array("color");
+ protected function lib_green($args) {
+ $color = $this->coerceColor($args[0]);
+ return $color[2];
+ }
+
+ protected static $lib_blue = array("color");
+ protected function lib_blue($args) {
+ $color = $this->coerceColor($args[0]);
+ return $color[3];
+ }
+
+ protected static $lib_alpha = array("color");
+ protected function lib_alpha($args) {
+ if ($color = $this->coerceColor($args[0])) {
+ return isset($color[4]) ? $color[4] : 1;
+ }
+
+ // this might be the IE function, so return value unchanged
+ return null;
+ }
+
+ protected static $lib_opacity = array("color");
+ protected function lib_opacity($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ return $this->lib_alpha($args);
+ }
+
+ // mix two colors
+ protected static $lib_mix = array("color-1", "color-2", "weight");
+ protected function lib_mix($args) {
+ list($first, $second, $weight) = $args;
+ $first = $this->assertColor($first);
+ $second = $this->assertColor($second);
+
+ if (!isset($weight)) {
+ $weight = 0.5;
+ } else {
+ $weight = $this->coercePercent($weight);
+ }
+
+ $firstAlpha = isset($first[4]) ? $first[4] : 1;
+ $secondAlpha = isset($second[4]) ? $second[4] : 1;
+
+ $w = $weight * 2 - 1;
+ $a = $firstAlpha - $secondAlpha;
+
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
+ $w2 = 1.0 - $w1;
+
+ $new = array('color',
+ $w1 * $first[1] + $w2 * $second[1],
+ $w1 * $first[2] + $w2 * $second[2],
+ $w1 * $first[3] + $w2 * $second[3],
+ );
+
+ if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
+ $new[] = $firstAlpha * $weight + $secondAlpha * ($weight - 1);
+ }
+
+ return $this->fixColor($new);
+ }
+
+ protected static $lib_hsl = array("hue", "saturation", "lightness");
+ protected function lib_hsl($args) {
+ list($h, $s, $l) = $args;
+ return $this->toRGB($h[1], $s[1], $l[1]);
+ }
+
+ protected static $lib_hsla = array("hue", "saturation",
+ "lightness", "alpha");
+ protected function lib_hsla($args) {
+ list($h, $s, $l, $a) = $args;
+ $color = $this->toRGB($h[1], $s[1], $l[1]);
+ $color[4] = $a[1];
+ return $color;
+ }
+
+ protected static $lib_hue = array("color");
+ protected function lib_hue($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[1], "deg");
+ }
+
+ protected static $lib_saturation = array("color");
+ protected function lib_saturation($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[2], "%");
+ }
+
+ protected static $lib_lightness = array("color");
+ protected function lib_lightness($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[3], "%");
+ }
+
+ protected function adjustHsl($color, $idx, $amount) {
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ $hsl[$idx] += $amount;
+ $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
+ if (isset($color[4])) $out[4] = $color[4];
+ return $out;
+ }
+
+ protected static $lib_adjust_hue = array("color", "degrees");
+ protected function lib_adjust_hue($args) {
+ $color = $this->assertColor($args[0]);
+ $degrees = $this->assertNumber($args[1]);
+ return $this->adjustHsl($color, 1, $degrees);
+ }
+
+ protected static $lib_lighten = array("color", "amount");
+ protected function lib_lighten($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 3, $amount);
+ }
+
+ protected static $lib_darken = array("color", "amount");
+ protected function lib_darken($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 3, -$amount);
+ }
+
+ protected static $lib_saturate = array("color", "amount");
+ protected function lib_saturate($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ $color = $this->assertColor($value);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 2, $amount);
+ }
+
+ protected static $lib_desaturate = array("color", "amount");
+ protected function lib_desaturate($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 2, -$amount);
+ }
+
+ protected static $lib_grayscale = array("color");
+ protected function lib_grayscale($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ return $this->adjustHsl($this->assertColor($value), 2, -100);
+ }
+
+ protected static $lib_complement = array("color");
+ protected function lib_complement($args) {
+ return $this->adjustHsl($this->assertColor($args[0]), 1, 180);
+ }
+
+ protected static $lib_invert = array("color");
+ protected function lib_invert($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ $color = $this->assertColor($value);
+ $color[1] = 255 - $color[1];
+ $color[2] = 255 - $color[2];
+ $color[3] = 255 - $color[3];
+ return $color;
+ }
+
+ // increases opacity by amount
+ protected static $lib_opacify = array("color", "amount");
+ protected function lib_opacify($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = $this->coercePercent($args[1]);
+
+ $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount;
+ $color[4] = min(1, max(0, $color[4]));
+ return $color;
+ }
+
+ protected static $lib_fade_in = array("color", "amount");
+ protected function lib_fade_in($args) {
+ return $this->lib_opacify($args);
+ }
+
+ // decreases opacity by amount
+ protected static $lib_transparentize = array("color", "amount");
+ protected function lib_transparentize($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = $this->coercePercent($args[1]);
+
+ $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount;
+ $color[4] = min(1, max(0, $color[4]));
+ return $color;
+ }
+
+ protected static $lib_fade_out = array("color", "amount");
+ protected function lib_fade_out($args) {
+ return $this->lib_transparentize($args);
+ }
+
+ protected static $lib_unquote = array("string");
+ protected function lib_unquote($args) {
+ $str = $args[0];
+ if ($str[0] == "string") $str[1] = "";
+ return $str;
+ }
+
+ protected static $lib_quote = array("string");
+ protected function lib_quote($args) {
+ $value = $args[0];
+ if ($value[0] == "string" && !empty($value[1]))
+ return $value;
+ return array("string", '"', array($value));
+ }
+
+ protected static $lib_percentage = array("value");
+ protected function lib_percentage($args) {
+ return array("number",
+ $this->coercePercent($args[0]) * 100,
+ "%");
+ }
+
+ protected static $lib_round = array("value");
+ protected function lib_round($args) {
+ $num = $args[0];
+ $num[1] = round($num[1]);
+ return $num;
+ }
+
+ protected static $lib_floor = array("value");
+ protected function lib_floor($args) {
+ $num = $args[0];
+ $num[1] = floor($num[1]);
+ return $num;
+ }
+
+ protected static $lib_ceil = array("value");
+ protected function lib_ceil($args) {
+ $num = $args[0];
+ $num[1] = ceil($num[1]);
+ return $num;
+ }
+
+ protected static $lib_abs = array("value");
+ protected function lib_abs($args) {
+ $num = $args[0];
+ $num[1] = abs($num[1]);
+ return $num;
+ }
+
+ protected function lib_min($args) {
+ $numbers = $this->getNormalizedNumbers($args);
+ $min = null;
+ foreach ($numbers as $key => $number) {
+ if (null === $min || $number[1] <= $min[1]) {
+ $min = array($key, $number[1]);
+ }
+ }
+
+ return $args[$min[0]];
+ }
+
+ protected function lib_max($args) {
+ $numbers = $this->getNormalizedNumbers($args);
+ $max = null;
+ foreach ($numbers as $key => $number) {
+ if (null === $max || $number[1] >= $max[1]) {
+ $max = array($key, $number[1]);
+ }
+ }
+
+ return $args[$max[0]];
+ }
+
+ protected function getNormalizedNumbers($args) {
+ $unit = null;
+ $originalUnit = null;
+ $numbers = array();
+ foreach ($args as $key => $item) {
+ if ('number' != $item[0]) {
+ $this->throwError("%s is not a number", $item[0]);
+ }
+ $number = $this->normalizeNumber($item);
+
+ if (null === $unit) {
+ $unit = $number[2];
+ $originalUnit = $item[2];
+ } elseif ($unit !== $number[2]) {
+ $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item[2]);
+ }
+
+ $numbers[$key] = $number;
+ }
+
+ return $numbers;
+ }
+
+ protected static $lib_length = array("list");
+ protected function lib_length($args) {
+ $list = $this->coerceList($args[0]);
+ return count($list[2]);
+ }
+
+ protected static $lib_nth = array("list", "n");
+ protected function lib_nth($args) {
+ $list = $this->coerceList($args[0]);
+ $n = $this->assertNumber($args[1]) - 1;
+ return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
+ }
+
+ protected function listSeparatorForJoin($list1, $sep) {
+ if (!isset($sep)) return $list1[1];
+ switch ($this->compileValue($sep)) {
+ case "comma":
+ return ",";
+ case "space":
+ return "";
+ default:
+ return $list1[1];
+ }
+ }
+
+ protected static $lib_join = array("list1", "list2", "separator");
+ protected function lib_join($args) {
+ list($list1, $list2, $sep) = $args;
+ $list1 = $this->coerceList($list1, " ");
+ $list2 = $this->coerceList($list2, " ");
+ $sep = $this->listSeparatorForJoin($list1, $sep);
+ return array("list", $sep, array_merge($list1[2], $list2[2]));
+ }
+
+ protected static $lib_append = array("list", "val", "separator");
+ protected function lib_append($args) {
+ list($list1, $value, $sep) = $args;
+ $list1 = $this->coerceList($list1, " ");
+ $sep = $this->listSeparatorForJoin($list1, $sep);
+ return array("list", $sep, array_merge($list1[2], array($value)));
+ }
+
+ protected function lib_zip($args) {
+ foreach ($args as $arg) {
+ $this->assertList($arg);
+ }
+
+ $lists = array();
+ $firstList = array_shift($args);
+ foreach ($firstList[2] as $key => $item) {
+ $list = array("list", "", array($item));
+ foreach ($args as $arg) {
+ if (isset($arg[2][$key])) {
+ $list[2][] = $arg[2][$key];
+ } else {
+ break 2;
+ }
+ }
+ $lists[] = $list;
+ }
+
+ return array("list", ",", $lists);
+ }
+
+ protected static $lib_type_of = array("value");
+ protected function lib_type_of($args) {
+ $value = $args[0];
+ switch ($value[0]) {
+ case "keyword":
+ if ($value == self::$true || $value == self::$false) {
+ return "bool";
+ }
+
+ if ($this->coerceColor($value)) {
+ return "color";
+ }
+
+ return "string";
+ default:
+ return $value[0];
+ }
+ }
+
+ protected static $lib_unit = array("number");
+ protected function lib_unit($args) {
+ $num = $args[0];
+ if ($num[0] == "number") {
+ return array("string", '"', array($num[2]));
+ }
+ return "";
+ }
+
+ protected static $lib_unitless = array("number");
+ protected function lib_unitless($args) {
+ $value = $args[0];
+ return $value[0] == "number" && empty($value[2]);
+ }
+
+ protected static $lib_comparable = array("number-1", "number-2");
+ protected function lib_comparable($args) {
+ list($number1, $number2) = $args;
+ if (!isset($number1[0]) || $number1[0] != "number" || !isset($number2[0]) || $number2[0] != "number") {
+ $this->throwError('Invalid argument(s) for "comparable"');
+ }
+
+ $number1 = $this->normalizeNumber($number1);
+ $number2 = $this->normalizeNumber($number2);
+
+ return $number1[2] == $number2[2] || $number1[2] == "" || $number2[2] == "";
+ }
+
+ /**
+ * Workaround IE7's content counter bug.
+ *
+ * @param array $args
+ */
+ protected function lib_counter($args) {
+ $list = array_map(array($this, 'compileValue'), $args);
+ return array('string', '', array('counter(' . implode(',', $list) . ')'));
+ }
+
+ public function throwError($msg = null) {
+ if (func_num_args() > 1) {
+ $msg = call_user_func_array("sprintf", func_get_args());
+ }
+
+ if ($this->sourcePos >= 0 && isset($this->sourceParser)) {
+ $this->sourceParser->throwParseError($msg, $this->sourcePos);
+ }
+
+ throw new Exception($msg);
+ }
+
+ /**
+ * CSS Colors
+ *
+ * @see http://www.w3.org/TR/css3-color
+ */
+ static protected $cssColors = array(
+ 'aliceblue' => '240,248,255',
+ 'antiquewhite' => '250,235,215',
+ 'aqua' => '0,255,255',
+ 'aquamarine' => '127,255,212',
+ 'azure' => '240,255,255',
+ 'beige' => '245,245,220',
+ 'bisque' => '255,228,196',
+ 'black' => '0,0,0',
+ 'blanchedalmond' => '255,235,205',
+ 'blue' => '0,0,255',
+ 'blueviolet' => '138,43,226',
+ 'brown' => '165,42,42',
+ 'burlywood' => '222,184,135',
+ 'cadetblue' => '95,158,160',
+ 'chartreuse' => '127,255,0',
+ 'chocolate' => '210,105,30',
+ 'coral' => '255,127,80',
+ 'cornflowerblue' => '100,149,237',
+ 'cornsilk' => '255,248,220',
+ 'crimson' => '220,20,60',
+ 'cyan' => '0,255,255',
+ 'darkblue' => '0,0,139',
+ 'darkcyan' => '0,139,139',
+ 'darkgoldenrod' => '184,134,11',
+ 'darkgray' => '169,169,169',
+ 'darkgreen' => '0,100,0',
+ 'darkgrey' => '169,169,169',
+ 'darkkhaki' => '189,183,107',
+ 'darkmagenta' => '139,0,139',
+ 'darkolivegreen' => '85,107,47',
+ 'darkorange' => '255,140,0',
+ 'darkorchid' => '153,50,204',
+ 'darkred' => '139,0,0',
+ 'darksalmon' => '233,150,122',
+ 'darkseagreen' => '143,188,143',
+ 'darkslateblue' => '72,61,139',
+ 'darkslategray' => '47,79,79',
+ 'darkslategrey' => '47,79,79',
+ 'darkturquoise' => '0,206,209',
+ 'darkviolet' => '148,0,211',
+ 'deeppink' => '255,20,147',
+ 'deepskyblue' => '0,191,255',
+ 'dimgray' => '105,105,105',
+ 'dimgrey' => '105,105,105',
+ 'dodgerblue' => '30,144,255',
+ 'firebrick' => '178,34,34',
+ 'floralwhite' => '255,250,240',
+ 'forestgreen' => '34,139,34',
+ 'fuchsia' => '255,0,255',
+ 'gainsboro' => '220,220,220',
+ 'ghostwhite' => '248,248,255',
+ 'gold' => '255,215,0',
+ 'goldenrod' => '218,165,32',
+ 'gray' => '128,128,128',
+ 'green' => '0,128,0',
+ 'greenyellow' => '173,255,47',
+ 'grey' => '128,128,128',
+ 'honeydew' => '240,255,240',
+ 'hotpink' => '255,105,180',
+ 'indianred' => '205,92,92',
+ 'indigo' => '75,0,130',
+ 'ivory' => '255,255,240',
+ 'khaki' => '240,230,140',
+ 'lavender' => '230,230,250',
+ 'lavenderblush' => '255,240,245',
+ 'lawngreen' => '124,252,0',
+ 'lemonchiffon' => '255,250,205',
+ 'lightblue' => '173,216,230',
+ 'lightcoral' => '240,128,128',
+ 'lightcyan' => '224,255,255',
+ 'lightgoldenrodyellow' => '250,250,210',
+ 'lightgray' => '211,211,211',
+ 'lightgreen' => '144,238,144',
+ 'lightgrey' => '211,211,211',
+ 'lightpink' => '255,182,193',
+ 'lightsalmon' => '255,160,122',
+ 'lightseagreen' => '32,178,170',
+ 'lightskyblue' => '135,206,250',
+ 'lightslategray' => '119,136,153',
+ 'lightslategrey' => '119,136,153',
+ 'lightsteelblue' => '176,196,222',
+ 'lightyellow' => '255,255,224',
+ 'lime' => '0,255,0',
+ 'limegreen' => '50,205,50',
+ 'linen' => '250,240,230',
+ 'magenta' => '255,0,255',
+ 'maroon' => '128,0,0',
+ 'mediumaquamarine' => '102,205,170',
+ 'mediumblue' => '0,0,205',
+ 'mediumorchid' => '186,85,211',
+ 'mediumpurple' => '147,112,219',
+ 'mediumseagreen' => '60,179,113',
+ 'mediumslateblue' => '123,104,238',
+ 'mediumspringgreen' => '0,250,154',
+ 'mediumturquoise' => '72,209,204',
+ 'mediumvioletred' => '199,21,133',
+ 'midnightblue' => '25,25,112',
+ 'mintcream' => '245,255,250',
+ 'mistyrose' => '255,228,225',
+ 'moccasin' => '255,228,181',
+ 'navajowhite' => '255,222,173',
+ 'navy' => '0,0,128',
+ 'oldlace' => '253,245,230',
+ 'olive' => '128,128,0',
+ 'olivedrab' => '107,142,35',
+ 'orange' => '255,165,0',
+ 'orangered' => '255,69,0',
+ 'orchid' => '218,112,214',
+ 'palegoldenrod' => '238,232,170',
+ 'palegreen' => '152,251,152',
+ 'paleturquoise' => '175,238,238',
+ 'palevioletred' => '219,112,147',
+ 'papayawhip' => '255,239,213',
+ 'peachpuff' => '255,218,185',
+ 'peru' => '205,133,63',
+ 'pink' => '255,192,203',
+ 'plum' => '221,160,221',
+ 'powderblue' => '176,224,230',
+ 'purple' => '128,0,128',
+ 'red' => '255,0,0',
+ 'rosybrown' => '188,143,143',
+ 'royalblue' => '65,105,225',
+ 'saddlebrown' => '139,69,19',
+ 'salmon' => '250,128,114',
+ 'sandybrown' => '244,164,96',
+ 'seagreen' => '46,139,87',
+ 'seashell' => '255,245,238',
+ 'sienna' => '160,82,45',
+ 'silver' => '192,192,192',
+ 'skyblue' => '135,206,235',
+ 'slateblue' => '106,90,205',
+ 'slategray' => '112,128,144',
+ 'slategrey' => '112,128,144',
+ 'snow' => '255,250,250',
+ 'springgreen' => '0,255,127',
+ 'steelblue' => '70,130,180',
+ 'tan' => '210,180,140',
+ 'teal' => '0,128,128',
+ 'thistle' => '216,191,216',
+ 'tomato' => '255,99,71',
+ 'transparent' => '0,0,0,0',
+ 'turquoise' => '64,224,208',
+ 'violet' => '238,130,238',
+ 'wheat' => '245,222,179',
+ 'white' => '255,255,255',
+ 'whitesmoke' => '245,245,245',
+ 'yellow' => '255,255,0',
+ 'yellowgreen' => '154,205,50'
+ );
+}
+
+/**
+ * SCSS parser
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_parser {
+ static protected $precedence = array(
+ "or" => 0,
+ "and" => 1,
+
+ '==' => 2,
+ '!=' => 2,
+ '<=' => 2,
+ '>=' => 2,
+ '=' => 2,
+ '<' => 3,
+ '>' => 2,
+
+ '+' => 3,
+ '-' => 3,
+ '*' => 4,
+ '/' => 4,
+ '%' => 4,
+ );
+
+ static protected $operators = array("+", "-", "*", "/", "%",
+ "==", "!=", "<=", ">=", "<", ">", "and", "or");
+
+ static protected $operatorStr;
+ static protected $whitePattern;
+ static protected $commentMulti;
+
+ static protected $commentSingle = "//";
+ static protected $commentMultiLeft = "/*";
+ static protected $commentMultiRight = "*/";
+
+ /**
+ * Constructor
+ *
+ * @param string $sourceName
+ * @param boolean $rootParser
+ */
+ public function __construct($sourceName = null, $rootParser = true) {
+ $this->sourceName = $sourceName;
+ $this->rootParser = $rootParser;
+
+ if (empty(self::$operatorStr)) {
+ self::$operatorStr = $this->makeOperatorStr(self::$operators);
+
+ $commentSingle = $this->preg_quote(self::$commentSingle);
+ $commentMultiLeft = $this->preg_quote(self::$commentMultiLeft);
+ $commentMultiRight = $this->preg_quote(self::$commentMultiRight);
+ self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
+ self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
+ }
+ }
+
+ static protected function makeOperatorStr($operators) {
+ return '('.implode('|', array_map(array('scss_parser','preg_quote'),
+ $operators)).')';
+ }
+
+ /**
+ * Parser buffer
+ *
+ * @param string $buffer;
+ *
+ * @return \StdClass
+ */
+ public function parse($buffer)
+ {
+ $this->count = 0;
+ $this->env = null;
+ $this->inParens = false;
+ $this->eatWhiteDefault = true;
+ $this->insertComments = true;
+ $this->buffer = $buffer;
+
+ $this->pushBlock(null); // root block
+ $this->whitespace();
+
+ while (false !== $this->parseChunk())
+ ;
+
+ if ($this->count != strlen($this->buffer)) {
+ $this->throwParseError();
+ }
+
+ if (!empty($this->env->parent)) {
+ $this->throwParseError("unclosed block");
+ }
+
+ $this->env->isRoot = true;
+
+ return $this->env;
+ }
+
+ /**
+ * Parse a single chunk off the head of the buffer and append it to the
+ * current parse environment.
+ *
+ * Returns false when the buffer is empty, or when there is an error.
+ *
+ * This function is called repeatedly until the entire document is
+ * parsed.
+ *
+ * This parser is most similar to a recursive descent parser. Single
+ * functions represent discrete grammatical rules for the language, and
+ * they are able to capture the text that represents those rules.
+ *
+ * Consider the function scssc::keyword(). (All parse functions are
+ * structured the same.)
+ *
+ * The function takes a single reference argument. When calling the
+ * function it will attempt to match a keyword on the head of the buffer.
+ * If it is successful, it will place the keyword in the referenced
+ * argument, advance the position in the buffer, and return true. If it
+ * fails then it won't advance the buffer and it will return false.
+ *
+ * All of these parse functions are powered by scssc::match(), which behaves
+ * the same way, but takes a literal regular expression. Sometimes it is
+ * more convenient to use match instead of creating a new function.
+ *
+ * Because of the format of the functions, to parse an entire string of
+ * grammatical rules, you can chain them together using &&.
+ *
+ * But, if some of the rules in the chain succeed before one fails, then
+ * the buffer position will be left at an invalid state. In order to
+ * avoid this, scssc::seek() is used to remember and set buffer positions.
+ *
+ * Before parsing a chain, use $s = $this->seek() to remember the current
+ * position into $s. Then if a chain fails, use $this->seek($s) to
+ * go back where we started.
+ *
+ * @return boolean
+ */
+ protected function parseChunk() {
+ $s = $this->seek();
+
+ // the directives
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
+ if ($this->literal("@media") && $this->mediaQueryList($mediaQueryList) && $this->literal("{")) {
+ $media = $this->pushSpecialBlock("media");
+ $media->queryList = $mediaQueryList[2];
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@mixin") &&
+ $this->keyword($mixinName) &&
+ ($this->argumentDef($args) || true) &&
+ $this->literal("{"))
+ {
+ $mixin = $this->pushSpecialBlock("mixin");
+ $mixin->name = $mixinName;
+ $mixin->args = $args;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@include") &&
+ $this->keyword($mixinName) &&
+ ($this->literal("(") &&
+ ($this->argValues($argValues) || true) &&
+ $this->literal(")") || true) &&
+ ($this->end() ||
+ $this->literal("{") && $hasBlock = true))
+ {
+ $child = array("include",
+ $mixinName, isset($argValues) ? $argValues : null, null);
+
+ if (!empty($hasBlock)) {
+ $include = $this->pushSpecialBlock("include");
+ $include->child = $child;
+ } else {
+ $this->append($child, $s);
+ }
+
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@import") &&
+ $this->valueList($importPath) &&
+ $this->end())
+ {
+ $this->append(array("import", $importPath), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@extend") &&
+ $this->selectors($selector) &&
+ $this->end())
+ {
+ $this->append(array("extend", $selector), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@function") &&
+ $this->keyword($fnName) &&
+ $this->argumentDef($args) &&
+ $this->literal("{"))
+ {
+ $func = $this->pushSpecialBlock("function");
+ $func->name = $fnName;
+ $func->args = $args;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@return") && $this->valueList($retVal) && $this->end()) {
+ $this->append(array("return", $retVal), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@each") &&
+ $this->variable($varName) &&
+ $this->literal("in") &&
+ $this->valueList($list) &&
+ $this->literal("{"))
+ {
+ $each = $this->pushSpecialBlock("each");
+ $each->var = $varName[1];
+ $each->list = $list;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@while") &&
+ $this->expression($cond) &&
+ $this->literal("{"))
+ {
+ $while = $this->pushSpecialBlock("while");
+ $while->cond = $cond;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@for") &&
+ $this->variable($varName) &&
+ $this->literal("from") &&
+ $this->expression($start) &&
+ ($this->literal("through") ||
+ ($forUntil = true && $this->literal("to"))) &&
+ $this->expression($end) &&
+ $this->literal("{"))
+ {
+ $for = $this->pushSpecialBlock("for");
+ $for->var = $varName[1];
+ $for->start = $start;
+ $for->end = $end;
+ $for->until = isset($forUntil);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@if") && $this->valueList($cond) && $this->literal("{")) {
+ $if = $this->pushSpecialBlock("if");
+ $if->cond = $cond;
+ $if->cases = array();
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if (($this->literal("@debug") || $this->literal("@warn")) &&
+ $this->valueList($value) &&
+ $this->end()) {
+ $this->append(array("debug", $value, $s), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@content") && $this->end()) {
+ $this->append(array("mixin_content"), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ $last = $this->last();
+ if (isset($last) && $last[0] == "if") {
+ list(, $if) = $last;
+ if ($this->literal("@else")) {
+ if ($this->literal("{")) {
+ $else = $this->pushSpecialBlock("else");
+ } elseif ($this->literal("if") && $this->valueList($cond) && $this->literal("{")) {
+ $else = $this->pushSpecialBlock("elseif");
+ $else->cond = $cond;
+ }
+
+ if (isset($else)) {
+ $else->dontAppend = true;
+ $if->cases[] = $else;
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ }
+
+ if ($this->literal("@charset") &&
+ $this->valueList($charset) && $this->end())
+ {
+ $this->append(array("charset", $charset), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // doesn't match built in directive, do generic one
+ if ($this->literal("@", false) && $this->keyword($dirName) &&
+ ($this->openString("{", $dirValue) || true) &&
+ $this->literal("{"))
+ {
+ $directive = $this->pushSpecialBlock("directive");
+ $directive->name = $dirName;
+ if (isset($dirValue)) $directive->value = $dirValue;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // property shortcut
+ // captures most properties before having to parse a selector
+ if ($this->keyword($name, false) &&
+ $this->literal(": ") &&
+ $this->valueList($value) &&
+ $this->end())
+ {
+ $name = array("string", "", array($name));
+ $this->append(array("assign", $name, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // variable assigns
+ if ($this->variable($name) &&
+ $this->literal(":") &&
+ $this->valueList($value) && $this->end())
+ {
+ // check for !default
+ $defaultVar = $value[0] == "list" && $this->stripDefault($value);
+ $this->append(array("assign", $name, $value, $defaultVar), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // misc
+ if ($this->literal("-->")) {
+ return true;
+ }
+
+ // opening css block
+ $oldComments = $this->insertComments;
+ $this->insertComments = false;
+ if ($this->selectors($selectors) && $this->literal("{")) {
+ $this->pushBlock($selectors);
+ $this->insertComments = $oldComments;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+ $this->insertComments = $oldComments;
+
+ // property assign, or nested assign
+ if ($this->propertyName($name) && $this->literal(":")) {
+ $foundSomething = false;
+ if ($this->valueList($value)) {
+ $this->append(array("assign", $name, $value), $s);
+ $foundSomething = true;
+ }
+
+ if ($this->literal("{")) {
+ $propBlock = $this->pushSpecialBlock("nestedprop");
+ $propBlock->prefix = $name;
+ $foundSomething = true;
+ } elseif ($foundSomething) {
+ $foundSomething = $this->end();
+ }
+
+ if ($foundSomething) {
+ return true;
+ }
+
+ $this->seek($s);
+ } else {
+ $this->seek($s);
+ }
+
+ // closing a block
+ if ($this->literal("}")) {
+ $block = $this->popBlock();
+ if (isset($block->type) && $block->type == "include") {
+ $include = $block->child;
+ unset($block->child);
+ $include[3] = $block;
+ $this->append($include, $s);
+ } elseif (empty($block->dontAppend)) {
+ $type = isset($block->type) ? $block->type : "block";
+ $this->append(array($type, $block), $s);
+ }
+ return true;
+ }
+
+ // extra stuff
+ if ($this->literal(";") ||
+ $this->literal("<!--"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function stripDefault(&$value) {
+ $def = end($value[2]);
+ if ($def[0] == "keyword" && $def[1] == "!default") {
+ array_pop($value[2]);
+ $value = $this->flattenList($value);
+ return true;
+ }
+
+ if ($def[0] == "list") {
+ return $this->stripDefault($value[2][count($value[2]) - 1]);
+ }
+
+ return false;
+ }
+
+ protected function literal($what, $eatWhitespace = null) {
+ if (!isset($eatWhitespace)) $eatWhitespace = $this->eatWhiteDefault;
+
+ // shortcut on single letter
+ if (!isset($what[1]) && isset($this->buffer[$this->count])) {
+ if ($this->buffer[$this->count] == $what) {
+ if (!$eatWhitespace) {
+ $this->count++;
+ return true;
+ }
+ // goes below...
+ } else {
+ return false;
+ }
+ }
+
+ return $this->match($this->preg_quote($what), $m, $eatWhitespace);
+ }
+
+ // tree builders
+
+ protected function pushBlock($selectors) {
+ $b = new stdClass;
+ $b->parent = $this->env; // not sure if we need this yet
+
+ $b->selectors = $selectors;
+ $b->children = array();
+
+ $this->env = $b;
+ return $b;
+ }
+
+ protected function pushSpecialBlock($type) {
+ $block = $this->pushBlock(null);
+ $block->type = $type;
+ return $block;
+ }
+
+ protected function popBlock() {
+ if (empty($this->env->parent)) {
+ $this->throwParseError("unexpected }");
+ }
+
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ unset($old->parent);
+ return $old;
+ }
+
+ protected function append($statement, $pos=null) {
+ if ($pos !== null) {
+ $statement[-1] = $pos;
+ if (!$this->rootParser) $statement[-2] = $this;
+ }
+ $this->env->children[] = $statement;
+ }
+
+ // last child that was appended
+ protected function last() {
+ $i = count($this->env->children) - 1;
+ if (isset($this->env->children[$i]))
+ return $this->env->children[$i];
+ }
+
+ // high level parsers (they return parts of ast)
+
+ protected function mediaQueryList(&$out) {
+ return $this->genericList($out, "mediaQuery", ",", false);
+ }
+
+ protected function mediaQuery(&$out) {
+ $s = $this->seek();
+
+ $expressions = null;
+ $parts = array();
+
+ if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->mixedKeyword($mediaType)) {
+ $prop = array("mediaType");
+ if (isset($only)) $prop[] = array("keyword", "only");
+ if (isset($not)) $prop[] = array("keyword", "not");
+ $media = array("list", "", array());
+ foreach ((array)$mediaType as $type) {
+ if (is_array($type)) {
+ $media[2][] = $type;
+ } else {
+ $media[2][] = array("keyword", $type);
+ }
+ }
+ $prop[] = $media;
+ $parts[] = $prop;
+ }
+
+ if (empty($parts) || $this->literal("and")) {
+ $this->genericList($expressions, "mediaExpression", "and", false);
+ if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function mediaExpression(&$out) {
+ $s = $this->seek();
+ $value = null;
+ if ($this->literal("(") &&
+ $this->expression($feature) &&
+ ($this->literal(":") && $this->expression($value) || true) &&
+ $this->literal(")"))
+ {
+ $out = array("mediaExp", $feature);
+ if ($value) $out[] = $value;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function argValues(&$out) {
+ if ($this->genericList($list, "argValue", ",", false)) {
+ $out = $list[2];
+ return true;
+ }
+ return false;
+ }
+
+ protected function argValue(&$out) {
+ $s = $this->seek();
+
+ $keyword = null;
+ if (!$this->variable($keyword) || !$this->literal(":")) {
+ $this->seek($s);
+ $keyword = null;
+ }
+
+ if ($this->genericList($value, "expression")) {
+ $out = array($keyword, $value, false);
+ $s = $this->seek();
+ if ($this->literal("...")) {
+ $out[2] = true;
+ } else {
+ $this->seek($s);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse list
+ *
+ * @param string $out
+ *
+ * @return boolean
+ */
+ public function valueList(&$out)
+ {
+ return $this->genericList($out, 'spaceList', ',');
+ }
+
+ protected function spaceList(&$out)
+ {
+ return $this->genericList($out, 'expression');
+ }
+
+ protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
+ $s = $this->seek();
+ $items = array();
+ while ($this->$parseItem($value)) {
+ $items[] = $value;
+ if ($delim) {
+ if (!$this->literal($delim)) break;
+ }
+ }
+
+ if (count($items) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($flatten && count($items) == 1) {
+ $out = $items[0];
+ } else {
+ $out = array("list", $delim, $items);
+ }
+
+ return true;
+ }
+
+ protected function expression(&$out) {
+ $s = $this->seek();
+
+ if ($this->literal("(")) {
+ if ($this->literal(")")) {
+ $out = array("list", "", array());
+ return true;
+ }
+
+ if ($this->valueList($out) && $this->literal(')') && $out[0] == "list") {
+ return true;
+ }
+
+ $this->seek($s);
+ }
+
+ if ($this->value($lhs)) {
+ $out = $this->expHelper($lhs, 0);
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function expHelper($lhs, $minP) {
+ $opstr = self::$operatorStr;
+
+ $ss = $this->seek();
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+ while ($this->match($opstr, $m) && self::$precedence[$m[1]] >= $minP) {
+ $whiteAfter = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ $op = $m[1];
+
+ // don't turn negative numbers into expressions
+ if ($op == "-" && $whiteBefore) {
+ if (!$whiteAfter) break;
+ }
+
+ if (!$this->value($rhs)) break;
+
+ // peek and see if rhs belongs to next operator
+ if ($this->peek($opstr, $next) && self::$precedence[$next[1]] > self::$precedence[$op]) {
+ $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
+ }
+
+ $lhs = array("exp", $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter);
+ $ss = $this->seek();
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+ }
+
+ $this->seek($ss);
+ return $lhs;
+ }
+
+ protected function value(&$out) {
+ $s = $this->seek();
+
+ if ($this->literal("not", false) && $this->whitespace() && $this->value($inner)) {
+ $out = array("unary", "not", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("+") && $this->value($inner)) {
+ $out = array("unary", "+", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // negation
+ if ($this->literal("-", false) &&
+ ($this->variable($inner) ||
+ $this->unit($inner) ||
+ $this->parenValue($inner)))
+ {
+ $out = array("unary", "-", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->parenValue($out)) return true;
+ if ($this->interpolation($out)) return true;
+ if ($this->variable($out)) return true;
+ if ($this->color($out)) return true;
+ if ($this->unit($out)) return true;
+ if ($this->string($out)) return true;
+ if ($this->func($out)) return true;
+ if ($this->progid($out)) return true;
+
+ if ($this->keyword($keyword)) {
+ if ($keyword == "null") {
+ $out = array("null");
+ } else {
+ $out = array("keyword", $keyword);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ // value wrappen in parentheses
+ protected function parenValue(&$out) {
+ $s = $this->seek();
+
+ $inParens = $this->inParens;
+ if ($this->literal("(") &&
+ ($this->inParens = true) && $this->expression($exp) &&
+ $this->literal(")"))
+ {
+ $out = $exp;
+ $this->inParens = $inParens;
+ return true;
+ } else {
+ $this->inParens = $inParens;
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ protected function progid(&$out) {
+ $s = $this->seek();
+ if ($this->literal("progid:", false) &&
+ $this->openString("(", $fn) &&
+ $this->literal("("))
+ {
+ $this->openString(")", $args, "(");
+ if ($this->literal(")")) {
+ $out = array("string", "", array(
+ "progid:", $fn, "(", $args, ")"
+ ));
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function func(&$func) {
+ $s = $this->seek();
+
+ if ($this->keyword($name, false) &&
+ $this->literal("("))
+ {
+ if ($name == "alpha" && $this->argumentList($args)) {
+ $func = array("function", $name, array("string", "", $args));
+ return true;
+ }
+
+ if ($name != "expression" && !preg_match("/^(-[a-z]+-)?calc$/", $name)) {
+ $ss = $this->seek();
+ if ($this->argValues($args) && $this->literal(")")) {
+ $func = array("fncall", $name, $args);
+ return true;
+ }
+ $this->seek($ss);
+ }
+
+ if (($this->openString(")", $str, "(") || true ) &&
+ $this->literal(")"))
+ {
+ $args = array();
+ if (!empty($str)) {
+ $args[] = array(null, array("string", "", array($str)));
+ }
+
+ $func = array("fncall", $name, $args);
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function argumentList(&$out) {
+ $s = $this->seek();
+ $this->literal("(");
+
+ $args = array();
+ while ($this->keyword($var)) {
+ $ss = $this->seek();
+
+ if ($this->literal("=") && $this->expression($exp)) {
+ $args[] = array("string", "", array($var."="));
+ $arg = $exp;
+ } else {
+ break;
+ }
+
+ $args[] = $arg;
+
+ if (!$this->literal(",")) break;
+
+ $args[] = array("string", "", array(", "));
+ }
+
+ if (!$this->literal(")") || !count($args)) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $args;
+ return true;
+ }
+
+ protected function argumentDef(&$out) {
+ $s = $this->seek();
+ $this->literal("(");
+
+ $args = array();
+ while ($this->variable($var)) {
+ $arg = array($var[1], null, false);
+
+ $ss = $this->seek();
+ if ($this->literal(":") && $this->genericList($defaultVal, "expression")) {
+ $arg[1] = $defaultVal;
+ } else {
+ $this->seek($ss);
+ }
+
+ $ss = $this->seek();
+ if ($this->literal("...")) {
+ $sss = $this->seek();
+ if (!$this->literal(")")) {
+ $this->throwParseError("... has to be after the final argument");
+ }
+ $arg[2] = true;
+ $this->seek($sss);
+ } else {
+ $this->seek($ss);
+ }
+
+ $args[] = $arg;
+ if (!$this->literal(",")) break;
+ }
+
+ if (!$this->literal(")")) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $args;
+ return true;
+ }
+
+ protected function color(&$out) {
+ $color = array('color');
+
+ if ($this->match('(#([0-9a-f]{6})|#([0-9a-f]{3}))', $m)) {
+ if (isset($m[3])) {
+ $num = $m[3];
+ $width = 16;
+ } else {
+ $num = $m[2];
+ $width = 256;
+ }
+
+ $num = hexdec($num);
+ foreach (array(3,2,1) as $i) {
+ $t = $num % $width;
+ $num /= $width;
+
+ $color[$i] = $t * (256/$width) + $t * floor(16/$width);
+ }
+
+ $out = $color;
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function unit(&$unit) {
+ if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m)) {
+ $unit = array("number", $m[1], empty($m[3]) ? "" : $m[3]);
+ return true;
+ }
+ return false;
+ }
+
+ protected function string(&$out) {
+ $s = $this->seek();
+ if ($this->literal('"', false)) {
+ $delim = '"';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
+ } else {
+ return false;
+ }
+
+ $content = array();
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while ($this->matchString($m, $delim)) {
+ $content[] = $m[1];
+ if ($m[2] == "#{") {
+ $this->count -= strlen($m[2]);
+ if ($this->interpolation($inter, false)) {
+ $content[] = $inter;
+ } else {
+ $this->count += strlen($m[2]);
+ $content[] = "#{"; // ignore it
+ }
+ } elseif ($m[2] == '\\') {
+ $content[] = $m[2];
+ if ($this->literal($delim, false)) {
+ $content[] = $delim;
+ }
+ } else {
+ $this->count -= strlen($delim);
+ break; // delim
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if ($this->literal($delim)) {
+ $out = array("string", $delim, $content);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function mixedKeyword(&$out) {
+ $s = $this->seek();
+
+ $parts = array();
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->keyword($key)) {
+ $parts[] = $key;
+ continue;
+ }
+
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ continue;
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($parts) == 0) return false;
+
+ if ($this->eatWhiteDefault) {
+ $this->whitespace();
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ // an unbounded string stopped by $end
+ protected function openString($end, &$out, $nestingOpen=null) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $stop = array("'", '"', "#{", $end);
+ $stop = array_map(array($this, "preg_quote"), $stop);
+ $stop[] = self::$commentMulti;
+
+ $patt = '(.*?)('.implode("|", $stop).')';
+
+ $nestingLevel = 0;
+
+ $content = array();
+ while ($this->match($patt, $m, false)) {
+ if (isset($m[1]) && $m[1] !== '') {
+ $content[] = $m[1];
+ if ($nestingOpen) {
+ $nestingLevel += substr_count($m[1], $nestingOpen);
+ }
+ }
+
+ $tok = $m[2];
+
+ $this->count-= strlen($tok);
+ if ($tok == $end) {
+ if ($nestingLevel == 0) {
+ break;
+ } else {
+ $nestingLevel--;
+ }
+ }
+
+ if (($tok == "'" || $tok == '"') && $this->string($str)) {
+ $content[] = $str;
+ continue;
+ }
+
+ if ($tok == "#{" && $this->interpolation($inter)) {
+ $content[] = $inter;
+ continue;
+ }
+
+ $content[] = $tok;
+ $this->count+= strlen($tok);
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($content) == 0) return false;
+
+ // trim the end
+ if (is_string(end($content))) {
+ $content[count($content) - 1] = rtrim(end($content));
+ }
+
+ $out = array("string", "", $content);
+ return true;
+ }
+
+ // $lookWhite: save information about whitespace before and after
+ protected function interpolation(&$out, $lookWhite=true) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = true;
+
+ $s = $this->seek();
+ if ($this->literal("#{") && $this->valueList($value) && $this->literal("}", false)) {
+
+ // TODO: don't error if out of bounds
+
+ if ($lookWhite) {
+ $left = preg_match('/\s/', $this->buffer[$s - 1]) ? " " : "";
+ $right = preg_match('/\s/', $this->buffer[$this->count]) ? " ": "";
+ } else {
+ $left = $right = false;
+ }
+
+ $out = array("interpolate", $value, $left, $right);
+ $this->eatWhiteDefault = $oldWhite;
+ if ($this->eatWhiteDefault) $this->whitespace();
+ return true;
+ }
+
+ $this->seek($s);
+ $this->eatWhiteDefault = $oldWhite;
+ return false;
+ }
+
+ // low level parsers
+
+ // returns an array of parts or a string
+ protected function propertyName(&$out) {
+ $s = $this->seek();
+ $parts = array();
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ } elseif ($this->keyword($text)) {
+ $parts[] = $text;
+ } elseif (count($parts) == 0 && $this->match('[:.#]', $m, false)) {
+ // css hacks
+ $parts[] = $m[0];
+ } else {
+ break;
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ if (count($parts) == 0) return false;
+
+ // match comment hack
+ if (preg_match(self::$whitePattern,
+ $this->buffer, $m, null, $this->count))
+ {
+ if (!empty($m[0])) {
+ $parts[] = $m[0];
+ $this->count += strlen($m[0]);
+ }
+ }
+
+ $this->whitespace(); // get any extra whitespace
+
+ $out = array("string", "", $parts);
+ return true;
+ }
+
+ // comma separated list of selectors
+ protected function selectors(&$out) {
+ $s = $this->seek();
+ $selectors = array();
+ while ($this->selector($sel)) {
+ $selectors[] = $sel;
+ if (!$this->literal(",")) break;
+ while ($this->literal(",")); // ignore extra
+ }
+
+ if (count($selectors) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $selectors;
+ return true;
+ }
+
+ // whitespace separated list of selectorSingle
+ protected function selector(&$out) {
+ $selector = array();
+
+ while (true) {
+ if ($this->match('[>+~]+', $m)) {
+ $selector[] = array($m[0]);
+ } elseif ($this->selectorSingle($part)) {
+ $selector[] = $part;
+ $this->whitespace();
+ } elseif ($this->match('\/[^\/]+\/', $m)) {
+ $selector[] = array($m[0]);
+ } else {
+ break;
+ }
+
+ }
+
+ if (count($selector) == 0) {
+ return false;
+ }
+
+ $out = $selector;
+ return true;
+ }
+
+ // the parts that make up
+ // div[yes=no]#something.hello.world:nth-child(-2n+1)%placeholder
+ protected function selectorSingle(&$out) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $parts = array();
+
+ if ($this->literal("*", false)) {
+ $parts[] = "*";
+ }
+
+ while (true) {
+ // see if we can stop early
+ if ($this->match("\s*[{,]", $m)) {
+ $this->count--;
+ break;
+ }
+
+ $s = $this->seek();
+ // self
+ if ($this->literal("&", false)) {
+ $parts[] = scssc::$selfSelector;
+ continue;
+ }
+
+ if ($this->literal(".", false)) {
+ $parts[] = ".";
+ continue;
+ }
+
+ if ($this->literal("|", false)) {
+ $parts[] = "|";
+ continue;
+ }
+
+ // for keyframes
+ if ($this->unit($unit)) {
+ $parts[] = $unit;
+ continue;
+ }
+
+ if ($this->keyword($name)) {
+ $parts[] = $name;
+ continue;
+ }
+
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ continue;
+ }
+
+ if ($this->literal('%', false) && $this->placeholder($placeholder)) {
+ $parts[] = '%';
+ $parts[] = $placeholder;
+ continue;
+ }
+
+ if ($this->literal("#", false)) {
+ $parts[] = "#";
+ continue;
+ }
+
+ // a pseudo selector
+ if ($this->match("::?", $m) && $this->mixedKeyword($nameParts)) {
+ $parts[] = $m[0];
+ foreach ($nameParts as $sub) {
+ $parts[] = $sub;
+ }
+
+ $ss = $this->seek();
+ if ($this->literal("(") &&
+ ($this->openString(")", $str, "(") || true ) &&
+ $this->literal(")"))
+ {
+ $parts[] = "(";
+ if (!empty($str)) $parts[] = $str;
+ $parts[] = ")";
+ } else {
+ $this->seek($ss);
+ }
+
+ continue;
+ } else {
+ $this->seek($s);
+ }
+
+ // attribute selector
+ // TODO: replace with open string?
+ if ($this->literal("[", false)) {
+ $attrParts = array("[");
+ // keyword, string, operator
+ while (true) {
+ if ($this->literal("]", false)) {
+ $this->count--;
+ break; // get out early
+ }
+
+ if ($this->match('\s+', $m)) {
+ $attrParts[] = " ";
+ continue;
+ }
+ if ($this->string($str)) {
+ $attrParts[] = $str;
+ continue;
+ }
+
+ if ($this->keyword($word)) {
+ $attrParts[] = $word;
+ continue;
+ }
+
+ if ($this->interpolation($inter, false)) {
+ $attrParts[] = $inter;
+ continue;
+ }
+
+ // operator, handles attr namespace too
+ if ($this->match('[|-~\$\*\^=]+', $m)) {
+ $attrParts[] = $m[0];
+ continue;
+ }
+
+ break;
+ }
+
+ if ($this->literal("]", false)) {
+ $attrParts[] = "]";
+ foreach ($attrParts as $part) {
+ $parts[] = $part;
+ }
+ continue;
+ }
+ $this->seek($s);
+ // should just break here?
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($parts) == 0) return false;
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function variable(&$out) {
+ $s = $this->seek();
+ if ($this->literal("$", false) && $this->keyword($name)) {
+ $out = array("var", $name);
+ return true;
+ }
+ $this->seek($s);
+ return false;
+ }
+
+ protected function keyword(&$word, $eatWhitespace = null) {
+ if ($this->match('([\w_\-\*!"\'\\\\][\w\-_"\'\\\\]*)',
+ $m, $eatWhitespace))
+ {
+ $word = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ protected function placeholder(&$placeholder) {
+ if ($this->match('([\w\-_]+)', $m)) {
+ $placeholder = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ // consume an end of statement delimiter
+ protected function end() {
+ if ($this->literal(';')) {
+ return true;
+ } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
+ // if there is end of file or a closing block next then we don't need a ;
+ return true;
+ }
+ return false;
+ }
+
+ // advance counter to next occurrence of $what
+ // $until - don't include $what in advance
+ // $allowNewline, if string, will be used as valid char set
+ protected function to($what, &$out, $until = false, $allowNewline = false) {
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? "." : "[^\n]";
+ }
+ if (!$this->match('('.$validChars.'*?)'.$this->preg_quote($what), $m, !$until)) return false;
+ if ($until) $this->count -= strlen($what); // give back $what
+ $out = $m[1];
+ return true;
+ }
+
+ public function throwParseError($msg = "parse error", $count = null) {
+ $count = !isset($count) ? $this->count : $count;
+
+ $line = $this->getLineNo($count);
+
+ if (!empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new Exception("$msg: failed at `$m[1]` $loc");
+ } else {
+ throw new Exception("$msg: $loc");
+ }
+ }
+
+ public function getLineNo($pos) {
+ return 1 + substr_count(substr($this->buffer, 0, $pos), "\n");
+ }
+
+ /**
+ * Match string looking for either ending delim, escape, or string interpolation
+ *
+ * {@internal This is a workaround for preg_match's 250K string match limit. }}
+ *
+ * @param array $m Matches (passed by reference)
+ * @param string $delim Delimeter
+ *
+ * @return boolean True if match; false otherwise
+ */
+ protected function matchString(&$m, $delim) {
+ $token = null;
+
+ $end = strpos($this->buffer, "\n", $this->count);
+ if ($end === false || $this->buffer[$end - 1] == '\\' || $this->buffer[$end - 2] == '\\' && $this->buffer[$end - 1] == "\r") {
+ $end = strlen($this->buffer);
+ }
+
+ // look for either ending delim, escape, or string interpolation
+ foreach (array('#{', '\\', $delim) as $lookahead) {
+ $pos = strpos($this->buffer, $lookahead, $this->count);
+ if ($pos !== false && $pos < $end) {
+ $end = $pos;
+ $token = $lookahead;
+ }
+ }
+
+ if (!isset($token)) {
+ return false;
+ }
+
+ $match = substr($this->buffer, $this->count, $end - $this->count);
+ $m = array(
+ $match . $token,
+ $match,
+ $token
+ );
+ $this->count = $end + strlen($token);
+
+ return true;
+ }
+
+ // try to match something on head of buffer
+ protected function match($regex, &$out, $eatWhitespace = null) {
+ if (!isset($eatWhitespace)) $eatWhitespace = $this->eatWhiteDefault;
+
+ $r = '/'.$regex.'/Ais';
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+ if ($eatWhitespace) $this->whitespace();
+ return true;
+ }
+ return false;
+ }
+
+ // match some whitespace
+ protected function whitespace() {
+ $gotWhite = false;
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if ($this->insertComments) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->append(array("comment", $m[1]));
+ $this->commentsSeen[$this->count] = true;
+ }
+ }
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
+ }
+ return $gotWhite;
+ }
+
+ protected function peek($regex, &$out, $from=null) {
+ if (!isset($from)) $from = $this->count;
+
+ $r = '/'.$regex.'/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ protected function seek($where = null) {
+ if ($where === null) return $this->count;
+ else $this->count = $where;
+ return true;
+ }
+
+ static function preg_quote($what) {
+ return preg_quote($what, '/');
+ }
+
+ protected function show() {
+ if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
+ return $m[1];
+ }
+ return "";
+ }
+
+ // turn list of length 1 into value type
+ protected function flattenList($value) {
+ if ($value[0] == "list" && count($value[2]) == 1) {
+ return $this->flattenList($value[2][0]);
+ }
+ return $value;
+ }
+}
+
+/**
+ * SCSS base formatter
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_formatter {
+ public $indentChar = " ";
+
+ public $break = "\n";
+ public $open = " {";
+ public $close = "}";
+ public $tagSeparator = ", ";
+ public $assignSeparator = ": ";
+
+ public function __construct() {
+ $this->indentLevel = 0;
+ }
+
+ public function indentStr($n = 0) {
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
+ public function property($name, $value) {
+ return $name . $this->assignSeparator . $value . ";";
+ }
+
+ protected function block($block) {
+ if (empty($block->lines) && empty($block->children)) return;
+
+ $inner = $pre = $this->indentStr();
+
+ if (!empty($block->selectors)) {
+ echo $pre .
+ implode($this->tagSeparator, $block->selectors) .
+ $this->open . $this->break;
+ $this->indentLevel++;
+ $inner = $this->indentStr();
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!empty($block->children)) {
+ echo $this->break;
+ }
+ }
+
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel--;
+ if (empty($block->children)) echo $this->break;
+ echo $pre . $this->close . $this->break;
+ }
+ }
+
+ public function format($block) {
+ ob_start();
+ $this->block($block);
+ $out = ob_get_clean();
+
+ return $out;
+ }
+}
+
+/**
+ * SCSS nested formatter
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_formatter_nested extends scss_formatter {
+ public $close = " }";
+
+ // adjust the depths of all children, depth first
+ public function adjustAllChildren($block) {
+ // flatten empty nested blocks
+ $children = array();
+ foreach ($block->children as $i => $child) {
+ if (empty($child->lines) && empty($child->children)) {
+ if (isset($block->children[$i + 1])) {
+ $block->children[$i + 1]->depth = $child->depth;
+ }
+ continue;
+ }
+ $children[] = $child;
+ }
+
+ $count = count($children);
+ for ($i = 0; $i < $count; $i++) {
+ $depth = $children[$i]->depth;
+ $j = $i + 1;
+ if (isset($children[$j]) && $depth < $children[$j]->depth) {
+ $childDepth = $children[$j]->depth;
+ for (; $j < $count; $j++) {
+ if ($depth < $children[$j]->depth && $childDepth >= $children[$j]->depth) {
+ $children[$j]->depth = $depth + 1;
+ }
+ }
+ }
+ }
+
+ $block->children = $children;
+
+ // make relative to parent
+ foreach ($block->children as $child) {
+ $this->adjustAllChildren($child);
+ $child->depth = $child->depth - $block->depth;
+ }
+ }
+
+ protected function block($block) {
+ if ($block->type == "root") {
+ $this->adjustAllChildren($block);
+ }
+
+ $inner = $pre = $this->indentStr($block->depth - 1);
+ if (!empty($block->selectors)) {
+ echo $pre .
+ implode($this->tagSeparator, $block->selectors) .
+ $this->open . $this->break;
+ $this->indentLevel++;
+ $inner = $this->indentStr($block->depth - 1);
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!empty($block->children)) echo $this->break;
+ }
+
+ foreach ($block->children as $i => $child) {
+ // echo "*** block: ".$block->depth." child: ".$child->depth."\n";
+ $this->block($child);
+ if ($i < count($block->children) - 1) {
+ echo $this->break;
+
+ if (isset($block->children[$i + 1])) {
+ $next = $block->children[$i + 1];
+ if ($next->depth == max($block->depth, 1) && $child->depth >= $next->depth) {
+ echo $this->break;
+ }
+ }
+ }
+ }
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel--;
+ echo $this->close;
+ }
+
+ if ($block->type == "root") {
+ echo $this->break;
+ }
+ }
+}
+
+/**
+ * SCSS compressed formatter
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_formatter_compressed extends scss_formatter {
+ public $open = "{";
+ public $tagSeparator = ",";
+ public $assignSeparator = ":";
+ public $break = "";
+
+ public function indentStr($n = 0) {
+ return "";
+ }
+}
+
+/**
+ * SCSS server
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_server {
+ /**
+ * Join path components
+ *
+ * @param string $left Path component, left of the directory separator
+ * @param string $right Path component, right of the directory separator
+ *
+ * @return string
+ */
+ protected function join($left, $right) {
+ return rtrim($left, '/\\') . DIRECTORY_SEPARATOR . ltrim($right, '/\\');
+ }
+
+ /**
+ * Get name of requested .scss file
+ *
+ * @return string|null
+ */
+ protected function inputName() {
+ switch (true) {
+ case isset($_GET['p']):
+ return $_GET['p'];
+ case isset($_SERVER['PATH_INFO']):
+ return $_SERVER['PATH_INFO'];
+ case isset($_SERVER['DOCUMENT_URI']):
+ return substr($_SERVER['DOCUMENT_URI'], strlen($_SERVER['SCRIPT_NAME']));
+ }
+ }
+
+ /**
+ * Get path to requested .scss file
+ *
+ * @return string
+ */
+ protected function findInput() {
+ if (($input = $this->inputName())
+ && strpos($input, '..') === false
+ && substr($input, -5) === '.scss'
+ ) {
+ $name = $this->join($this->dir, $input);
+
+ if (is_file($name) && is_readable($name)) {
+ return $name;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get path to cached .css file
+ *
+ * @return string
+ */
+ protected function cacheName($fname) {
+ return $this->join($this->cacheDir, md5($fname) . '.css');
+ }
+
+ /**
+ * Get path to cached imports
+ *
+ * @return string
+ */
+ protected function importsCacheName($out) {
+ return $out . '.imports';
+ }
+
+ /**
+ * Determine whether .scss file needs to be re-compiled.
+ *
+ * @param string $in Input path
+ * @param string $out Output path
+ *
+ * @return boolean True if compile required.
+ */
+ protected function needsCompile($in, $out) {
+ if (!is_file($out)) return true;
+
+ $mtime = filemtime($out);
+ if (filemtime($in) > $mtime) return true;
+
+ // look for modified imports
+ $icache = $this->importsCacheName($out);
+ if (is_readable($icache)) {
+ $imports = unserialize(file_get_contents($icache));
+ foreach ($imports as $import) {
+ if (filemtime($import) > $mtime) return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get If-Modified-Since header from client request
+ *
+ * @return string
+ */
+ protected function getModifiedSinceHeader()
+ {
+ $modifiedSince = '';
+
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
+ $modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+
+ if (false !== ($semicolonPos = strpos($modifiedSince, ';'))) {
+ $modifiedSince = substr($modifiedSince, 0, $semicolonPos);
+ }
+ }
+
+ return $modifiedSince;
+ }
+
+ /**
+ * Compile .scss file
+ *
+ * @param string $in Input path (.scss)
+ * @param string $out Output path (.css)
+ *
+ * @return string
+ */
+ protected function compile($in, $out) {
+ $start = microtime(true);
+ $css = $this->scss->compile(file_get_contents($in), $in);
+ $elapsed = round((microtime(true) - $start), 4);
+
+ $v = scssc::$VERSION;
+ $t = @date('r');
+ $css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css;
+
+ file_put_contents($out, $css);
+ file_put_contents($this->importsCacheName($out),
+ serialize($this->scss->getParsedFiles()));
+ return $css;
+ }
+
+ /**
+ * Compile requested scss and serve css. Outputs HTTP response.
+ *
+ * @param string $salt Prefix a string to the filename for creating the cache name hash
+ */
+ public function serve($salt = '') {
+ $protocol = isset($_SERVER['SERVER_PROTOCOL'])
+ ? $_SERVER['SERVER_PROTOCOL']
+ : 'HTTP/1.0';
+
+ if ($input = $this->findInput()) {
+ $output = $this->cacheName($salt . $input);
+
+ if ($this->needsCompile($input, $output)) {
+ try {
+ $css = $this->compile($input, $output);
+
+ $lastModified = gmdate('D, d M Y H:i:s', filemtime($output)) . ' GMT';
+
+ header('Last-Modified: ' . $lastModified);
+ header('Content-type: text/css');
+
+ echo $css;
+
+ return;
+ } catch (Exception $e) {
+ header($protocol . ' 500 Internal Server Error');
+ header('Content-type: text/plain');
+
+ echo 'Parse error: ' . $e->getMessage() . "\n";
+ }
+ }
+
+ header('X-SCSS-Cache: true');
+ header('Content-type: text/css');
+
+ $modifiedSince = $this->getModifiedSinceHeader();
+ $mtime = filemtime($output);
+
+ if (@strtotime($modifiedSince) === $mtime) {
+ header($protocol . ' 304 Not Modified');
+
+ return;
+ }
+
+ $lastModified = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
+ header('Last-Modified: ' . $lastModified);
+
+ echo file_get_contents($output);
+
+ return;
+ }
+
+ header($protocol . ' 404 Not Found');
+ header('Content-type: text/plain');
+
+ $v = scssc::$VERSION;
+ echo "/* INPUT NOT FOUND scss $v */\n";
+ }
+
+ /**
+ * Constructor
+ *
+ * @param string $dir Root directory to .scss files
+ * @param string $cacheDir Cache directory
+ * @param \scssc|null $scss SCSS compiler instance
+ */
+ public function __construct($dir, $cacheDir=null, $scss=null) {
+ $this->dir = $dir;
+
+ if (!isset($cacheDir)) {
+ $cacheDir = $this->join($dir, 'scss_cache');
+ }
+
+ $this->cacheDir = $cacheDir;
+ if (!is_dir($this->cacheDir)) mkdir($this->cacheDir, 0755, true);
+
+ if (!isset($scss)) {
+ $scss = new scssc();
+ $scss->setImportPaths($this->dir);
+ }
+ $this->scss = $scss;
+ }
+
+ /**
+ * Helper method to serve compiled scss
+ *
+ * @param string $path Root path
+ */
+ static public function serveFrom($path) {
+ $server = new self($path);
+ $server->serve();
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/site/.gitignore b/public/system/storage/vendor/leafo/scssphp/site/.gitignore
new file mode 100644
index 0000000..6cff422
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/.gitignore
@@ -0,0 +1,2 @@
+.sitegen_cache
+.tup
diff --git a/public/system/storage/vendor/leafo/scssphp/site/composer.html b/public/system/storage/vendor/leafo/scssphp/site/composer.html
new file mode 100644
index 0000000..40d6b7a
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/composer.html
@@ -0,0 +1,6 @@
+<pre class="highlight lang_json"><code><span class="p">{</span>
+ <span class="nt">&quot;require&quot;</span><span class="p">:</span> <span class="p">{</span>
+ <span class="nt">&quot;leafo/scssphp&quot;</span><span class="p">:</span> <span class="s2">&quot;$current_version&quot;</span>
+ <span class="p">}</span>
+<span class="p">}</span></code>
+</pre>
diff --git a/public/system/storage/vendor/leafo/scssphp/site/docs/index.md b/public/system/storage/vendor/leafo/scssphp/site/docs/index.md
new file mode 100644
index 0000000..1a7b607
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/docs/index.md
@@ -0,0 +1,306 @@
+ title: Documentation
+--
+
+<h1 skip="true">scssphp $current_version Documentation</h1>
+
+<div class="index">$index</div>
+
+## PHP Interface
+
+### Including
+
+The entire project comes in a single file. Just include it somewhere to start
+using it:
+
+ ```php
+ <?php
+ require "scssphp/scss.inc.php";
+ ```
+
+### Compiling
+
+In order to manually compile code from PHP you must create an instance of the
+`scssc` class. The typical flow is to create the instance, set any compile time
+options, then run the compiler with the `compile` method.
+
+ ```php
+ <?php
+ require "scssphp/scss.inc.php";
+ $scss = new scssc();
+
+ echo $scss->compile('
+ $color: #abc;
+ div { color: lighten($color, 20%); }
+ ');
+ ```
+
+* <p>`compile($scssCode)` will attempt to compile a string of SCSS code. If it
+ succeeds then the CSS will be returned as a string. If there is any error, an
+ exception is thrown with an appropriate error message.
+ </p>
+
+### Import Paths
+
+When you import a file using the `@import` directive, the current path of your
+PHP script is used as the search path by default. This is often not what
+you want, so there are two methods for manipulating the import path:
+`addImportPath`, and `setImportPaths`.
+
+* `addImportPath($path)` will append `$path` to the list of the import
+ paths that are searched.
+
+* `setImportPaths($pathArray)` will replace the entire import path with
+ `$pathArray`. The value of `$pathArray` will be converted to an array if it
+ isn't one already.
+
+If the import path is set to `array()` then importing is effectively disabled.
+The default import path is `array("")`, which means the current directory.
+
+ ```php
+ <?php
+ require "scssphp/scss.inc.php";
+ $scss = new scssc();
+ $scss->setImportPaths("assets/stylesheets/");
+
+ // will search for `assets/stylesheets/mixins.scss'
+ echo $scss->compile('@import "mixins.scss"');
+ ```
+
+Besides adding static import paths, it's also possible to add custom import
+functions. This allows you to load paths from a database, or HTTP, or using
+files that SCSS would otherwise not process (such as vanilla CSS imports).
+
+ ```php
+ <?php
+ require "scssphp/scss.inc.php";
+ $scss = new scssc();
+ $scss->addImportPath(function($path) {
+ if (!file_exists('stylesheets/'.$path)) return null;
+ return 'stylesheets/'.$path;
+ });
+
+ // will import `stylesheets/vanilla.css'
+ echo $scss->compile('@import "vanilla.css"');
+ ```
+
+### Output Formatting
+
+It's possible to customize the formatting of the output CSS by changing the
+default formatter.
+
+Three formatters are included:
+
+* `scss_formatter`
+* `scss_formatter_nested` *(default)*
+* `scss_formatter_compressed`
+
+We can change the formatting using the `setFormatter` method.
+
+* <p>`setFormatter($formatterName)` sets the current formatter to `$formatterName`,
+ the name of a class as a string that implements the formatting interface. See
+ the source for `scss_formatter` for an example.
+ </p>
+
+Given the following SCSS:
+
+ ```scss
+ .navigation {
+ ul {
+ line-height: 20px;
+ color: blue;
+ a {
+ color: red;
+ }
+ }
+ }
+
+ .footer {
+ .copyright {
+ color: silver;
+ }
+ }
+ ```
+
+The formatters will output,
+
+`scss_formatter`:
+
+ ```css
+ .navigation ul {
+ line-height: 20px;
+ color: blue;
+ }
+ .navigation ul a {
+ color: red;
+ }
+ .footer .copyright {
+ color: silver;
+ }
+ ```
+
+`scss_formatter_nested`:
+
+ ```css
+ .navigation ul {
+ line-height: 20px;
+ color: blue; }
+ .navigation ul a {
+ color: red; }
+
+ .footer .copyright {
+ color: silver; }
+ ```
+
+`scss_formatter_compressed`:
+
+ ```css
+ .navigation ul{line-height:20px;color:blue;}.navigation ul a{color:red;}.footer .copyright{color:silver;}
+ ```
+
+### Custom Functions
+
+It's possible to register custom functions written in PHP that can be called
+from SCSS. Some possible applications include appending your assets directory
+to a URL with an `asset-url` function, or converting image URLs to an embedded
+data URI to reduce the number of requests on a page with a `data-uri` function.
+
+We can add and remove functions using the methods `registerFunction` and
+`unregisterFunction`.
+
+* `registerFunction($functionName, $callable)` assigns the callable value to
+ the name `$functionName`. The name is normalized using the rules of SCSS.
+ Meaning underscores and dashes are interchangeable. If a function with the
+ same name already exists then it is replaced.
+
+* `unregisterFunction($functionName)` removes `$functionName` from the list of
+ available functions.
+
+
+The `$callable` can be anything that PHP knows how to call using
+`call_user_func`. The function receives two arguments when invoked. The first
+is an array of SCSS typed arguments that the function was sent. The second is a
+reference to the current `scss` instance.
+
+The *SCSS typed arguments* are actually just arrays that represent SCSS values.
+SCSS has different types than PHP, and this is how **scssphp** represents them
+internally.
+
+For example, the value `10px` in PHP would be `array("number", 1, "px")`. There
+is a large variety of types. Experiment with a debugging function like `print_r`
+to examine the possible inputs.
+
+The return value of the custom function can either be a SCSS type or a basic
+PHP type. (such as a string or a number) If it's a PHP type, it will be converted
+automatically to the corresponding SCSS type.
+
+As an example, a function called `add-two` is registered, which adds two numbers
+together. PHP's anonymous function syntax is used to define the function.
+
+ ```php
+ <?php
+ $scss = new scssc();
+
+ $scss->registerFunction("add-two", function($args) {
+ list($a, $b) = $args;
+ return $a[1] + $b[1];
+ });
+
+ $scss->compile('.ex1 { result: add-two(10, 10); }');
+ ```
+
+It's worth noting that in this example we lose the units of the number, and we
+also don't do any type checking. This will have undefined results if we give it
+anything other than two numbers.
+
+
+## SCSS Server
+
+The SCSS server is a small class that helps with automatically compiling SCSS.
+
+It's an endpoint for your web application that searches for SCSS files in a
+directory then compiles and serves them as CSS. It will only compile
+files if they've been modified (or one of the imports has been modified).
+
+### Using `serveFrom`
+
+`scss_server::serveFrom` is a simple to use function that should handle most cases.
+
+For example, create a file `style.php`:
+
+ ```php
+ <?php
+ $directory = "stylesheets";
+
+ require "scssphp/scss.inc.php";
+ scss_server::serveFrom($directory);
+ ```
+
+Going to the URL `example.com/style.php/style.scss` will attempt to compile
+`style.scss` from the `stylesheets` directory, and serve it as CSS.
+
+* <p>`scss_server::serveFrom($directory)` will serve SCSS files out of
+ `$directory`. It will attempt to get the path to the file out of
+ `$_SERVER["PATH_INFO"]`. (It also looks at the GET parameter `p`)
+ </p>
+
+If it can not find the file it will return an HTTP 404 page:
+
+ ```text
+ /* INPUT NOT FOUND scss v0.0.1 */
+ ```
+
+If the file can't be compiled due to an error, then an HTTP 500 page is
+returned. Similar to the following:
+
+ ```text
+ Parse error: parse error: failed at `height: ;` stylesheets/test.scss on line 8
+ ```
+
+By default , the SCSS server must have write access to the style sheet
+directory. It writes its cache in a special directory called `scss_cache`.
+
+Also, because SCSS server writes headers, make sure no output is written before
+it runs.
+
+### Using `scss_server`
+
+Creating an instance of `scss_server` is just another way of accomplishing what
+`serveFrom` does. It let's us customize the cache directory and the instance
+of the `scssc` that is used to compile
+
+
+* <p>`new scss_server($sourceDir, $cacheDir, $scss)` creates a new server that
+ serves files from `$sourceDir`. The cache dir is where the cached compiled
+ files are placed. When `null`, `$sourceDir . "/scss_cache"` is used. `$scss`
+ is the instance of `scss` that is used to compile.
+ </p>
+
+Just call the `serve` method to let it render its output.
+
+Here's an example of creating a SCSS server that outputs compressed CSS:
+
+ ```php
+ <?php
+ require "scssphp/scss.inc.php";
+
+ $scss = new scssc();
+ $scss->setFormatter("scss_formatter_compressed");
+
+ $server = new scss_server("stylesheets", null, $scss);
+ $server->serve();
+ ```
+
+
+## Command Line Tool
+
+A really basic command line tool is included for integration with scripts. It
+is called `pscss`. It reads a SCSS file from standard out and returns the CSS.
+
+If passed the flag `-v`, input is ignored and the current version if returned.
+
+The flag `-f` can be used to set the [formatter](#Output_formatting):
+
+ ```bash
+ $ ./pscss -f scss_formatter_compressed < styles.scss
+ ```
+
diff --git a/public/system/storage/vendor/leafo/scssphp/site/index.md b/public/system/storage/vendor/leafo/scssphp/site/index.md
new file mode 100644
index 0000000..da028da
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/index.md
@@ -0,0 +1,210 @@
+**scssphp** is a compiler for [SCSS][0] written in PHP.
+
+SCSS is a CSS preprocessor that adds many features like variables, mixins,
+imports, color manipulation, functions, and tons of other powerful features.
+
+The entire compiler comes in a single class file ready for including in any
+kind of project in addition to a command line tool for running the compiler
+from the terminal.
+
+**scssphp** implements SCSS (3.2.12). It does not implement the SASS syntax,
+only the SCSS syntax.
+
+Follow the author on twitter: [@moonscript](http://twitter.com/moonscript).
+
+<div class="github-buttons">
+<iframe src="http://ghbtns.com/github-btn.html?user=leafo&repo=scssphp&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
+<iframe src="http://ghbtns.com/github-btn.html?user=leafo&repo=scssphp&type=fork&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="95px" height="20px"></iframe>
+</div>
+
+<a name="installing"></a>
+## Installing
+
+You can always download the latest version here:
+<a href="$root/src/scssphp-$current_version.tar.gz" id="download-link">scssphp-$current_version.tar.gz</a>
+
+You can also find the latest source online:
+<https://github.com/leafo/scssphp/>
+
+If you use [Packagist][2] for installing packages, then you can update your `composer.json` like so:
+
+$render{[[composer]]}
+
+<a name="quickstart"></a>
+## Language Reference
+
+For a complete guide to the syntax of SCSS, consult the [official documentation][1].
+
+## PHP Reference
+
+Complete documentation for **scssphp** is located at <a href="$root/docs/">http://leafo.net/scssphp/docs/</a>.
+
+### Quickstart
+
+If you just want to start serving compiled `scss` files as quick as possible
+then start here.
+
+**scssphp** comes with a easy to use class that automatically compiles modified
+`scss` files and serves them from a directory you specify.
+
+Create a file, like `style.php`:
+
+ ```php
+ <?php
+ $directory = "stylesheets";
+
+ require "scssphp/scss.inc.php";
+ scss_server::serveFrom($directory);
+
+ ```
+
+Create the directory set in the script alongside the script, then add your
+`scss` files to it.
+
+If we've got a file in there called `style.scss`, then we just need to hit the
+url: `example.com/style.php/style.scss` to get the compiled css.
+
+If there is an error compiling, the url will result in a `500` error with the
+error message. If the file can't be found, then a friendly `404` is returned.
+
+**scssphp** will automatically create a `scss_cache` directory inside the
+stylesheets directory where it will cache the compiled output. This way it can
+quickly serve the files if no modifications have been made. Your PHP script
+must have permission to write in `scss_cache`.
+
+### Compiler Interface
+
+If you're interested in directly using the compiler, then all you need to do is
+require `scss.inc.php` and invoke the `scss` class:
+
+ ```php
+ <?php
+ require "scssphp/scss.inc.php";
+ $scss = new scssc();
+
+ echo $scss->compile('
+ $color: #abc;
+ div { color: lighten($color, 20%); }
+ ');
+
+ ```
+
+The `compile` method takes `SCSS` as a string, and returns the `CSS`. If there
+is an error when compiling then an exception is thrown with an appropriate
+message.
+
+
+For a more detailed guide consult <a href="$root/docs/">http://leafo.net/scssphp/docs/</a>.
+
+<a name="issues"></a>
+## Issues
+
+Find any issues? I'd love to fix them for you, post about them on [the issues tracker][3].
+
+<div id="changelog"></div>
+## Changelog
+
+* **0.0.12** -- July 6, 2014
+ * revert erroneous import-partials-fix (smuuf)
+ * handle If-Modified-Since in client request, and send Last-Modified in response (braver)
+ * add hhvm to travis-ci testing
+* **0.0.11** -- July 5, 2014
+ * support multi-line continuation character (backslash)per CSS2.1 and CSS3 spec (caiosm1005)
+ * imported partials should not be compiled (squarestar)
+ * add setVariables() and unsetVariable() to interface (leafo/lessphp)
+ * micro-optimizing is_null() (Yahasana)
+* **0.0.10** -- April 14, 2014
+ * fix media query merging (timonbaetz)
+ * inline if should treat null as false (wonderslug)
+ * optimizing toHSL() (jfsullivan)
+* **0.0.9** -- December 23, 2013
+ * fix @for/@while inside @content block (sergeylukin)
+ * fix functions in mixin_content (timonbaetz)
+ * fix infinite loop when target extends itself (oscherler)
+ * fix function arguments are lost inside of @content block
+ * allow setting number precision (kasperisager)
+ * add public function helpers (toBool, get, findImport, assertList, assertColor, assertNumber, throwError) (Burgov, atdt)
+ * add optional cache buster prefix to serve() method (iMoses)
+* **0.0.8** -- September 16, 2013
+ * Avoid IE7 content: counter bug
+ * Support transparent as color name
+ * Recursively create cache dir (turksheadsw)
+ * Fix for INPUT NOT FOUND (morgen32)
+* **0.0.7** -- May 24, 2013
+ * Port various fixes from leafo/lessphp.
+ * Improve filter precision.
+ * Parsing large image data-urls does not work.
+ * Add == and != ops for colors.
+ * @if and @while directives should treat null like false.
+ * Add pscss as bin in composer.json (Christian Lück).
+ * Fix !default bug (James Shannon, Alberto Aldegheri).
+ * Fix mixin content includes (James Shannon, Christian Brandt).
+ * Fix passing of varargs to another mixin.
+ * Fix interpolation bug in expToString() (Matti Jarvinen).
+* **0.0.5** -- March 11, 2013
+ * Better compile time errors
+ * Fix top level properties inside of a nested `@media` (Anthon Pang)
+ * Fix some issues with `@extends` (Anthon Pang)
+ * Enhanced handling of `null` (Anthon Pang)
+ * Helper functions shouldn't mix with css builtins (Anthon Pang)
+ * Enhance selector parsing (Guilherme Blanco, Anthon Pang)
+ * Add Placeholder selector support (Martin Hasoň)
+ * Add variable argument support (Martin Hasoň)
+ * Add zip, index, comparable functions (Martin Hasoň)
+ * A bunch of parser and bug fixes
+* **0.0.4** -- Nov 3nd, 2012
+ * [Import path can be a function](docs/#import_paths) (Christian Lück).
+ * Correctly parse media queries with more than one item (Christian Lück).
+ * Add `ie_hex_str`, `abs`, `min`, `max` functions (Martin Hasoň)
+ * Ignore expressions inside of `calc()` (Martin Hasoň)
+ * Improve operator evaluation (Martin Hasoň)
+ * Add [`@content`](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixin-content) support.
+ * Misc bug fixes.
+* **0.0.3** -- August 2nd, 2012
+ * Add missing and/or/not operators.
+ * Expression evaluation happens correctly.
+ * Import file caching and _partial filename support.
+ * Misc bug fixes.
+* **0.0.2** -- July 30th, 2012
+ * SCSS server is aware of imports
+ * added custom function interface
+ * compressed formatter
+ * wrote <a href="http://leafo.net/scssphp/docs/">documentation</a>
+* Initial Release v0.0.1 -- July 29th, 2012
+
+<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
+<script type="text/javascript">
+(function() {
+ var changelog = jQuery("#changelog").nextAll("ul:first");
+ var hidden = changelog.children("li").slice(1).hide();
+ if (hidden.length) {
+ var show_all = jQuery("<a href=''>Show All</a>").insertAfter(changelog).on("click", function() {
+ hidden.show();
+ show_all.remove();
+ return false;
+ });
+ }
+})();
+</script>
+
+<a name="comments"></a>
+## Comments
+
+<div class="comments" id="disqus_thread"></div>
+<script type="text/javascript">
+ var disqus_shortname = 'leafo';
+ var disqus_url = 'http://leafo.net/scssphp/';
+
+ (function() {
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
+ })();
+</script>
+
+
+ [0]: http://sass-lang.com/
+ [1]: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#css_extensions
+ [2]: http://packagist.org/
+ [3]: https://github.com/leafo/scssphp/issues
+ [4]: https://github.com/leafo/scssphp/
diff --git a/public/system/storage/vendor/leafo/scssphp/site/site.moon b/public/system/storage/vendor/leafo/scssphp/site/site.moon
new file mode 100644
index 0000000..35d8aa4
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/site.moon
@@ -0,0 +1,15 @@
+require "sitegen"
+
+tools = require "sitegen.tools"
+
+sitegen.create_site =>
+ @current_version = "0.0.12"
+ @title = "SCSS Compiler in PHP"
+
+ scssphp = tools.system_command "pscss < %s > %s", "css"
+ build scssphp, "style.scss", "style/style.css"
+
+ deploy_to "leaf@leafo.net", "www/scssphp/"
+
+ add "docs/index.md"
+
diff --git a/public/system/storage/vendor/leafo/scssphp/site/style.scss b/public/system/storage/vendor/leafo/scssphp/site/style.scss
new file mode 100644
index 0000000..18ecc09
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/style.scss
@@ -0,0 +1,303 @@
+
+$site_width: 640px;
+
+$light_teal: #7FC7AF;
+$teal: desaturate(#3FB8AF, 10%);
+$brown: #DAD8A7;
+$pink: darken(#FF9E9D, 10%);
+$btn_color: desaturate(#FF3D7F, 10%);
+
+::selection {
+ background: red;
+ color: white;
+}
+
+@mixin unselectable {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
+
+@mixin grad($top, $bottom) {
+ background-color: mix($top, $bottom);
+ background-image: linear-gradient(bottom, $bottom 0%, $top 100%);
+ background-image: -webkit-linear-gradient(bottom, $bottom 0%, $top 100%);
+ background-image: -moz-linear-gradient(bottom, $bottom 0%, $top 100%);
+ background-image: -o-linear-gradient(bottom, $bottom 0%, $top 100%);
+ background-image: -ms-linear-gradient(bottom, $bottom 0%, $top 100%);
+}
+
+@mixin autograd($color, $amount: 10%) {
+ @include grad($color, darken($color, $amount));
+}
+
+body {
+ background: $pink;
+ font-family: Lato, sans-serif;
+}
+
+.header, .footer, .body {
+ .inner {
+ width: $site_width;
+ margin: 0 auto;
+ }
+}
+
+.header {
+ text-shadow: 0px -1px 0px darken($teal, 15%);
+
+ .color {
+ background: $teal url(../img/tile.png);
+ border-top: 4px solid $light_teal;
+ box-shadow: inset 0px 1px 0px rgba(255,255,255, 0.5), inset 0px 8px 8px -8px #37505A, inset 0px -1px 0px rgba(255,255,255, 0.3);
+ }
+
+ h1 {
+ font-family: 'Quicksand', sans-serif;
+ font-size: 40px;
+ line-height: 100px;
+ font-weight: normal;
+ margin: 0;
+
+ a {
+ text-decoration: none;
+ color: #EDFFF9;
+
+ &:active {
+ position: relative;
+ top: 1px;
+ }
+ }
+ }
+
+ .nav {
+ padding: 8px 0;
+ font-size: 17px;
+ text-shadow: none;
+ background: darken($teal, 30%);
+ color: $teal;
+ box-shadow: inset 0px 4px 8px -4px rgba(0,0,0,0.9), inset 0px -1px 0px rgba(255,255,255, 0.8);
+
+ a {
+ color: lighten($teal, 40%);
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+
+ .social {
+ float: right;
+ margin-top: -2px;
+ }
+ }
+
+ .download-area {
+ float: right;
+ margin-top: 25px;
+ background: rgba(255,255,255, 0.3);
+ border-radius: 8px;
+ padding: 5px;
+
+ a {
+ text-decoration: none;
+ }
+
+ .download-button {
+ $height: 8px;
+ $depress: 4px;
+
+ @include unselectable;
+
+ color: white;
+ text-align: center;
+
+ @include autograd($btn_color);
+
+ position: relative;
+ top: -1 * $height;
+
+ padding: 8px 20px;
+ border-radius: 8px;
+ text-shadow: none;
+
+ box-shadow: 0px $height 0px darken($btn_color, 30%), inset 0px -1px 0px rgba(255,255,255, 0.2), inset 0px 1px 0px rgba(0,0,0, 0.2);
+ text-shadow: 0px 1px 2px darken($btn_color, 40%);
+
+ cursor: pointer;
+
+ -webkit-transition: all 0.05s ease-in-out;
+ -moz-transition: all 0.05s ease-in-out;
+ transition: all 0.05s ease-in-out;
+
+ &:hover {
+ @include autograd(lighten($btn_color, 3%));
+ }
+
+ &:active {
+ box-shadow: 0px $height - $depress 0px darken($btn_color, 30%), inset 0px -1px 0px rgba(255,255,255, 0.2), inset 0px 1px 0px rgba(0,0,0, 0.2);
+ top: -1 * ($height - $depress);
+ }
+
+ .top {
+ font-weight: bold;
+ font-size: 16px;
+ }
+
+ .sub {
+ font-size: 14px;
+ }
+ }
+ }
+
+}
+
+.body {
+ $bg_color: #FEFFED;
+ $text_color: darken($brown, 60%);
+ box-shadow: inset 0px 4px 8px -4px rgba(0,0,0,0.7), inset 0px -4px 8px -4px rgba(0,0,0,0.4);
+ background: $bg_color;
+ overflow: hidden;
+ color: $text_color;
+ font-size: 18px;
+ padding-bottom: 20px;
+
+ .inner {
+ background: white;
+ margin-top: 20px;
+ padding: 30px 50px;
+ border: 1px solid lightGrey;
+ box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.19);
+
+ h1, h2, h3 {
+ margin: 0 0 20px 0;
+ }
+ }
+
+ h1, h2, h3 {
+ text-shadow: 1px 1px 0px $bg_color, 2px 2px 0px rgba($text_color, 0.3);
+ letter-spacing: -1px;
+ }
+
+ h3 {
+ color: #4D4C3D;
+ }
+
+ p {
+ margin: 0 0 15px 0;
+ }
+
+ a {
+ color: #DB1C4A;
+ &:hover {
+ color: lighten(#DB1C4A, 10%);
+ }
+ }
+
+ pre {
+ margin: 20px 0;
+ }
+}
+
+.footer {
+ font-size: 16px;
+ color: lighten($pink, 20%);
+ text-shadow: 0px 1px 0px darken($pink, 20%);
+
+ border-top: 1px dashed darken($pink, 50%);
+ box-shadow: inset 0px 1px 0px rgba(255,255,255, 0.5);
+ padding: 8px 0 20px 0;
+
+ line-height: 150%;
+
+ a {
+ color: white;
+ font-weight: bold;
+ text-decoration: none;
+ padding: 0 4px;
+ border-radius: 4px;
+ border: 1px solid lighten($pink, 4%);
+
+ &:hover {
+ background: darken($pink, 3%);
+ border: 1px solid lighten($pink, 4%);
+ }
+ }
+}
+
+
+p {
+ line-height: 150%;
+ code {
+ background: rgba(0,0,0, 0.1);
+ border-radius: 4px;
+ padding: 1px 4px;
+ }
+}
+
+.comments {
+ font-size: 12px;
+}
+
+.index {
+ line-height: 150%;
+ margin-bottom: 20px;
+
+ ul {
+ margin: 0;
+ }
+}
+
+.highlight {
+ background: #333;
+ color: white;
+ font-size: 14px;
+ padding: 10px;
+ box-shadow: 0px 1px 3px rgba(0,0,0, 0.7), inset 0px 0px 0px 1px rgba(255,255,255,0.3);
+ border-radius: 2px;
+ border: 1px solid #222;
+
+
+ // builtins
+ .nb {
+ color: #FFA67C;
+ }
+
+ // strings
+ .s, .s1, .s2, .se, .nt {
+ color: #ffe898;
+ }
+
+ // proper names
+ .nc, .vc, .bp {
+ color: #98d9ff;
+ }
+
+ // true, false, nil
+ .kc {
+ color: #acfff0;
+ }
+
+ // function lit, braces, parens
+ .nf, .kt {
+ color: #9fff98;
+ }
+
+ .nv {
+ color: #ff9898;
+ }
+
+ // keywords
+ .k, .kd, .na {
+ color: #cb98ff;
+ }
+
+ .c1, .c2 {
+ color: #929292;
+ }
+
+ .m, .mi, .mf, .mh, .o {
+ color: #9495ff;
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/site/templates/index.html b/public/system/storage/vendor/leafo/scssphp/site/templates/index.html
new file mode 100644
index 0000000..587b691
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/templates/index.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>$if{"title"}[[$title - ]]scssphp</title>
+ <link href='http://fonts.googleapis.com/css?family=Lato:400,900|Quicksand' rel='stylesheet' type='text/css'>
+ <link rel="stylesheet" href="$root/style/normalize.css" />
+ <link rel="stylesheet" href="$root/style/style.css?$generate_date" />
+ $analytics{"UA-136625-1"}
+</head>
+<body>
+ <div class="header">
+ <div class="color">
+ <div class="inner">
+ <div class="download-area">
+ <a href="$root/src/scssphp-$current_version.tar.gz">
+ <div class="download-button" id="download-button">
+ <div class="top">Download</div>
+ <div class="sub">scssphp-$current_version.tar.gz</div>
+ </div>
+ </a>
+ </div>
+
+ <h1><a href="$root">scssphp</a></h1>
+ </div>
+ </div>
+
+ <div class="nav">
+ <div class="inner">
+ <div class="social">
+ <a href="https://twitter.com/share" class="twitter-share-button" data-url="http://leafo.net/scssphp/" data-text="scssphp v$current_version - SCSS compiler for PHP" data-count="horizontal" data-via="moonscript">Tweet</a><script type="text/javascript" src="//platform.twitter.com/widgets.js"></script>
+ <a href="https://twitter.com/moonscript" class="twitter-follow-button" data-width="70px" data-show-count="false" data-show-screen-name="false">Follow @moonscript</a>
+ </div>
+
+ <a href="$root/#installing">Install</a>
+ &middot;
+ <a href="$root/#quickstart">Quickstart</a>
+ &middot;
+ <a href="$root/docs/">Docs</a>
+ &middot;
+ <a href="$root/#comments">Comments</a>
+ </div>
+ </div>
+
+ </div>
+
+ <div class="body">
+ <div class="inner">
+ $body
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="inner">
+ <div>
+ created by <a href="http://leafo.net">leaf corcoran</a> &middot; scssphp is licensed under GPL3/MIT
+ </div>
+ <div>
+ generated by <a href="http://github.com/leafo/sitegen">sitegen</a> on $generate_date
+ </div>
+ </div>
+ </div>
+
+ <script type="text/javascript">
+ (function() {
+ document.getElementById("download-button").onclick = function() {
+ _gaq.push(['_trackEvent', 'scssphp', 'click', 'download-button']);
+ }
+ var link = document.getElementById("download-link");
+ if (link) link.onclick = function() {
+ _gaq.push(['_trackEvent', 'scssphp', 'click', 'download-link']);
+ }
+ })();
+ </script>
+
+ <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
+
+
+ <a href="https://github.com/leafo/scssphp"><img style="position: fixed; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub"></a>
+</body>
+</html>
diff --git a/public/system/storage/vendor/leafo/scssphp/site/www/.gitignore b/public/system/storage/vendor/leafo/scssphp/site/www/.gitignore
new file mode 100644
index 0000000..e821797
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/www/.gitignore
@@ -0,0 +1,2 @@
+docs/index.html
+index.html \ No newline at end of file
diff --git a/public/system/storage/vendor/leafo/scssphp/site/www/img/tile.png b/public/system/storage/vendor/leafo/scssphp/site/www/img/tile.png
new file mode 100644
index 0000000..ecb7149
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/www/img/tile.png
Binary files differ
diff --git a/public/system/storage/vendor/leafo/scssphp/site/www/style/normalize.css b/public/system/storage/vendor/leafo/scssphp/site/www/style/normalize.css
new file mode 100644
index 0000000..8fa27e0
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/site/www/style/normalize.css
@@ -0,0 +1,500 @@
+/*! normalize.css 2012-07-07T09:50 UTC - http://github.com/necolas/normalize.css */
+
+/* ==========================================================================
+ HTML5 display definitions
+ ========================================================================== */
+
+/*
+ * Corrects `block` display not defined in IE6/7/8/9 & FF3.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/*
+ * Corrects `inline-block` display not defined in IE6/7/8/9 & FF3.
+ */
+
+audio,
+canvas,
+video {
+ display: inline-block;
+ *display: inline;
+ *zoom: 1;
+}
+
+/*
+ * Prevents modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/*
+ * Addresses styling for `hidden` attribute not present in IE7/8/9, FF3, S4.
+ * Known issue: no IE6 support.
+ */
+
+[hidden] {
+ display: none;
+}
+
+/* ==========================================================================
+ Base
+ ========================================================================== */
+
+/*
+ * 1. Corrects text resizing oddly in IE6/7 when body `font-size` is set using
+ * `em` units.
+ * 2. Prevents iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-size: 100%; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+ -ms-text-size-adjust: 100%; /* 2 */
+}
+
+/*
+ * Addresses `font-family` inconsistency between `textarea` and other form
+ * elements.
+ */
+
+html,
+button,
+input,
+select,
+textarea {
+ font-family: sans-serif;
+}
+
+/*
+ * Addresses margins handled incorrectly in IE6/7.
+ */
+
+body {
+ margin: 0;
+}
+
+/* ==========================================================================
+ Links
+ ========================================================================== */
+
+/*
+ * Addresses `outline` inconsistency between Chrome and other browsers.
+ */
+
+a:focus {
+ outline: thin dotted;
+}
+
+/*
+ * Improves readability when focused and also mouse hovered in all browsers.
+ * people.opera.com/patrickl/experiments/keyboard/test
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* ==========================================================================
+ Typography
+ ========================================================================== */
+
+/*
+ * Addresses font sizes and margins set differently in IE6/7.
+ * Addresses font sizes within `section` and `article` in FF4+, Chrome, S5.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+h2 {
+ font-size: 1.5em;
+ margin: 0.83em 0;
+}
+
+h3 {
+ font-size: 1.17em;
+ margin: 1em 0;
+}
+
+h4 {
+ font-size: 1em;
+ margin: 1.33em 0;
+}
+
+h5 {
+ font-size: 0.83em;
+ margin: 1.67em 0;
+}
+
+h6 {
+ font-size: 0.75em;
+ margin: 2.33em 0;
+}
+
+/*
+ * Addresses styling not present in IE7/8/9, S5, Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/*
+ * Addresses style set to `bolder` in FF3+, S4/5, Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+blockquote {
+ margin: 1em 40px;
+}
+
+/*
+ * Addresses styling not present in S5, Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/*
+ * Addresses styling not present in IE6/7/8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/*
+ * Addresses margins set differently in IE6/7.
+ */
+
+p,
+pre {
+ margin: 1em 0;
+}
+
+/*
+ * Corrects font family set oddly in IE6, S4/5, Chrome.
+ * en.wikipedia.org/wiki/User:Davidgothberg/Test59
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, serif;
+ _font-family: 'courier new', monospace;
+ font-size: 1em;
+}
+
+/*
+ * Improves readability of pre-formatted text in all browsers.
+ */
+
+pre {
+ white-space: pre;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+/*
+ * Addresses CSS quotes not supported in IE6/7.
+ */
+
+q {
+ quotes: none;
+}
+
+/*
+ * Addresses `quotes` property not supported in S4.
+ */
+
+q:before,
+q:after {
+ content: '';
+ content: none;
+}
+
+small {
+ font-size: 75%;
+}
+
+/*
+ * Prevents `sub` and `sup` affecting `line-height` in all browsers.
+ * gist.github.com/413930
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* ==========================================================================
+ Lists
+ ========================================================================== */
+
+/*
+ * Addresses margins set differently in IE6/7.
+ */
+
+dl,
+menu,
+ol,
+ul {
+ margin: 1em 0;
+}
+
+dd {
+ margin: 0 0 0 40px;
+}
+
+/*
+ * Addresses paddings set differently in IE6/7.
+ */
+
+menu,
+ol,
+ul {
+ padding: 0 0 0 40px;
+}
+
+/*
+ * Corrects list images handled incorrectly in IE7.
+ */
+
+nav ul,
+nav ol {
+ list-style: none;
+ list-style-image: none;
+}
+
+/* ==========================================================================
+ Embedded content
+ ========================================================================== */
+
+/*
+ * 1. Removes border when inside `a` element in IE6/7/8/9, FF3.
+ * 2. Improves image quality when scaled in IE7.
+ * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
+ */
+
+img {
+ border: 0; /* 1 */
+ -ms-interpolation-mode: bicubic; /* 2 */
+}
+
+/*
+ * Corrects overflow displayed oddly in IE9.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* ==========================================================================
+ Figures
+ ========================================================================== */
+
+/*
+ * Addresses margin not present in IE6/7/8/9, S5, O11.
+ */
+
+figure {
+ margin: 0;
+}
+
+/* ==========================================================================
+ Forms
+ ========================================================================== */
+
+/*
+ * Corrects margin displayed oddly in IE6/7.
+ */
+
+form {
+ margin: 0;
+}
+
+/*
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/*
+ * 1. Corrects color not being inherited in IE6/7/8/9.
+ * 2. Corrects text not wrapping in FF3.
+ * 3. Corrects alignment displayed oddly in IE6/7.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0;
+ white-space: normal; /* 2 */
+ *margin-left: -7px; /* 3 */
+}
+
+/*
+ * 1. Corrects font size not being inherited in all browsers.
+ * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome.
+ * 3. Improves appearance and consistency in all browsers.
+ */
+
+button,
+input,
+select,
+textarea {
+ font-size: 100%; /* 1 */
+ margin: 0; /* 2 */
+ vertical-align: baseline; /* 3 */
+ *vertical-align: middle; /* 3 */
+}
+
+/*
+ * Addresses FF3/4 setting `line-height` on `input` using `!important` in the
+ * UA stylesheet.
+ */
+
+button,
+input {
+ line-height: normal;
+}
+
+/*
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Corrects inability to style clickable `input` types in iOS.
+ * 3. Improves usability and consistency of cursor style between image-type
+ * `input` and others.
+ * 4. Removes inner spacing in IE7 without affecting normal text inputs.
+ * Known issue: inner spacing remains in IE6.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+ *overflow: visible; /* 4 */
+}
+
+/*
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+input[disabled] {
+ cursor: default;
+}
+
+/*
+ * 1. Addresses box sizing set to content-box in IE8/9.
+ * 2. Removes excess padding in IE8/9.
+ * 3. Removes excess padding in IE7.
+ * Known issue: excess padding remains in IE6.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+ *height: 13px; /* 3 */
+ *width: 13px; /* 3 */
+}
+
+/*
+ * 1. Addresses `appearance` set to `searchfield` in S5, Chrome.
+ * 2. Addresses `box-sizing` set to `border-box` in S5, Chrome (include `-moz`
+ * to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/*
+ * Removes inner padding and search cancel button in S5, Chrome on OS X.
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/*
+ * Removes inner padding and border in FF3+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/*
+ * 1. Removes default vertical scrollbar in IE6/7/8/9.
+ * 2. Improves readability and alignment in all browsers.
+ */
+
+textarea {
+ overflow: auto; /* 1 */
+ vertical-align: top; /* 2 */
+}
+
+/* ==========================================================================
+ Tables
+ ========================================================================== */
+
+/*
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/ApiTest.php b/public/system/storage/vendor/leafo/scssphp/tests/ApiTest.php
new file mode 100644
index 0000000..ecebe55
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/ApiTest.php
@@ -0,0 +1,80 @@
+<?php
+
+require_once __DIR__ . "/../scss.inc.php";
+
+class ApiTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->scss = new scssc();
+ }
+
+ public function testUserFunction()
+ {
+ $this->scss->registerFunction("add-two", function ($args) {
+ list($a, $b) = $args;
+ return $a[1] + $b[1];
+ });
+
+ $this->assertEquals(
+ "result: 30;",
+ $this->compile("result: add-two(10, 20);")
+ );
+ }
+
+ public function testImportMissing()
+ {
+ $this->assertEquals(
+ '@import "missing";',
+ $this->compile('@import "missing";')
+ );
+ }
+
+ public function testImportCustomCallback()
+ {
+ $this->scss->addImportPath(function ($path) {
+ return __DIR__ . '/inputs/' . str_replace('.css', '.scss', $path);
+ });
+
+ $this->assertEquals(
+ trim(file_get_contents(__DIR__ . '/outputs/variables.css')),
+ $this->compile('@import "variables.css";')
+ );
+ }
+
+ /**
+ * @dataProvider provideSetVariables
+ */
+ public function testSetVariables($expected, $scss, $variables)
+ {
+ $this->scss->setVariables($variables);
+
+ $this->assertEquals($expected, $this->compile($scss));
+ }
+
+ public function provideSetVariables()
+ {
+ return array(
+ array(
+ ".magic {\n color: red;\n width: 760px; }",
+ '.magic { color: $color; width: $base - 200; }',
+ array(
+ 'color' => 'red',
+ 'base' => '960px',
+ ),
+ ),
+ array(
+ ".logo {\n color: #808080; }",
+ '.logo { color: desaturate($primary, 100%); }',
+ array(
+ 'primary' => '#ff0000',
+ ),
+ ),
+ );
+ }
+
+ public function compile($str)
+ {
+ return trim($this->scss->compile($str));
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/ExceptionTest.php b/public/system/storage/vendor/leafo/scssphp/tests/ExceptionTest.php
new file mode 100644
index 0000000..63d1db6
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/ExceptionTest.php
@@ -0,0 +1,86 @@
+<?php
+
+require_once __DIR__ . "/../scss.inc.php";
+
+class ExceptionTest extends PHPUnit_Framework_TestCase {
+ public function setUp() {
+ $this->scss = new scssc();
+ }
+
+ /**
+ * @param string $scss
+ * @param string $expectedExceptionMessage
+ *
+ * @dataProvider provideScss
+ */
+ public function testThrowError($scss, $expectedExceptionMessage) {
+ try {
+ $this->compile($scss);
+ } catch (Exception $e) {
+ if (strpos($e->getMessage(), $expectedExceptionMessage) !== false) {
+ return;
+ };
+ }
+
+ $this->fail('Expected exception to be raised: ' . $expectedExceptionMessage);
+ }
+
+ /**
+ * @return array
+ */
+ public function provideScss() {
+ return array(
+ array(<<<END_OF_SCSS
+.test {
+ foo : bar;
+END_OF_SCSS
+,
+ 'unclosed block'
+ ),
+ array(<<<END_OF_SCSS
+.test {
+}}
+END_OF_SCSS
+,
+ 'unexpected }'
+ ),
+ array(<<<END_OF_SCSS
+.test { color: #fff / 0; }
+END_OF_SCSS
+,
+ 'color: Can\'t divide by zero'
+ ),
+ array(<<<END_OF_SCSS
+.test {
+ @include foo();
+}
+END_OF_SCSS
+,
+ 'Undefined mixin foo'
+ ),
+ array(<<<END_OF_SCSS
+@mixin do-nothing() {
+}
+
+.test {
+ @include do-nothing(\$a: "hello");
+}
+END_OF_SCSS
+,
+ 'Mixin or function doesn\'t have an argument named $a.'
+ ),
+ array(<<<END_OF_SCSS
+div {
+ color: darken(cobaltgreen, 10%);
+}
+END_OF_SCSS
+,
+ 'expecting color'
+ ),
+ );
+ }
+
+ private function compile($str) {
+ return trim($this->scss->compile($str));
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/InputTest.php b/public/system/storage/vendor/leafo/scssphp/tests/InputTest.php
new file mode 100644
index 0000000..fbd83b6
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/InputTest.php
@@ -0,0 +1,83 @@
+<?php
+
+require_once __DIR__ . "/../scss.inc.php";
+
+// Runs all the tests in inputs/ and compares their output to ouputs/
+
+function _dump($value) {
+ fwrite(STDOUT, print_r($value, true));
+}
+
+function _quote($str) {
+ return preg_quote($str, "/");
+}
+
+class InputTest extends PHPUnit_Framework_TestCase {
+ protected static $inputDir = "inputs";
+ protected static $outputDir = "outputs";
+
+ public function setUp() {
+ $this->scss = new scssc();
+ $this->scss->addImportPath(__DIR__ . "/" . self::$inputDir);
+ }
+
+ /**
+ * @dataProvider fileNameProvider
+ */
+ public function testInputFile($inFname, $outFname) {
+ if (getenv("BUILD")) {
+ return $this->buildInput($inFname,$outFname);
+ }
+
+ if (!is_readable($outFname)) {
+ $this->fail("$outFname is missing, ".
+ "consider building tests with BUILD=true");
+ }
+
+ $input = file_get_contents($inFname);
+ $output = file_get_contents($outFname);
+
+ $this->assertEquals($output, $this->scss->compile($input));
+ }
+
+ public function fileNameProvider() {
+ return array_map(function($a) { return array($a, InputTest::outputNameFor($a)); },
+ self::findInputNames());
+ }
+
+ // only run when env is set
+ public function buildInput($inFname, $outFname) {
+ $css = $this->scss->compile(file_get_contents($inFname));
+ file_put_contents($outFname, $css);
+ }
+
+ static public function findInputNames($pattern="*") {
+ $files = glob(__DIR__ . "/" . self::$inputDir . "/" . $pattern);
+ $files = array_filter($files, "is_file");
+ if ($pattern = getenv("MATCH")) {
+ $files = array_filter($files, function($fname) use ($pattern) {
+ return preg_match("/$pattern/", $fname);
+ });
+ }
+
+ return $files;
+ }
+
+ static public function outputNameFor($input) {
+ $front = _quote(__DIR__ . "/");
+ $out = preg_replace("/^$front/", "", $input);
+
+ $in = _quote(self::$inputDir . "/");
+ $out = preg_replace("/$in/", self::$outputDir . "/", $out);
+ $out = preg_replace("/.scss$/", ".css", $out);
+
+ return __DIR__ . "/" . $out;
+ }
+
+ static public function buildTests($pattern) {
+ $files = self::findInputNames($pattern);
+ foreach ($files as $file) {
+ }
+ }
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/compare-scss.sh b/public/system/storage/vendor/leafo/scssphp/tests/compare-scss.sh
new file mode 100644
index 0000000..3b04292
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/compare-scss.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+diff_tool="$1"
+
+for file in $(ls inputs/*.scss); do
+ out_file=$(echo $file | sed -e 's/inputs/outputs/' -e 's/\.scss$/\.css/')
+ sass=$(scss < $file 2> /dev/null)
+ if [ $? = "0" ]; then
+ # echo $file
+ # echo "$sass"
+ # echo
+
+ if [ "$(cat $out_file)" != "$sass" ]; then
+ echo "* [FAIL] $file"
+ if [ -n "$diff_tool" ]; then
+ $diff_tool $out_file <(echo "$sass") 2> /dev/null
+ fi
+ else
+ echo " [PASS] $file"
+ fi
+ else
+ echo " $file"
+ fi
+done
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/builtins.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/builtins.scss
new file mode 100644
index 0000000..ef93a03
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/builtins.scss
@@ -0,0 +1,171 @@
+
+#color {
+ color: rgb(34,234,24);
+
+ red: red(rgb(34,234,24));
+ green: green(rgb(34,234,24));
+ blue: blue(rgb(34,234,24));
+
+ color: rgba(1,2,4, 0.5);
+ a1: alpha(rgb(1,2,4));
+ a2: alpha(rgba(1,2,4, 0.5));
+
+ mix: mix(rgb(1,2,3), rgb(3,4,5));
+
+ rgba: rgba($color: #a7c, $alpha: 0.4);
+ rgba: rgba(#a7c, 0.4);
+}
+
+#hsl {
+ color: hsl(100, 50, 55);
+ color: hsla(100, 50, 55, 0.5);
+
+ hue: hue(hsl(100, 50, 55));
+ sat: saturation(hsl(100, 50, 55));
+ lig: lightness(hsl(100, 50, 55));
+}
+
+#more-color {
+ $color: hsl(-80,44,33);
+
+ light: lighten($color, 10%);
+ dark: darken($color, 10%);
+
+ sat: saturate($color, 10%);
+ desat: desaturate($color, 10%);
+
+ gray: grayscale($color);
+ comp: complement($color);
+ inv: invert($color);
+}
+
+#more-more-color {
+ $color: rgba(1,2,3,0.5);
+ op: opacity($color);
+
+ opacify: opacify($color, 0.1);
+ opacify: fade-in($color, 0.1);
+
+ transparentize: transparentize($color, 0.1);
+ transparentize: fade-out($color, 0.1);
+ transparentize: transparentize(#348203, 0.1);
+}
+
+#more-more-more-color {
+ $color: rgba(10,10,10,0);
+ color: adjust-color($color, $blue: 69, $red: 55, $green: 100, $alpha: 0.4);
+ color: adjust-color($color, $hue: 170, $saturation: 100, $lightness: 50);
+
+ color: change-color($color, $blue: 69, $red: 55, $green: 100, $alpha: 0.4);
+ color: change-color($color, $hue: 170, $saturation: 100, $lightness: 50);
+
+ color: scale-color($color, $red: 55%);
+ color: scale-color($color, $red: -55%);
+
+ color: scale-color($color, $lightness: 55%);
+ color: scale-color($color, $lightness: -55%);
+
+ color: ie-hex-str($color);
+ color: ie-hex-str(#abc);
+}
+
+#string {
+ color: unquote("hello what is going on");
+ // color: quote(yeah you know it); // **
+ color: quote(yeah);
+ color: quote("I do?");
+}
+
+#number {
+ color: percentage(100/40);
+ color: round(3.4);
+ color: floor(3.4);
+ color: ceil(3.4);
+
+ top: floor(10.4px);
+ top: ceil(.4ex);
+ width: percentage(100px / 50px);
+ bottom: abs(-10px);
+ padding: min(5em, 3em, 4em) max(2px, 1in) min(1in, 96px) max(1in, 72pt);
+}
+
+#list {
+ len: length(hello world what);
+ len: length(thing);
+
+ n: nth(hello world what, 1);
+ // n: nth(hello world what, 100); // **
+
+ hello: join(one two three, hello, comma);
+ hello: join(one two three, hello world what is going, comma);
+ hello: append(one two three, hello, comma);
+
+ index: index(1px solid red, solid);
+ index: index(1px solid red, dashed);
+ index: index(1px solid red, #f00);
+ index: index(96px solid red, 1in);
+ index: index((1in 2) a b, 1in);
+ index: index((1in 2) a b, (96px 2));
+ index: index((1in 2) a b, (1in, 2));
+ index: index((1px solid red), solid);
+ index: index(1px 3px + 3px, 4+2px);
+ $var: oo;
+ index: index(foo bar, f#{$var});
+
+ $yes: one, two, three;
+ $no: great job;
+ world: join($yes, $no);
+ world: append($yes, $no);
+
+ cool: join($yes, $no, space);
+ cool: join($no, $yes);
+
+ zip: zip((1px, 2px), (solid dashed));
+ zip: zip(1px 2px 3px, solid dashed, red green blue);
+}
+
+#introspection {
+ t: type-of(100px);
+ t: type-of(asdf);
+ t: type-of("asdf");
+ t: type-of(true);
+ t: type-of(#fff);
+ t: type-of(blue);
+ t: type-of(one two three);
+
+ u: unit(12);
+ u: unit(12px);
+ u: unit(12em);
+
+ l: unitless(23);
+ l: unitless(23deg);
+
+ c: comparable(2px, 1px);
+ c: comparable(100px, 3em);
+ c: comparable(10cm, 3mm);
+ c: comparable(1, 4);
+ c: comparable(1ex, 4em);
+ c: comparable(2em, 5em);
+}
+
+#if {
+ color: if(true, yes, no);
+ color: if(false, yes, no);
+ color: if(false or true, yes, no);
+ color: if(10px, yes, no);
+}
+
+.transparent {
+ r: red(transparent);
+ g: green(transparent);
+ b: blue(transparent);
+ a: alpha(transparent);
+}
+
+.alpha {
+ a: alpha(black);
+ a: alpha(#fff);
+ a: alpha(rgb(0, 0, 0));
+ a: alpha(rgba(0, 0, 0, 0.5));
+ a: alpha(currentColor);
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/comments.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/comments.scss
new file mode 100644
index 0000000..a4e2d11
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/comments.scss
@@ -0,0 +1,28 @@
+
+// what is going on?
+
+/** what the heck **/
+
+/**
+
+Here is a block comment
+
+**/
+
+
+// this is a comment
+
+// trailing backslash \
+/*hello*/div /*yeah*/ { //surew
+ border: 1px solid red; // world
+ /* another property */
+ color: url('http://mage-page.com');
+ string: "hello /* this is not a comment */";
+ world: "// neither is this";
+ string: 'hello /* this is not a comment */' /*what if this is a comment */;
+ world: '// neither is this' // hell world;
+ ;
+ what-ever: 100px;
+ background: url(/*this is not a comment?*/); // uhh what happens here
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/compass_extract.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/compass_extract.scss
new file mode 100644
index 0000000..fba4572
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/compass_extract.scss
@@ -0,0 +1,248 @@
+// Extracted from compass/typography/vertical_rhythm.scss
+
+
+// The base font size.
+$base-font-size: 16px !default;
+
+// The base line height determines the basic unit of vertical rhythm.
+$base-line-height: 24px !default;
+
+// Set the default border style for rhythm borders.
+$default-rhythm-border-style: solid !default;
+
+// The default font size in all browsers.
+$browser-default-font-size: 16px;
+
+// Set to false if you want to use absolute pixels in sizing your typography.
+$relative-font-sizing: true !default;
+
+// Allows the `adjust-font-size-to` mixin and the `lines-for-font-size` function
+// to round the line height to the nearest half line height instead of the
+// nearest integral line height to avoid large spacing between lines.
+$round-to-nearest-half-line: false !default;
+
+// Ensure there is at least this many pixels
+// of vertical padding above and below the text.
+$min-line-padding: 2px !default;
+
+// $base-font-size but in your output unit of choice.
+// Defaults to 1em when `$relative-font-sizing` is true.
+$font-unit: if($relative-font-sizing, 1em, $base-font-size) !default;
+
+// The basic unit of font rhythm.
+$base-rhythm-unit: $base-line-height / $base-font-size * $font-unit;
+
+// The leader is the amount of whitespace in a line.
+// It might be useful in your calculations.
+$base-leader: ($base-line-height - $base-font-size) * $font-unit / $base-font-size;
+
+// The half-leader is the amount of whitespace above and below a line.
+// It might be useful in your calculations.
+$base-half-leader: $base-leader / 2;
+
+// True if a number has a relative unit.
+@function relative-unit($number) {
+ @return unit($number) == "%" or unit($number) == "em" or unit($number) == "rem"
+}
+
+// True if a number has an absolute unit.
+@function absolute-unit($number) {
+ @return not (relative-unit($number) or unitless($number));
+}
+
+@if $relative-font-sizing and not relative-unit($font-unit) {
+ @warn "$relative-font-sizing is true but $font-unit is set to #{$font-unit} which is not a relative unit.";
+}
+
+// Establishes a font baseline for the given font-size.
+@mixin establish-baseline($font-size: $base-font-size) {
+ // IE 6 refuses to resize fonts set in pixels and it weirdly resizes fonts
+ // whose root is set in ems. So we set the root font size in percentages of
+ // the default font size.
+ * html {
+ font-size: 100% * ($font-size / $browser-default-font-size);
+ }
+ html {
+ font-size: $font-size;
+ @include adjust-leading-to(1, if($relative-font-sizing, $font-size, $base-font-size));
+ }
+}
+
+// Resets the line-height to 1 vertical rhythm unit.
+// Does not work on elements whose font-size is different from $base-font-size.
+//
+// @deprecated This mixin will be removed in the next release.
+// Please use the `adjust-leading-to` mixin instead.
+@mixin reset-baseline {
+ @include adjust-leading-to(1, if($relative-font-sizing, $base-font-size, $base-font-size));
+}
+
+// Show a background image that can be used to debug your alignments.
+// Include the $img argument if you would rather use your own image than the
+// Compass default gradient image.
+@mixin debug-vertical-alignment($img: false) {
+ @if $img {
+ background: image-url($img);
+ } @else {
+ @include baseline-grid-background($base-rhythm-unit);
+ }
+}
+
+// Adjust a block to have a different font size and line height to maintain the
+// rhythm. $lines specifies how many multiples of the baseline rhythm each line
+// of this font should use up. It does not have to be an integer, but it
+// defaults to the smallest integer that is large enough to fit the font.
+// Use $from-size to adjust from a font-size other than the base font-size.
+@mixin adjust-font-size-to($to-size, $lines: lines-for-font-size($to-size), $from-size: $base-font-size) {
+ @if not $relative-font-sizing and $from-size != $base-font-size {
+ @warn "$relative-font-sizing is false but a relative font size was passed to adjust-font-size-to";
+ }
+ font-size: $font-unit * $to-size / $from-size;
+ @include adjust-leading-to($lines, if($relative-font-sizing, $to-size, $base-font-size));
+}
+
+// Adjust a block to have different line height to maintain the rhythm.
+// $lines specifies how many multiples of the baseline rhythm each line of this
+// font should use up. It does not have to be an integer, but it defaults to the
+// smallest integer that is large enough to fit the font.
+@mixin adjust-leading-to($lines, $font-size: $base-font-size) {
+ line-height: rhythm($lines, $font-size);
+}
+
+// Calculate rhythm units.
+@function rhythm(
+ $lines: 1,
+ $font-size: $base-font-size,
+ $offset: 0
+) {
+ @if not $relative-font-sizing and $font-size != $base-font-size {
+ @warn "$relative-font-sizing is false but a relative font size was passed to the rhythm function";
+ }
+ $rhythm: $font-unit * ($lines * $base-line-height - $offset) / $font-size;
+ // Round the pixels down to nearest integer.
+ @if unit($rhythm) == px {
+ $rhythm: floor($rhythm);
+ }
+ @return $rhythm;
+}
+
+// Calculate the minimum multiple of rhythm units needed to contain the font-size.
+@function lines-for-font-size($font-size) {
+ $lines: if($round-to-nearest-half-line,
+ ceil(2 * $font-size / $base-line-height) / 2,
+ ceil($font-size / $base-line-height));
+ @if $lines * $base-line-height - $font-size < $min-line-padding * 2 {
+ $lines: $lines + if($round-to-nearest-half-line, 0.5, 1);
+ }
+ @return $lines;
+}
+
+// Apply leading whitespace. The $property can be margin or padding.
+@mixin leader($lines: 1, $font-size: $base-font-size, $property: margin) {
+ #{$property}-top: rhythm($lines, $font-size);
+}
+
+// Apply leading whitespace as padding.
+@mixin padding-leader($lines: 1, $font-size: $base-font-size) {
+ padding-top: rhythm($lines, $font-size);
+}
+
+// Apply leading whitespace as margin.
+@mixin margin-leader($lines: 1, $font-size: $base-font-size) {
+ margin-top: rhythm($lines, $font-size);
+}
+
+// Apply trailing whitespace. The $property can be margin or padding.
+@mixin trailer($lines: 1, $font-size: $base-font-size, $property: margin) {
+ #{$property}-bottom: rhythm($lines, $font-size);
+}
+
+// Apply trailing whitespace as padding.
+@mixin padding-trailer($lines: 1, $font-size: $base-font-size) {
+ padding-bottom: rhythm($lines, $font-size);
+}
+
+// Apply trailing whitespace as margin.
+@mixin margin-trailer($lines: 1, $font-size: $base-font-size) {
+ margin-bottom: rhythm($lines, $font-size);
+}
+
+// Shorthand mixin to apply whitespace for top and bottom margins and padding.
+@mixin rhythm($leader: 0, $padding-leader: 0, $padding-trailer: 0, $trailer: 0, $font-size: $base-font-size) {
+ @include leader($leader, $font-size);
+ @include padding-leader($padding-leader, $font-size);
+ @include padding-trailer($padding-trailer, $font-size);
+ @include trailer($trailer, $font-size);
+}
+
+// Apply a border and whitespace to any side without destroying the vertical
+// rhythm. The whitespace must be greater than the width of the border.
+@mixin apply-side-rhythm-border($side, $width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
+ @if not $relative-font-sizing and $font-size != $base-font-size {
+ @warn "$relative-font-sizing is false but a relative font size was passed to apply-side-rhythm-border";
+ }
+ border-#{$side}: {
+ style: $border-style;
+ width: $font-unit * $width / $font-size;
+ };
+ padding-#{$side}: rhythm($lines, $font-size, $offset: $width);
+}
+
+// Apply borders and whitespace equally to all sides.
+@mixin rhythm-borders($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
+ @if not $relative-font-sizing and $font-size != $base-font-size {
+ @warn "$relative-font-sizing is false but a relative font size was passed to rhythm-borders";
+ }
+ border: {
+ style: $border-style;
+ width: $font-unit * $width / $font-size;
+ };
+ padding: rhythm($lines, $font-size, $offset: $width);
+}
+
+// Apply a leading border.
+@mixin leading-border($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
+ @include apply-side-rhythm-border(top, $width, $lines, $font-size, $border-style);
+}
+
+// Apply a trailing border.
+@mixin trailing-border($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
+ @include apply-side-rhythm-border(bottom, $width, $lines, $font-size, $border-style);
+}
+
+// Apply both leading and trailing borders.
+@mixin horizontal-borders($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
+ @include leading-border($width, $lines, $font-size, $border-style);
+ @include trailing-border($width, $lines, $font-size, $border-style);
+}
+
+// Alias for `horizontal-borders` mixin.
+@mixin h-borders($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
+ @include horizontal-borders($width, $lines, $font-size, $border-style);
+}
+
+#test-0 {
+ unit: relative-unit(10px);
+ unit: relative-unit(50%);
+ rhythm: rhythm();
+ size: lines-for-font-size(15px);
+ size: lines-for-font-size(16px);
+ size: lines-for-font-size(17px);
+ size: lines-for-font-size(27px);
+ size: lines-for-font-size(37px);
+}
+
+
+#test-1 {
+ @include rhythm(5, 6, 7);
+}
+
+#test-2 {
+ @include rhythm-borders;
+}
+
+#test-3 {
+ @include horizontal-borders;
+}
+
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/content.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/content.scss
new file mode 100644
index 0000000..55ca04e
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/content.scss
@@ -0,0 +1,61 @@
+
+@mixin apply-to-ie6-only {
+ * html {
+ @content;
+ }
+}
+@include apply-to-ie6-only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+
+$color: white;
+@mixin colors($color: blue) {
+ background-color: $color;
+ @content;
+ border-color: $color;
+}
+.colors {
+ @include colors { color: $color; }
+}
+
+
+@mixin iphone {
+ @media only screen and (max-width: 480px) {
+ @content;
+ }
+}
+
+@include iphone {
+ body { color: red }
+}
+
+
+#sidebar {
+ $sidebar-width: 300px;
+ width: $sidebar-width;
+ @include iphone {
+ width: $sidebar-width / 3;
+ }
+}
+
+
+@mixin respond-to($width) {
+ @media only screen and (min-width: $width) { @content; }
+}
+
+@include respond-to(40em) {
+ @for $i from 1 through 2 {
+ .grid-#{$i} { width: 100%; }
+ }
+}
+
+@include respond-to(40em) {
+ $i: 1;
+ @while $i <= 2 {
+ .grid-#{$i} { width: 100%; }
+ $i: $i + 1;
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/content_with_function.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/content_with_function.scss
new file mode 100644
index 0000000..f1462d6
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/content_with_function.scss
@@ -0,0 +1,17 @@
+$test-var: true;
+
+@mixin mixin-using-content() {
+ @content;
+}
+
+@function test-function($value) {
+ @return $value;
+}
+
+@include mixin-using-content {
+ @if $test-var {
+ body {
+ padding: test-function(1 px);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/default_args.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/default_args.scss
new file mode 100644
index 0000000..dbc8880
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/default_args.scss
@@ -0,0 +1,15 @@
+
+
+@mixin cool($color: blue) {
+ margin: 100px;
+}
+
+@function what($height: red) {
+ @return $height;
+}
+
+div {
+ height: what();
+ @include cool;
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/directives.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/directives.scss
new file mode 100644
index 0000000..65f1c51
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/directives.scss
@@ -0,0 +1,108 @@
+
+@charset "hello-world";
+
+@page :left {
+ div {
+ color: red;
+ }
+}
+
+@page test {
+ @media yes {
+ div {
+ color: red;
+ }
+
+ @media no {
+ pre {
+ color: blue;
+ }
+ }
+ }
+}
+
+@media something {
+ @page {
+ @media else {
+ div {
+ height: 200px;
+ }
+ }
+ }
+}
+
+
+div {
+ color: red;
+ @page yeah {
+ pre {
+ height: 20px;
+ }
+ }
+}
+
+@font-face {
+ color: red;
+ height: 20px;
+}
+
+
+@keyframes 'bounce' {
+ from {
+ top: 100px;
+ animation-timing-function: ease-out;
+ }
+
+ 25% {
+ top: 50px;
+ animation-timing-function: ease-in;
+ }
+
+ 50% {
+ top: 100px;
+ animation-timing-function: ease-out;
+ }
+
+ 75% {
+ top: 75px;
+ animation-timing-function: ease-in;
+ }
+
+ to {
+ top: 100px;
+ }
+}
+
+@-webkit-keyframes flowouttoleft {
+ 0% { -webkit-transform: translateX(0) scale(1); }
+ 60%, 70% { -webkit-transform: translateX(0) scale(.7); }
+ 100% { -webkit-transform: translateX(-100%) scale(.7); }
+}
+
+div {
+ animation-name: 'diagonal-slide';
+ animation-duration: 5s;
+ animation-iteration-count: 10;
+}
+
+@keyframes 'diagonal-slide' {
+
+ from {
+ left: 0;
+ top: 0;
+ }
+
+ to {
+ left: 100px;
+ top: 100px;
+ }
+
+}
+
+@document url(http://www.w3.org/),
+ url-prefix(http://www.w3.org/Style/),
+ domain(mozilla.org),
+ regexp("https:.*")
+{
+ body { color: purple; background: yellow; }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/extends.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/extends.scss
new file mode 100644
index 0000000..74a5160
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/extends.scss
@@ -0,0 +1,184 @@
+
+error, other {
+ border: 1px #f00;
+ background-color: #fdd;
+}
+
+pre, span {
+ seriousError {
+ @extend error;
+ font-size: 20px;
+ }
+}
+
+hello {
+ @extend other;
+ color: green;
+ div {
+ margin: 10px;
+ }
+}
+
+.cool {
+ color: red;
+}
+
+.blue {
+ color: purple;
+}
+
+.me {
+ @extend .cool, .blue;
+}
+
+.hoverlink { @extend a:hover }
+a:hover { text-decoration: underline }
+
+
+// partial matching and selector merging:
+
+div.hello.world.hmm {
+ color: blue;
+}
+
+pre, code {
+ .okay.span {
+ @extend .hello;
+ }
+}
+
+// multiple matches per selector
+.xxxxx .xxxxx .xxxxx {
+ color: green;
+}
+
+code {
+ @extend .xxxxx;
+ color: red;
+}
+
+
+// chained
+
+.alpha {
+ color: red;
+}
+
+.beta {
+ @extend .alpha;
+ color: white;
+}
+
+.gama {
+ @extend .beta;
+ color: blue;
+}
+
+// merging selector sequences
+
+#admin .tabbar a {font-weight: bold}
+#demo .overview .fakelink {@extend a}
+
+a1 b1 c1 d1 { color: red; }
+x1 y1 z1 w1 { @extend a1; }
+
+a2 b2 c2 d2 { color: red; }
+x2 y2 z2 w2 { @extend b2; }
+
+
+a3 b3 c3 d3 { color: red; }
+x3 y3 z3 w3 { @extend c3; }
+
+
+a4 b4 c4 d4 { color: red; }
+x4 y4 z4 w4 { @extend d4; }
+
+// removing common prefix
+
+#butt .yeah .okay { font-weight: bold }
+#butt .umm .sure { @extend .okay }
+
+a9 b9 s9 t9 v9 { color: red; }
+
+a9 b9 x9 y9 z9 {
+ @extend v9;
+}
+
+// extends & media
+
+@media print {
+ horse {
+ color: blue;
+ }
+}
+
+man {
+ color: red;
+ @extend horse;
+}
+
+
+// result == match
+
+wassup {
+ color: blue;
+ @extend wassup;
+}
+
+.foo {
+ .wassup {
+ @extend .wassup;
+ color: blue;
+ }
+}
+
+// multi-extend
+
+#something {
+ color: red;
+}
+
+.x {
+ @extend #something;
+}
+
+.y {
+ @extend #something;
+}
+
+// twitter-sass-bootstrap infinite loop
+
+.nav-tabs {
+ &.nav-justified {
+ @extend .nav-justified;
+ }
+}
+.nav-justified {
+ text-align: justify;
+}
+
+// multi-extend with nesting
+
+.btn:hover,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+ color: red;
+}
+.edit .actions {
+ button {
+ float: right;
+ @extend .btn;
+ }
+}
+.edit {
+ .new {
+ .actions {
+ padding: 0;
+ }
+ .actions button {
+ @extend .btn;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/filter_effects.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/filter_effects.scss
new file mode 100644
index 0000000..e8f9a3b
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/filter_effects.scss
@@ -0,0 +1,48 @@
+#number {
+ -webkit-filter: grayscale(1)
+ sepia(0.5)
+ saturate(0.1)
+ invert(1)
+ opacity(0.5)
+ brightness(0.5)
+ contrast(0.5);
+}
+
+#percentage {
+ -webkit-filter: grayscale(100%)
+ sepia(50%)
+ saturate(10%)
+ invert(100%)
+ opacity(50%)
+ brightness(50%)
+ contrast(50%);
+}
+
+#misc {
+ -webkit-filter: hue-rotate(90deg)
+ blur(10px)
+ drop-shadow(10px -16px 30px purple);
+}
+
+@mixin opacity($opacity, $style: 0) {
+ @if ($opacity < 1) {
+ opacity: $opacity;
+ filter: alpha(opacity=$opacity * 100, style=$style);
+ } @else {
+ opacity: $opacity / 100;
+ filter: alpha(opacity=$opacity);
+ }
+}
+
+#decimal {
+ @include opacity(.5, 1);
+}
+
+#percent {
+ @include opacity(50);
+}
+
+.row {
+ background-color: darken(#2ba6cb, 40%);
+ color: darken(#2ba6cb, 10%);
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/functions.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/functions.scss
new file mode 100644
index 0000000..d555ae9
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/functions.scss
@@ -0,0 +1,81 @@
+
+@function hello($x) {
+ @return $x + 4;
+}
+
+@function add($a, $b) {
+ @return $a + $b;
+}
+
+div {
+ color: hello(10px);
+ sum: add(11, 12);
+}
+
+// make sure values are being reduced before being passed up to previous scope
+
+@function one($a, $b) {
+ @return $a $b;
+}
+
+@function two($a, $b) {
+ @return $a#{$a} $b;
+}
+
+@function three($a, $b: default) {
+ @return "hello #{$a} and #{$b}"
+}
+
+@function all($a...) {
+ @return "hello #{$a}"
+}
+
+div {
+ hello: one(10, 55);
+ hello: two(10, 55);
+ hello: three(10, 55);
+}
+
+
+@function hello_world() {
+ @return 1000;
+}
+
+del {
+ color: hello-world();
+}
+
+div {
+ $args: foo bar;
+ hello: three($args...);
+ hello: three(bar...);
+ hello: all(Alice, Bob, Tom);
+}
+
+@function stringConcatCompassStyle($start,$last)
+{
+ // Compass still uses it like this
+ @return #{$start}-#{$last};
+}
+
+.foo
+{
+ test2: stringConcatCompassStyle(-moz,art);
+}
+
+@mixin content_test {
+ span {
+ $color: green;
+ @content;
+ }
+}
+
+@function func_test($c) {
+ @return $c + 1;
+}
+
+div {
+ @include content_test {
+ height: func_test(2px);
+ }
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/ie7.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/ie7.scss
new file mode 100644
index 0000000..3d4771b
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/ie7.scss
@@ -0,0 +1,12 @@
+// http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
+#foo:before {
+ content: counter(item, ".") ": ";
+}
+
+#bar:before {
+ content: counter(item,".");
+}
+
+#fu:before {
+ content: counter(item);
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/if.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/if.scss
new file mode 100644
index 0000000..d62b056
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/if.scss
@@ -0,0 +1,76 @@
+
+@function conds($val) {
+ @if $val {
+ @return "red";
+ }
+
+ @return "blue";
+}
+
+div {
+ @if something {
+ color: blue;
+ }
+}
+
+pre {
+ val-1: conds(true);
+ val-2: conds(false);
+ val-3: conds(null);
+ val-4: conds(1);
+ val-5: conds(0);
+}
+
+
+span {
+ @if false {
+ color: red;
+ } @else {
+ color: blue;
+ }
+
+ @if true {
+ height: 10px;
+ } @else {
+ color: 20px;
+ }
+
+ @if false {
+ height: 10px;
+ } @elseif false {
+ color: 20px;
+ } @else {
+ width: 20px;
+ }
+}
+
+div {
+ @if false {
+ color: red;
+ } @else if false {
+ color: green;
+ } @else {
+ color: blue;
+ }
+
+ @if false {
+ border-color: red;
+ } @else if true {
+ border-color: green;
+ } @else {
+ border-color: blue;
+ }
+
+}
+
+// doesn't work in scss, thing loses scope
+del {
+ @if false {
+ $thing: yes;
+ } @else {
+ $thing: no;
+ }
+
+ thing: $thing;
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/if_on_null.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/if_on_null.scss
new file mode 100644
index 0000000..1688706
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/if_on_null.scss
@@ -0,0 +1,8 @@
+@function testfunc($pseudo: null) {
+ $output: if($pseudo, "green", "red");
+ @return $output;
+}
+
+body {
+ background-color: testfunc();
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/import.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/import.scss
new file mode 100644
index 0000000..61625cd
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/import.scss
@@ -0,0 +1,23 @@
+
+@import "foo.css";
+@import "foo" screen;
+@import "http://foo.com/bar";
+@import url(foo);
+
+@import "imports/simple";
+
+pre {
+ color: red;
+ @import "imports/simple.scss";
+}
+
+code {
+ @import "imports/simple", "imports/simple";
+}
+
+@import "imports/partial";
+
+body {
+ color: $variable;
+ @include partial-mixin();
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/_partial.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/_partial.scss
new file mode 100644
index 0000000..010c3c4
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/_partial.scss
@@ -0,0 +1,10 @@
+
+#partial {
+ color: blue;
+}
+
+$variable: #7C2;
+
+@mixin partial-mixin() {
+ background: gray;
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/simple.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/simple.scss
new file mode 100644
index 0000000..4b3e1f9
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/imports/simple.scss
@@ -0,0 +1,4 @@
+div {
+ height: 200px;
+ color: red;
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/interpolation.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/interpolation.scss
new file mode 100644
index 0000000..3ac51cf
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/interpolation.scss
@@ -0,0 +1,86 @@
+
+div {
+ color: red#{white} blue;
+ color: red #{white} blue;
+ color: red #{white}blue;
+ color: red#{white}blue;
+ color: #{umm}#{yeah}#{what};
+ color: #{stacked};
+
+ font-size: 10px/#{something};
+ font-size: 10px / #{something};
+
+ test: "what#{"world"}wrong";
+ test: "what#{'world'}wrong";
+ test: "what#{world}wrong";
+ test: "what"#{world}"wrong";
+
+ hi: "what is #{4 + 12} end"
+}
+
+
+// interpolation in selectors
+
+pre {
+ $var: cool;
+
+ #{var} {
+ color: red;
+ }
+
+ #{var} dad {
+ color: red;
+ }
+
+ bed#{var}dad {
+ color: red;
+ }
+}
+
+cool {
+ @for $x from 1 through 5 {
+ .thing-#{$x} {
+ color: red;
+ }
+ }
+}
+
+a#{b}c#{d}e {
+ color: red;
+}
+
+##{hello}, .#{world}{
+ color: red;
+}
+
+#abc#{hello}yeah, .cool#{world}yes{
+ color: red;
+}
+
+$scope: 2;
+
+div.element:nth-child(#{$scope}n)
+{
+ display: none;
+}
+
+// property interpolation
+
+div {
+ $var: hello;
+ #{$var}: world;
+ cool#{$var}:world;
+ #{$var}one:world;
+ two#{$var}one:world;
+
+ one#{a + b}two: cool;
+
+ #{hello}: {
+ #{world}: red;
+ #{mold}: white;
+ #{$var}: blue;
+ }
+
+}
+
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/keyword_args.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/keyword_args.scss
new file mode 100644
index 0000000..0b8e475
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/keyword_args.scss
@@ -0,0 +1,24 @@
+
+// mixins
+
+@mixin hello($a: one, $b:two, $c:three, $d: four) {
+ out: $a $b $c $d;
+}
+
+pre {
+ @include hello(alpha, $d: palace, $b: fort);
+}
+
+
+// functions
+
+@function cool($a, $b) {
+ @return $a - $b;
+}
+
+div {
+ hello: cool($b: 5, $a: 10);
+ world: cool(5, 10);
+}
+
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/list.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/list.scss
new file mode 100644
index 0000000..afeb742
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/list.scss
@@ -0,0 +1,15 @@
+$list: (black);
+$list: join($list, white, comma);
+
+div {
+ padding: join(10px 20px, 30px 40px);
+ margin: join((0, 10px), (10px, 10px), space);
+ background: linear-gradient($list);
+}
+
+$list: ();
+$list: join($list, (red, blue), comma);
+
+p {
+ background: linear-gradient($list);
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/looping.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/looping.scss
new file mode 100644
index 0000000..6f25e72
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/looping.scss
@@ -0,0 +1,51 @@
+
+div {
+ @each $var in what is this {
+ color: $var;
+ }
+
+ @each $var in what, is, this {
+ font: $var;
+ }
+
+ $list: what is this;
+ @each $var in $list {
+ background: $var;
+ }
+
+ $list: what, is, this;
+ @each $var in $list {
+ border: $var;
+ }
+}
+
+
+span {
+ $i: 0;
+ @while $i <= 10 {
+ color: $i;
+ $i: $i + 1;
+ }
+}
+
+pre {
+ @for $x from 1 to 5 {
+ color: $x;
+ }
+
+ @for $x from 1 through 5 {
+ height: $x;
+ }
+
+ $y: 10;
+ @for $x from $y through 3 {
+ cool: $x;
+ }
+
+}
+
+$j: null;
+@while $j {
+ .item { width: 2em; }
+ $j: false;
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/media.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/media.scss
new file mode 100644
index 0000000..3c2c147
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/media.scss
@@ -0,0 +1,208 @@
+
+// media syntax
+@media {
+ div { color: blue; }
+}
+@media what {
+ div { color: blue; }
+}
+
+@media (cool) {
+ div { color: blue; }
+}
+@media (cool: blue) {
+ div { color: blue; }
+}
+
+@media hello and (world) and (butt: man) {
+ div { color: blue; }
+}
+
+$navbarCollapseWidth: 940px;
+
+@media (max-width: $navbarCollapseWidth) {
+ color: red;
+}
+
+// media bubbling
+@media not hello and (world) {
+ color: blue;
+ pre {
+ color: blue;
+ }
+
+ @media butt {
+ color: red;
+ div {
+ color: red;
+ }
+ }
+}
+
+@media a, b {
+ @media c {
+ color: blue;
+ }
+}
+
+@media a{
+ @media b, c {
+ color: blue;
+ }
+}
+
+@media a, b{
+ @media c, d {
+ color: blue;
+ }
+}
+
+$media: cree;
+$feature: -webkit-min-device-pixel-ratio;
+$value: 1.5;
+
+div {
+ color: blue;
+ @media s#{$media}n and ($feature: $value) {
+ .sidebar {
+ width: 500px;
+ }
+ }
+}
+
+// @media + @mixin
+@mixin color {
+ color: red;
+ .success {
+ color: green;
+ }
+}
+
+div {
+ position: absolute;
+ $y: 2em;
+ @media screen {
+ top: 0;
+ $x: 5px;
+ p {
+ margin: $x;
+ }
+ bottom: 6em + $y;
+ @include color;
+ }
+}
+
+.button {
+ width: 300px;
+ height: 100px;
+ background: #eee;
+
+ :hover {
+ background: #aaa;
+ }
+
+ @media only screen and (max-width : 300px){
+ width: 100px;
+ height: 100px;
+ }
+}
+
+code {
+ position: absolute;
+ @media screen {
+ pre {
+ height: 20px;
+ }
+ height: 10px;
+ }
+}
+
+dt {
+ @media screen {
+ @media (color: blue) {
+ height: 10px;
+ }
+ }
+}
+
+// nesting media queries
+@media screen {
+ .screen {
+ width: 12px;
+ }
+ @media only screen {
+ .only-screen {
+ height: 11px;
+ }
+ }
+}
+
+@media only screen {
+ .only-screen {
+ width: 14px;
+ }
+ @media only screen {
+ .only-screen {
+ height: 16px;
+ }
+ }
+}
+
+@media not screen {
+ @media screen {
+ .invalid {
+ height: 12px;
+ }
+ }
+}
+
+@media not screen {
+ @media print {
+ .only-print {
+ height: 12px;
+ }
+ }
+}
+
+@media screen {
+ @media not print {
+ .only-print {
+ height: 12px;
+ }
+ }
+}
+
+@media not screen {
+ @media not print {
+ .invalid {
+ height: 12px;
+ }
+ }
+}
+
+@media not screen {
+ @media not screen {
+ .not-screen {
+ height: 15px;
+ }
+ }
+}
+
+@media only screen {
+ @media print {
+ .invalid {
+ height: 15px;
+ }
+ }
+}
+
+@media only screen {
+ @media screen and (color: blue) {
+ @media screen and (width: 13) {
+ .only-screen {
+ height: 15px;
+ }
+ }
+ }
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/mixins.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/mixins.scss
new file mode 100644
index 0000000..2e368a6
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/mixins.scss
@@ -0,0 +1,158 @@
+
+@mixin something {
+ color: red;
+ pre {
+ height: 200px;
+ }
+}
+
+div {
+ color: blue;
+ @include something;
+}
+
+@mixin something($color) {
+ color: $color;
+
+ div {
+ height: 20px;
+ }
+}
+
+@mixin cool($a, $b, $c) {
+ height: $a + $b + $c;
+}
+
+span {
+ @include something(blue);
+}
+
+html {
+ @include cool(10px, 12px, 21px);
+}
+
+
+@mixin hello_world {
+ height: 20px;
+}
+
+del {
+ @include hello-world;
+}
+
+
+// variable shadowing
+
+
+$color: white;
+@mixin colors($color: blue) {
+ color: $color;
+}
+
+div {
+ color: $color;
+ @include colors();
+ color: $color;
+}
+
+@mixin linear-gradient($from, $to, $pos: left top) {
+ background-image: linear-gradient($pos, $from, $to);
+}
+
+div {
+ @include linear-gradient(red, green);
+}
+
+@mixin box-shadow($shadows...) {
+ -moz-box-shadow: $shadows;
+ -webkit-box-shadow: $shadows;
+ box-shadow: $shadows;
+}
+
+div {
+ @include box-shadow(10px 10px 5px #888);
+ @include box-shadow(inset 10px 10px #888, -10px -10px #f4f4f4);
+}
+
+@mixin nested {
+ @include something(red);
+}
+
+div {
+ p {
+ .class {
+ @include nested;
+ }
+
+ @include nested;
+
+ .top {
+ top: 0;
+
+ div {
+ color: red;
+ }
+ }
+
+ color: blue;
+ }
+}
+
+// mixin content (http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixin-content)
+@mixin content-simple {
+ div.mixin-content-simple {
+ @content;
+ }
+}
+
+@mixin content-with-arg ( $background ) {
+ div.mixin-content-with-arg {
+ background: $background;
+ @content;
+ }
+}
+
+@include content-simple {
+ color: red;
+}
+
+@include content-with-arg($background: blue) {
+ color: red;
+}
+
+@include content-with-arg($background: purple) {
+ @include hello_world;
+}
+
+@include content-simple {
+ @include cool(10px, 12px, 21px);
+}
+
+@include content-simple {
+ @include something(orange);
+}
+
+@include content-with-arg($background: purple) {
+ @include cool(10px, 12px, 21px);
+}
+
+@include content-with-arg($background: purple) {
+ @include something(orange);
+}
+
+@mixin wallpaper($image, $top: 0, $right: 0, $bottom: 0, $left: 0) {
+ background: $image;
+ position: absolute;
+ top: $top;
+ right: $right;
+ bottom: $bottom;
+ left: $left;
+}
+
+@mixin logo($offsets...) {
+ @include wallpaper(url(/images/logo.png), $offsets...);
+}
+
+#please-wait {
+ @include logo(1em, $left: 4em, $bottom: 3em);
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/nesting.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/nesting.scss
new file mode 100644
index 0000000..68e3117
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/nesting.scss
@@ -0,0 +1,45 @@
+
+
+body {
+ color: red;
+}
+
+
+div {
+ color: red;
+ height: yes;
+
+ pre {
+ color: blue;
+ }
+}
+
+
+div: blue;
+
+
+div {
+ font: 10px hello world {
+ size: 10px;
+ color: blue;
+ }
+
+ border: {
+ left: 1px solid blue;
+ right: 2px dashed green;
+ }
+}
+
+
+#nested-nesting {
+ bar: baz;
+ bang: {
+ bop: bar;
+ bip: 1px;
+ blat: {
+ baf: bort
+ }
+ }
+}
+
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/null.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/null.scss
new file mode 100644
index 0000000..147dc2e
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/null.scss
@@ -0,0 +1,41 @@
+$list: null;
+.div {
+ one: null;
+ one: null world;
+ one: NULL world;
+ one: a null, b;
+ two: a $list $list, $list, b;
+ three: $list;
+}
+
+$value: null;
+ p:before {
+ content: "I ate #{$value} pies!";
+}
+
+@mixin Rounded($radius1, $direction: null, $radius2: false) {
+ $corner: null;
+ @if $direction == TL { $corner: top-left-; }
+ @if $direction == TR { $corner: top-right-; }
+ @if $direction == BL { $corner: bottom-left-; }
+ @if $direction == BR { $corner: bottom-right-; }
+ @if $radius2 {
+ -webkit-border-#{$corner}radius: $radius1 $radius2;
+ border-#{$corner}radius: $radius1 $radius2;
+ } @else {
+ -webkit-border-#{$corner}radius: $radius1;
+ border-#{$corner}radius: $radius1;
+ }
+}
+
+.foo {
+ @include Rounded(10);
+}
+
+.fu {
+ @include Rounded(20, null);
+}
+
+.bar {
+ @include Rounded(30, TL);
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/operators.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/operators.scss
new file mode 100644
index 0000000..eb6e20e
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/operators.scss
@@ -0,0 +1,143 @@
+
+
+body {
+ color: 1 + 2 + 5;
+ color: 1 + 2 * 5 + 5;
+ height: 10px/10px;
+ color: 10px/2 + 1;
+ color: (10px/2);
+ bottom: (4/2px);
+ top: 1em * (1 * 24px - 0) / 16px;
+ left: 1 - 2cm;
+ top: (2cm/12px);
+}
+
+div {
+ color: 4 == 3;
+ color: hello == hello;
+
+ color: 4 > 3;
+ color: 4 < 3;
+ color: what > 3;
+}
+
+
+#units {
+ test: 1in + 4cm;
+ test: 12mm + 1;
+ test: 1 + 3em;
+ test: 1mm + 1cm;
+ test: 1cm + 1mm;
+}
+
+#modulo {
+ test: 3 % 2;
+ test: 4cm % 3;
+}
+
+#colors {
+ color: red + rgb(1,2,3);
+ color: red - rgb(1,2,3);
+ color: rgba(1,2,3, 0.5) * rgba(3,4,5, 0.5);
+ color: rgba(10,15,20, 0.5) / rgba(2,2,2, 0.5);
+
+ color: rgba(1,2,3, 0.5) * 2;
+ color: rgba(1,2,3, 0.5) / 2;
+ color: rgba(1,2,3, 0.5) + 2;
+ color: rgba(1,2,3, 0.5) - 2;
+
+ color: blue + 34;
+
+ color: #fff == #000;
+ color: #fff == #fff;
+
+ color: #fff != #000;
+ color: #fff != #fff;
+}
+
+
+#preserve {
+ hello: what -going;
+ hello: what - going;
+}
+
+#strings {
+ hello: what -going;
+
+ hello: what +going;
+ hello: what+going;
+ hello: what+ going;
+ hello: what + going;
+
+ hello: "what" + going;
+ hello: going + "what";
+ hello: "what" + "what";
+}
+
+#negation {
+ $num: 100;
+ a: -$num + 40;
+ b: 10 -$num;
+ b: 10 - $num;
+}
+
+#bools-fail {
+ and: false and two;
+ and: one and two;
+ and: one and false;
+
+ or: false or two;
+ or: one or two;
+ or: one or false;
+}
+
+#bools {
+ and: (false and two);
+ and: (one and two);
+ and: (one and false);
+
+ or: (false or two);
+ or: (one or two);
+ or: (one or false);
+}
+
+
+#nots-fail {
+ not: not true + 2;
+ not: not false;
+ not: not 0;
+ not: not 1;
+ not: not "";
+ not: not hello;
+}
+
+#nots {
+ not: (not true) + 2;
+ not: (not false);
+ not: (not 0);
+ not: (not 1);
+ not: (not "");
+ not: (not hello);
+}
+
+#string-test {
+ str: hi == "hi";
+ str: hi == "no";
+ str: 'yes' == 'yes';
+
+ $var1: "hello";
+ $var2: hello;
+
+ str: "#{$var1}" == '#{$var2}';
+
+ str: xhello#{$var1}x == "x#{$var2}hellox"; // xhellohellofalse
+
+ str: unit(10px) == px;
+}
+
+
+#special {
+ cancel-unit: (10px / 10px);
+}
+
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/placeholder_selector.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/placeholder_selector.scss
new file mode 100644
index 0000000..da3cda1
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/placeholder_selector.scss
@@ -0,0 +1,18 @@
+#context a%extreme span {
+ color: blue;
+ font-weight: bold;
+ font-size: 2em;
+}
+
+.notice, .error { @extend %extreme; }
+
+.hidden %placeholder {
+ margin: 0;
+}
+
+p {
+ @extend #context;
+ padding: 2em;
+}
+
+div { @extend .hidden; } \ No newline at end of file
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/scss_css.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/scss_css.scss
new file mode 100644
index 0000000..03d63d0
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/scss_css.scss
@@ -0,0 +1,986 @@
+[foo~=bar] {
+ a: b; }
+
+
+[foo^=bar] {
+ a: b; }
+
+
+[foo$=bar] {
+ a: b; }
+
+
+[foo*=bar] {
+ a: b; }
+
+
+[foo|=en] {
+ a: b; }
+
+
+foo {
+ a: 2;
+ b: 2.3em;
+ c: 50%;
+ d: "fraz bran";
+ e: flanny-blanny-blan;
+ f: url(http://sass-lang.com);
+ // g: U+ffa?;
+ h: #aabbcc; }
+
+
+selector {
+ property: value;
+ property2: value; }
+
+
+sel{p:v}
+
+.foo {
+ /* Foo
+Bar
+ Baz */
+ a: b; }
+
+
+.foo {
+ /* Foo
+Bar
+ Baz */
+ a: b; }
+
+
+.foo {/* Foo
+ Bar */
+ a: b; }
+
+
+.foo {/* Foo
+ Bar
+ Baz */
+ a: b; }
+
+
+@foo {
+ rule {
+ a: b; }
+
+ a: b; }
+
+
+@foo {a:b};
+@bar {a:b};
+
+
+@foo "bar"
+
+foo {
+ a: 12px calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
+
+
+foo {bar: baz}
+<!--
+bar {bar: baz}
+-->
+baz {bar: baz}
+
+
+/*
+ * foo
+ */
+bar {baz: bang}
+
+
+E, F {
+ a: b; }
+
+
+E F, G H {
+ a: b; }
+
+
+E > F, G > H {
+ a: b; }
+
+
+/* This is a CSS comment. */
+.one {color: green;} /* Another comment */
+/* The following should not be used:
+.two {color: red;} */
+.three {color: green; /* color: red; */}
+/**
+.four {color: red;} */
+.five {color: green;}
+/**/
+.six {color: green;}
+/*********/
+.seven {color: green;}
+/* a comment **/
+.eight {color: green;}
+
+
+foo {
+ a: \foo bar;
+ b: foo\ bar;
+ c: \2022 \0020;
+ d: foo\\bar;
+ e: foo\"\'bar; }
+
+
+foo {
+ a: "\foo bar";
+ b: "foo\ bar";
+ c: "\2022 \0020";
+ d: "foo\\bar";
+ e: "foo\"'bar"; }
+
+
+foo {
+ _name: val;
+ *name: val;
+ :name: val;
+ .name: val;
+ #name: val;
+ name/**/: val;
+ name/*\**/: val;
+ name: val; }
+
+
+@foo "bar" ;
+
+foo {
+ a: -moz-element(#foo);
+ b: -webkit-element(#foo);
+ b: -foobar-element(#foo); }
+
+
+@foo {}
+
+@foo {
+}
+
+
+@foo;
+
+foo {;;;;
+ bar: baz;;;;
+ ;;}
+
+
+#foo .bar {}
+
+#foo .bar {
+}
+
+
+0% {
+ a: b; }
+
+
+60% {
+ a: b; }
+
+
+100% {
+ a: b; }
+
+
+12px {
+ a: b; }
+
+
+"foo" {
+ a: b; }
+
+
+foo {
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
+
+
+:foo("bar") {
+ a: b; }
+
+
+:foo(bar) {
+ a: b; }
+
+
+:foo(12px) {
+ a: b; }
+
+
+:foo(+) {
+ a: b; }
+
+
+:foo(-) {
+ a: b; }
+
+
+:foo(+"bar") {
+ a: b; }
+
+
+:foo(-++--baz-"bar"12px) {
+ a: b; }
+
+
+foo {
+ a: foo-bar(12);
+ b: -foo-bar-baz(13, 14 15); }
+
+
+@import "foo.css";
+
+@import 'foo.css';
+
+@import url("foo.css");
+
+@import url('foo.css');
+
+@import url(foo.css);
+
+@import "foo.css" screen;
+
+@import "foo.css" screen, print;
+
+@import "foo.css" screen, print and (foo: 0);
+
+@import "foo.css" screen, only print, screen and (foo: 0);
+
+foo {
+ a: foo !important;
+ b: foo bar !important;
+ b: foo, bar !important; }
+
+
+foo {
+ a: -moz-bar-baz;
+ b: foo -o-bar-baz; }
+
+
+foo {a: /* b; c: */ d}
+
+
+foo {a /*: b; c */: d}
+
+
+/* Foo
+ * Bar */
+
+
+.foo {
+ /* Foo
+ * Bar */ }
+
+
+[foo] {
+ a: b; }
+
+
+[foo="bar"] {
+ a: b; }
+
+
+[foo~="bar"] {
+ a: b; }
+
+
+[foo^="bar"] {
+ a: b; }
+
+
+[foo$="bar"] {
+ a: b; }
+
+
+[foo*="bar"] {
+ a: b; }
+
+
+[foo|="en"] {
+ a: b; }
+
+
+:root {
+ a: b; }
+
+
+:nth-child(n) {
+ a: b; }
+
+
+:nth-last-child(n) {
+ a: b; }
+
+
+:nth-of-type(n) {
+ a: b; }
+
+
+:nth-last-of-type(n) {
+ a: b; }
+
+
+:first-child {
+ a: b; }
+
+
+:last-child {
+ a: b; }
+
+
+:first-of-type {
+ a: b; }
+
+
+:last-of-type {
+ a: b; }
+
+
+:only-child {
+ a: b; }
+
+
+:only-of-type {
+ a: b; }
+
+
+:empty {
+ a: b; }
+
+
+:link {
+ a: b; }
+
+
+:visited {
+ a: b; }
+
+
+:active {
+ a: b; }
+
+
+:hover {
+ a: b; }
+
+
+:focus {
+ a: b; }
+
+
+:target {
+ a: b; }
+
+
+:lang(fr) {
+ a: b; }
+
+
+:enabled {
+ a: b; }
+
+
+:disabled {
+ a: b; }
+
+
+:checked {
+ a: b; }
+
+
+::first-line {
+ a: b; }
+
+
+::first-letter {
+ a: b; }
+
+
+::before {
+ a: b; }
+
+
+::after {
+ a: b; }
+
+
+.warning {
+ a: b; }
+
+
+#myid {
+ a: b; }
+
+
+:not(s) {
+ a: b; }
+
+
+@media all {
+ rule1 {
+ prop: val; }
+
+ rule2 {
+ prop: val; } }
+
+
+@media screen, print {
+ rule1 {
+ prop: val; }
+
+ rule2 {
+ prop: val; } }
+
+
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+ a: b; }
+
+
+@media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
+ a: b; }
+
+
+:-moz-any(h1, h2, h3) {
+ a: b; }
+
+
+:-moz-any(.foo) {
+ a: b; }
+
+
+:-moz-any(foo bar, .baz > .bang) {
+ a: b; }
+
+
+@-moz-document url(http://www.w3.org/),
+ url-prefix(http://www.w3.org/Style/),
+ domain(mozilla.org),
+ regexp("^https:.*") {
+ .foo {a: b}
+}
+
+
+foo {
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
+ filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
+
+
+foo {
+ filter: alpha(opacity=20);
+ filter: alpha(opacity=20, enabled=true);
+ filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); }
+
+
+@foo bar {
+ a: b; }
+
+@bar baz {
+ c: d; }
+
+
+@foo bar;
+@bar baz;
+
+
+/* Foo
+ * Bar */
+/* Baz
+ * Bang */
+
+
+.foo {
+ /* Foo
+ * Bar */
+ /* Baz
+ * Bang */ }
+
+
+.foo {
+ /* Foo Bar *//* Baz Bang */ }
+
+
+@namespace "http://www.w3.org/Profiles/xhtml1-strict";
+
+@namespace url(http://www.w3.org/Profiles/xhtml1-strict);
+
+@namespace html url("http://www.w3.org/Profiles/xhtml1-strict");
+
+[foo|bar=baz] {
+ a: b; }
+
+
+[*|bar=baz] {
+ a: b; }
+
+
+[foo|bar|=baz] {
+ a: b; }
+
+
+foo|E {
+ a: b; }
+
+
+*|E {
+ a: b; }
+
+
+foo|* {
+ a: b; }
+
+
+*|* {
+ a: b; }
+
+
+:not(foo|bar) {
+ a: b; }
+
+
+:not(*|bar) {
+ a: b; }
+
+
+:not(foo|*) {
+ a: b; }
+
+
+:not(*|*) {
+ a: b; }
+
+
+:not(#blah) {
+ a: b; }
+
+
+:not(.blah) {
+ a: b; }
+
+
+:not([foo]) {
+ a: b; }
+
+
+:not([foo^="bar"]) {
+ a: b; }
+
+
+:not([baz|foo~="bar"]) {
+ a: b; }
+
+
+:not(:hover) {
+ a: b; }
+
+
+:not(:nth-child(2n + 3)) {
+ a: b; }
+
+
+:not(:not(#foo)) {
+ a: b; }
+
+
+:not(a#foo.bar) {
+ a: b; }
+
+
+:not(#foo .bar > baz) {
+ a: b; }
+
+
+:not(h1, h2, h3) {
+ a: b; }
+
+
+@mixin foo {
+ a: b; }
+
+
+foo {
+ a: "bang #{1 + " bar "} bip"; }
+
+
+:nth-child(-n) {
+ a: b; }
+
+
+:nth-child(+n) {
+ a: b; }
+
+
+:nth-child(even) {
+ a: b; }
+
+
+:nth-child(odd) {
+ a: b; }
+
+
+:nth-child(50) {
+ a: b; }
+
+
+:nth-child(-50) {
+ a: b; }
+
+
+:nth-child(+50) {
+ a: b; }
+
+
+:nth-child(2n+3) {
+ a: b; }
+
+
+:nth-child(2n-3) {
+ a: b; }
+
+
+:nth-child(+2n-3) {
+ a: b; }
+
+
+:nth-child(-2n+3) {
+ a: b; }
+
+
+:nth-child(-2n+ 3) {
+ a: b; }
+
+
+:nth-child( 2n + 3 ) {
+ a: b; }
+
+
+foo {
+ a: foo bar baz;
+ b: foo, #aabbcc, -12;
+ c: 1px/2px/-3px;
+ d: foo bar, baz/bang; }
+
+
+@page {
+ prop1: val;
+ prop2: val; }
+
+
+@page flap {
+ prop1: val;
+ prop2: val; }
+
+
+@page :first {
+ prop1: val;
+ prop2: val; }
+
+
+@page flap:first {
+ prop1: val;
+ prop2: val; }
+
+
+.foo {
+ /* Foo */
+ a: b; }
+
+
+.foo {
+ /* Foo
+ * Bar */a: b; }
+
+
+/* Foo */
+.foo {
+ a: b; }
+
+
+/* Foo
+ * Bar */.foo {
+ a: b; }
+
+
+.foo /* .a #foo */ #bar:baz(/* bang )*/ bip) {
+ a: b; }
+
+
+> E {
+ a: b; }
+
+
++ E {
+ a: b; }
+
+
+~ E {
+ a: b; }
+
+
+> > E {
+ a: b; }
+
+
+>> E {
+ a: b; }
+
+
+E* {
+ a: b; }
+
+
+E*.foo {
+ a: b; }
+
+
+E*:hover {
+ a: b; }
+
+
+E,
+F {
+ a: b; }
+
+
+E
+F {
+ a: b; }
+
+
+E, F
+G, H {
+ a: b; }
+
+
+body {
+ /*
+ //comment here
+ */
+}
+
+
+E>F { a: b;}
+
+E~F { a: b;}
+
+E+F { a: b;}
+
+* {
+ a: b; }
+
+
+E {
+ a: b; }
+
+
+E[foo] {
+ a: b; }
+
+
+E[foo="bar"] {
+ a: b; }
+
+
+E[foo~="bar"] {
+ a: b; }
+
+
+E[foo^="bar"] {
+ a: b; }
+
+
+E[foo$="bar"] {
+ a: b; }
+
+
+E[foo*="bar"] {
+ a: b; }
+
+
+E[foo|="en"] {
+ a: b; }
+
+
+E:root {
+ a: b; }
+
+
+E:nth-child(n) {
+ a: b; }
+
+
+E:nth-last-child(n) {
+ a: b; }
+
+
+E:nth-of-type(n) {
+ a: b; }
+
+
+E:nth-last-of-type(n) {
+ a: b; }
+
+
+E:first-child {
+ a: b; }
+
+
+E:last-child {
+ a: b; }
+
+
+E:first-of-type {
+ a: b; }
+
+
+E:last-of-type {
+ a: b; }
+
+
+E:only-child {
+ a: b; }
+
+
+E:only-of-type {
+ a: b; }
+
+
+E:empty {
+ a: b; }
+
+
+E:link {
+ a: b; }
+
+
+E:visited {
+ a: b; }
+
+
+E:active {
+ a: b; }
+
+
+E:hover {
+ a: b; }
+
+
+E:focus {
+ a: b; }
+
+
+E:target {
+ a: b; }
+
+
+E:lang(fr) {
+ a: b; }
+
+
+E:enabled {
+ a: b; }
+
+
+E:disabled {
+ a: b; }
+
+
+E:checked {
+ a: b; }
+
+
+E::first-line {
+ a: b; }
+
+
+E::first-letter {
+ a: b; }
+
+
+E::before {
+ a: b; }
+
+
+E::after {
+ a: b; }
+
+
+E.warning {
+ a: b; }
+
+
+E#myid {
+ a: b; }
+
+
+E:not(s) {
+ a: b; }
+
+
+E F {
+ a: b; }
+
+
+E > F {
+ a: b; }
+
+
+E + F {
+ a: b; }
+
+
+E ~ F {
+ a: b; }
+
+
+@supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+ .foo {
+ a: b;
+ }
+}
+
+
+@-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+ .foo {
+ a: b;
+ }
+}
+
+
+foo {
+ foo: bar;
+ #baz: bang;
+ #bip: bop; }
+
+
+foo {
+ a: -2;
+ b: -2.3em;
+ c: -50%;
+ d: -foo(bar baz); }
+
+
+foo {
+ a: -0.5em;
+ b: +0.5em;
+ c: -foo(12px);
+ d: +foo(12px);
+ }
+
+
+@charset "UTF-8";
+
+foo {
+ -moz-foo-bar: blat;
+ -o-flat-blang: wibble; }
+
+
+foo {
+ a: foo();
+ b: bar baz-bang() bip; }
+
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/selectors.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/selectors.scss
new file mode 100644
index 0000000..01c7f8b
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/selectors.scss
@@ -0,0 +1,187 @@
+* { color: blue; }
+E { color: blue; }
+
+E:not(:link) { color: blue; }
+E:not(:link):not(:visited) { color: blue; }
+E:not(:link, :visited) { color: blue; }
+E:matches(:hover, :focus) { color: blue; }
+
+E.warning { color: blue; }
+E#id { color: blue; }
+E[foo] { color: blue; }
+E[foo="barbar"] { color: blue; }
+E[foo="barbar" i] { color: blue; }
+E[foo~="hello#$@%@$#^"] { color: blue; }
+E[foo^="color: green;"] { color: blue; }
+E[foo$="239023"] { color: blue; }
+E[foo*="29302"] { color: blue; }
+E[foo|="239032"] { color: blue; }
+
+[foo] { color: blue; }
+[foo] .helloWorld { color: blue; }
+[foo].helloWorld { color: blue; }
+[foo="barbar"] { color: blue; }
+[foo~="hello#$@%@$#^"] { color: blue; }
+[foo^="color: green;"] { color: blue; }
+[foo$="239023"] { color: blue; }
+[foo*="29302"] { color: blue; }
+[foo|="239032"] { color: blue; }
+
+E:dir(ltr) { color: blue; }
+E:lang(en) { color: blue; }
+E:lang(en, fr) { color: blue; }
+
+E:any-link { color: blue; }
+E:link { color: blue; }
+E:visited { color: blue; }
+E:local-link { color: blue; }
+E:local-link(0) { color: red; }
+E:local-link(1) { color: white; }
+E:local-link(2) { color: red; }
+E:target { color: blue; }
+E:scope { color: blue; }
+
+E:current { color: blue; }
+E:current(:link) { color: blue; }
+E:past { color: blue; }
+E:future { color: blue; }
+
+E:active { color: blue; }
+E:hover { color: blue; }
+E:focus { color: blue; }
+E:enabled { color: blue; }
+E:disabled { color: blue; }
+E:indeterminate { color: blue; }
+E:default { color: blue; }
+E:in-range { color: blue; }
+E:out-of-range { color: blue; }
+E:required { color: blue; }
+E:optional { color: blue; }
+E:read-only { color: blue; }
+E:read-write { color: blue; }
+
+E:root { color: blue; }
+E:empty { color: blue; }
+E:first-child { color: blue; }
+E:nth-child(odd) { color: blue; }
+E:nth-child(2n+1) { color: blue; }
+E:nth-child(5) { color: blue; }
+E:last-child { color: blue; }
+E:nth-last-child(-n+2) { color: blue; }
+E:only-child { color: blue; }
+E:first-of-type { color: blue; }
+E:nth-of-type(2n) { color: blue; }
+E:last-of-type { color: blue; }
+E:nth-last-of-type(n) { color: blue; }
+E:only-of-type { color: blue; }
+E:nth-match(odd) { color: blue; }
+E:nth-last-match(odd) { color: blue; }
+
+E:column(n) { color: blue; }
+E:nth-column(n) { color: blue; }
+E:nth-last-column(n) { color: blue; }
+
+E F { color: blue; }
+E > F { color: blue; }
+E + F { color: blue; }
+E ~ F { color: blue; }
+E /foo/ F { color: blue; }
+E! > F { color: blue; }
+
+// namespaces
+[foo|att=val] { color: blue }
+[*|att] { color: yellow }
+[|att] { color: green }
+[att] { color: green }
+
+// CSS2.1
+E::first-line { color: blue; }
+E::first-letter { color: blue; }
+E::before { color: blue; }
+E::after { color: blue; }
+
+// CSS3 UI (at risk)
+E::choices { color: blue; }
+E::value { color: blue; }
+E::repeat-index { color: blue; }
+E::repeat-item { color: blue; }
+
+E:first { color: blue; }
+E:first-line { color: blue; }
+E:first-letter { color: blue; }
+E:before{ color: blue; }
+E:after { color: blue; }
+E:checked { color: blue; }
+E:invalid { color: blue; }
+E:valid { color: blue; }
+E:left { color: blue; }
+E:right { color: blue; }
+
+// -moz experimental
+E:any(ol) { color: blue; }
+E::selection { color: blue; }
+
+// one of these is nested property,
+// the other is a css block.
+div {
+ font:something {
+ size: 30em;
+ }
+
+ font: something {
+ size: 30em;
+ }
+
+}
+
+// self selector
+
+.something {
+ &.world {
+ color: blue;
+ }
+
+ & .mold {
+ height: 200px;
+ }
+
+ .dog & {
+ color: blue;
+ }
+}
+
+.simple {
+ .dad & .wolf {
+ color: blue;
+ }
+
+ .rad&.bad {
+ color: blue;
+ }
+
+}
+
+div {
+ .something & .what {
+ &.world {
+ color: blue;
+ }
+ }
+}
+
+div {
+ &.foo & {
+ color: blue;
+ }
+}
+
+.main, div {
+ .message div {
+ .title {
+ .nice-fonts & {
+ font-size: 24px;
+ }
+ }
+ }
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/values.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/values.scss
new file mode 100644
index 0000000..45123a5
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/values.scss
@@ -0,0 +1,43 @@
+
+#values {
+ color: #eee;
+ color: #eeeeee;
+ height: 20px;
+ width: 80%;
+ color: "hello world";
+ height: url("http://google.com");
+ dads: url(http://leafo.net);
+ padding: 10px 10px 10px 10px, 3px 3px 3px;
+ textblock: "This is a \
+multiline block \
+#not { color: #eee;}";
+ margin: 4,3,1;
+ content: "This is a \
+multiline string.";
+ border-radius: -1px -1px -1px black;
+}
+
+#subtraction {
+ lit: 10 -11;
+ lit: 10 - 11;
+ lit: 10- 11;
+ lit: 10-11;
+
+ $num: 100;
+ var: 10 -$num;
+ var: 10 - $num;
+ var: 10- $num;
+ var: 10-$num;
+}
+
+
+#special {
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12);
+}
+
+#unary {
+ b: +0.5em;
+ c: -foo(12px);
+ d: +foo(12px);
+}
+
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/inputs/variables.scss b/public/system/storage/vendor/leafo/scssphp/tests/inputs/variables.scss
new file mode 100644
index 0000000..bebd4dc
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/inputs/variables.scss
@@ -0,0 +1,56 @@
+
+$color: red, two, three;
+
+div {
+ height: $color;
+}
+
+$a: 1000;
+
+div {
+ $a: 2000 !default;
+ num: $a;
+}
+
+div {
+ $b: 2000 !default;
+ num: $b;
+}
+
+$cool_color: null;
+$cool_color: blue !default;
+
+pre {
+ color: $cool_color;
+}
+
+$something_man: 100px;
+cool: $something_man;
+
+
+del {
+ $something: blue;
+
+ div {
+ $something: red;
+ pre {
+ color: $something;
+ }
+ }
+
+ color: $something;
+}
+
+$font-family-simple: Arial !default;
+$font-family-spaces: Helvetica Neue !default;
+$font-family-quotes: "Helvetica Neue" !default;
+$font-family-commas: Helvetica, Arial, sans-serif !default;
+$font-family-sans: "Helvetica Neue", Helvetica, Arial, sans-serif !default;
+
+body {
+ font-family: $font-family-simple;
+ font-family: $font-family-spaces;
+ font-family: $font-family-quotes;
+ font-family: $font-family-commas;
+ font-family: $font-family-sans;
+}
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/builtins.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/builtins.css
new file mode 100644
index 0000000..b7884c2
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/builtins.css
@@ -0,0 +1,126 @@
+#color {
+ color: #22ea18;
+ red: 34;
+ green: 234;
+ blue: 24;
+ color: rgba(1, 2, 4, 0.5);
+ a1: 1;
+ a2: 0.5;
+ mix: #020304;
+ rgba: rgba(170, 119, 204, 0.4);
+ rgba: rgba(170, 119, 204, 0.4); }
+
+#hsl {
+ color: #79c653;
+ color: rgba(121, 198, 83, 0.5);
+ hue: 100deg;
+ sat: 50%;
+ lig: 55%; }
+
+#more-color {
+ light: #7e3d9e;
+ dark: #432154;
+ sat: #632782;
+ desat: #5e3871;
+ gray: #545454;
+ comp: #48792f;
+ inv: #9fd086; }
+
+#more-more-color {
+ op: 0.5;
+ opacify: rgba(1, 2, 3, 0.6);
+ opacify: rgba(1, 2, 3, 0.6);
+ transparentize: rgba(1, 2, 3, 0.4);
+ transparentize: rgba(1, 2, 3, 0.4);
+ transparentize: rgba(52, 130, 3, 0.9); }
+
+#more-more-more-color {
+ color: rgba(65, 110, 79, 0.4);
+ color: rgba(20, 255, 216, 0);
+ color: rgba(55, 100, 69, 0.4);
+ color: rgba(0, 255, 213, 0);
+ color: rgba(145, 10, 10, 0);
+ color: rgba(5, 10, 10, 0);
+ color: rgba(145, 145, 145, 0);
+ color: rgba(5, 5, 5, 0);
+ color: #000A0A0A;
+ color: #FFAABBCC; }
+
+#string {
+ color: hello what is going on;
+ color: "yeah";
+ color: "I do?"; }
+
+#number {
+ color: 250%;
+ color: 3;
+ color: 3;
+ color: 4;
+ top: 10px;
+ top: 1ex;
+ width: 200%;
+ bottom: 10px;
+ padding: 3em 1in 96px 72pt; }
+
+#list {
+ len: 3;
+ len: 1;
+ n: hello;
+ hello: one, two, three, hello;
+ hello: one, two, three, hello, world, what, is, going;
+ hello: one, two, three, hello;
+ index: 2;
+ index: false;
+ index: 3;
+ index: 1;
+ index: false;
+ index: 1;
+ index: false;
+ index: 2;
+ index: 2;
+ index: 1;
+ world: one, two, three, great, job;
+ world: one, two, three, great job;
+ cool: one two three great job;
+ cool: great job one two three;
+ zip: 1px solid, 2px dashed;
+ zip: 1px solid red, 2px dashed green; }
+
+#introspection {
+ t: number;
+ t: string;
+ t: string;
+ t: bool;
+ t: color;
+ t: color;
+ t: list;
+ u: "";
+ u: "px";
+ u: "em";
+ l: true;
+ l: false;
+ c: true;
+ c: false;
+ c: true;
+ c: true;
+ c: false;
+ c: true; }
+
+#if {
+ color: yes;
+ color: no;
+ color: yes;
+ color: yes; }
+
+.transparent {
+ r: 0;
+ g: 0;
+ b: 0;
+ a: 0; }
+
+.alpha {
+ a: 1;
+ a: 1;
+ a: 1;
+ a: 0.5;
+ a: alpha(currentColor); }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/comments.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/comments.css
new file mode 100644
index 0000000..751ddfe
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/comments.css
@@ -0,0 +1,19 @@
+/** what the heck **/
+/**
+
+Here is a block comment
+
+**/
+/*hello*/
+div {
+ /* another property */
+ border: 1px solid red;
+ color: url('http://mage-page.com');
+ string: "hello /* this is not a comment */";
+ world: "// neither is this";
+ /*what if this is a comment */
+ string: 'hello /* this is not a comment */';
+ world: '// neither is this';
+ what-ever: 100px;
+ /*this is not a comment?*/
+ background: url(); }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/compass_extract.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/compass_extract.css
new file mode 100644
index 0000000..8ae7f37
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/compass_extract.css
@@ -0,0 +1,28 @@
+#test-0 {
+ unit: false;
+ unit: true;
+ rhythm: 1.5em;
+ size: 1;
+ size: 1;
+ size: 1;
+ size: 2;
+ size: 2; }
+
+#test-1 {
+ margin-top: 7.5em;
+ padding-top: 9em;
+ padding-bottom: 10.5em;
+ margin-bottom: 0em; }
+
+#test-2 {
+ border-style: solid;
+ border-width: 0.0625em;
+ padding: 1.4375em; }
+
+#test-3 {
+ border-top-style: solid;
+ border-top-width: 0.0625em;
+ padding-top: 1.4375em;
+ border-bottom-style: solid;
+ border-bottom-width: 0.0625em;
+ padding-bottom: 1.4375em; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/content.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/content.css
new file mode 100644
index 0000000..6657a21
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/content.css
@@ -0,0 +1,29 @@
+* html #logo {
+ background-image: url(/logo.gif); }
+
+.colors {
+ background-color: blue;
+ color: white;
+ border-color: blue; }
+
+@media only screen and (max-width: 480px) {
+ body {
+ color: red; } }
+
+#sidebar {
+ width: 300px; }
+ @media only screen and (max-width: 480px) {
+ #sidebar {
+ width: 100px; } }
+
+@media only screen and (min-width: 40em) {
+ .grid-1 {
+ width: 100%; }
+ .grid-2 {
+ width: 100%; } }
+
+@media only screen and (min-width: 40em) {
+ .grid-1 {
+ width: 100%; }
+ .grid-2 {
+ width: 100%; } }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/content_with_function.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/content_with_function.css
new file mode 100644
index 0000000..185fe66
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/content_with_function.css
@@ -0,0 +1,2 @@
+body {
+ padding: 1 px; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/default_args.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/default_args.css
new file mode 100644
index 0000000..19379e0
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/default_args.css
@@ -0,0 +1,3 @@
+div {
+ height: red;
+ margin: 100px; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/directives.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/directives.css
new file mode 100644
index 0000000..2b71558
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/directives.css
@@ -0,0 +1,77 @@
+@charset "hello-world";
+@page :left {
+ div {
+ color: red; } }
+
+@page test {
+ @media yes {
+ div {
+ color: red; } } }
+
+@media something {
+ @page {
+ @media else {
+ div {
+ height: 200px; } } } }
+
+div {
+ color: red; }
+ @page yeah {
+ div pre {
+ height: 20px; } }
+
+@font-face {
+ color: red;
+ height: 20px; }
+
+@keyframes 'bounce' {
+ from {
+ top: 100px;
+ animation-timing-function: ease-out; }
+
+ 25% {
+ top: 50px;
+ animation-timing-function: ease-in; }
+
+ 50% {
+ top: 100px;
+ animation-timing-function: ease-out; }
+
+ 75% {
+ top: 75px;
+ animation-timing-function: ease-in; }
+
+ to {
+ top: 100px; } }
+
+@-webkit-keyframes flowouttoleft {
+ 0% {
+ -webkit-transform: translateX(0) scale(1); }
+
+ 60%, 70% {
+ -webkit-transform: translateX(0) scale(0.7); }
+
+ 100% {
+ -webkit-transform: translateX(-100%) scale(0.7); } }
+
+div {
+ animation-name: 'diagonal-slide';
+ animation-duration: 5s;
+ animation-iteration-count: 10; }
+
+@keyframes 'diagonal-slide' {
+ from {
+ left: 0;
+ top: 0; }
+
+ to {
+ left: 100px;
+ top: 100px; } }
+
+@document url(http://www.w3.org/),
+ url-prefix(http://www.w3.org/Style/),
+ domain(mozilla.org),
+ regexp("https:.*") {
+ body {
+ color: purple;
+ background: yellow; } }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/extends.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/extends.css
new file mode 100644
index 0000000..e40cd86
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/extends.css
@@ -0,0 +1,87 @@
+error, pre seriousError, span seriousError, other, hello {
+ border: 1px #f00;
+ background-color: #fdd; }
+
+pre seriousError, span seriousError {
+ font-size: 20px; }
+
+hello {
+ color: green; }
+ hello div {
+ margin: 10px; }
+
+.cool, .me {
+ color: red; }
+
+.blue, .me {
+ color: purple; }
+
+a:hover, .hoverlink, #demo .overview .fakelink:hover {
+ text-decoration: underline; }
+
+div.hello.world.hmm, pre div.okay.span.world.hmm, pre #butt .umm div.sure.span.world.hmm, #butt .umm pre div.sure.span.world.hmm, code div.okay.span.world.hmm, code #butt .umm div.sure.span.world.hmm, #butt .umm code div.sure.span.world.hmm {
+ color: blue; }
+
+.xxxxx .xxxxx .xxxxx, code .xxxxx .xxxxx, code code .xxxxx, code code code, code .xxxxx code, .xxxxx code .xxxxx, .xxxxx code code, .xxxxx .xxxxx code {
+ color: green; }
+
+code {
+ color: red; }
+
+.alpha, .beta, .gama {
+ color: red; }
+
+.beta, .gama {
+ color: white; }
+
+.gama {
+ color: blue; }
+
+#admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink {
+ font-weight: bold; }
+
+a1 b1 c1 d1, x1 y1 z1 w1 b1 c1 d1 {
+ color: red; }
+
+a2 b2 c2 d2, a2 x2 y2 z2 w2 c2 d2, x2 y2 z2 a2 w2 c2 d2 {
+ color: red; }
+
+a3 b3 c3 d3, a3 b3 x3 y3 z3 w3 d3, x3 y3 z3 a3 b3 w3 d3 {
+ color: red; }
+
+a4 b4 c4 d4, a4 b4 c4 x4 y4 z4 w4, x4 y4 z4 a4 b4 c4 w4 {
+ color: red; }
+
+#butt .yeah .okay, #butt .yeah .umm .sure, #butt .umm .yeah .sure {
+ font-weight: bold; }
+
+a9 b9 s9 t9 v9, a9 b9 s9 t9 x9 y9 z9, a9 b9 x9 y9 s9 t9 z9 {
+ color: red; }
+
+@media print {
+ horse, man {
+ color: blue; } }
+
+man {
+ color: red; }
+
+wassup {
+ color: blue; }
+
+.foo .wassup {
+ color: blue; }
+
+#something, .x, .y {
+ color: red; }
+
+.nav-justified, .nav-tabs.nav-justified {
+ text-align: justify; }
+
+.btn:hover, .edit .actions button:hover, .edit .new .actions button:hover, .btn:active, .edit .actions button:active, .edit .new .actions button:active, .btn.active, .edit .actions button.active, .edit .new .actions button.active, .btn.disabled, .edit .actions button.disabled, .edit .new .actions button.disabled, .btn[disabled], .edit .actions button[disabled], .edit .new .actions button[disabled] {
+ color: red; }
+
+.edit .actions button {
+ float: right; }
+
+.edit .new .actions {
+ padding: 0; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/filter_effects.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/filter_effects.css
new file mode 100644
index 0000000..7d0bee8
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/filter_effects.css
@@ -0,0 +1,20 @@
+#number {
+ -webkit-filter: grayscale(1) sepia(0.5) saturate(0.1) invert(1) opacity(0.5) brightness(0.5) contrast(0.5); }
+
+#percentage {
+ -webkit-filter: grayscale(100%) sepia(50%) saturate(10%) invert(100%) opacity(50%) brightness(50%) contrast(50%); }
+
+#misc {
+ -webkit-filter: hue-rotate(90deg) blur(10px) drop-shadow(10px -16px 30px purple); }
+
+#decimal {
+ opacity: 0.5;
+ filter: alpha(opacity=50, style=1); }
+
+#percent {
+ opacity: 0.5;
+ filter: alpha(opacity=50); }
+
+.row {
+ background-color: #071c23;
+ color: #2284a1; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/functions.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/functions.css
new file mode 100644
index 0000000..a19ae74
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/functions.css
@@ -0,0 +1,22 @@
+div {
+ color: 14px;
+ sum: 23; }
+
+div {
+ hello: 10 55;
+ hello: 1010 55;
+ hello: "hello 10 and 55"; }
+
+del {
+ color: 1000; }
+
+div {
+ hello: "hello foo and bar";
+ hello: "hello bar and default";
+ hello: "hello Alice, Bob, Tom"; }
+
+.foo {
+ test2: -moz-art; }
+
+div span {
+ height: 3px; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/ie7.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/ie7.css
new file mode 100644
index 0000000..7196fb1
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/ie7.css
@@ -0,0 +1,8 @@
+#foo:before {
+ content: counter(item,".") ": "; }
+
+#bar:before {
+ content: counter(item,"."); }
+
+#fu:before {
+ content: counter(item); }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/if.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/if.css
new file mode 100644
index 0000000..b9d0520
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/if.css
@@ -0,0 +1,21 @@
+div {
+ color: blue; }
+
+pre {
+ val-1: "red";
+ val-2: "blue";
+ val-3: "blue";
+ val-4: "red";
+ val-5: "red"; }
+
+span {
+ color: blue;
+ height: 10px;
+ width: 20px; }
+
+div {
+ color: blue;
+ border-color: green; }
+
+del {
+ thing: no; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/if_on_null.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/if_on_null.css
new file mode 100644
index 0000000..2dfca95
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/if_on_null.css
@@ -0,0 +1,2 @@
+body {
+ background-color: "red"; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/import.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/import.css
new file mode 100644
index 0000000..1cd9b6b
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/import.css
@@ -0,0 +1,27 @@
+@import "foo.css";
+@import "foo" screen;
+@import "http://foo.com/bar";
+@import url(foo);
+div {
+ height: 200px;
+ color: red; }
+
+pre {
+ color: red; }
+ pre div {
+ height: 200px;
+ color: red; }
+
+code div {
+ height: 200px;
+ color: red; }
+ code div {
+ height: 200px;
+ color: red; }
+
+#partial {
+ color: blue; }
+
+body {
+ color: #7c2;
+ background: gray; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/interpolation.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/interpolation.css
new file mode 100644
index 0000000..89dc81c
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/interpolation.css
@@ -0,0 +1,54 @@
+div {
+ color: redwhite blue;
+ color: red white blue;
+ color: red whiteblue;
+ color: redwhiteblue;
+ color: ummyeahwhat;
+ color: stacked;
+ font-size: 10px/something;
+ font-size: 10px / something;
+ test: "whatworldwrong";
+ test: "whatworldwrong";
+ test: "whatworldwrong";
+ test: "what"world"wrong";
+ hi: "what is 16 end"; }
+
+pre var {
+ color: red; }
+ pre var dad {
+ color: red; }
+ pre bedvardad {
+ color: red; }
+
+cool .thing-1 {
+ color: red; }
+ cool .thing-2 {
+ color: red; }
+ cool .thing-3 {
+ color: red; }
+ cool .thing-4 {
+ color: red; }
+ cool .thing-5 {
+ color: red; }
+
+abcde {
+ color: red; }
+
+#hello, .world {
+ color: red; }
+
+#abchelloyeah, .coolworldyes {
+ color: red; }
+
+div.element:nth-child(2n) {
+ display: none; }
+
+div {
+ hello: world;
+ coolhello: world;
+ helloone: world;
+ twohelloone: world;
+ oneabtwo: cool;
+ hello-world: red;
+ hello-mold: white;
+ hello-hello: blue; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/keyword_args.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/keyword_args.css
new file mode 100644
index 0000000..441c4ab
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/keyword_args.css
@@ -0,0 +1,6 @@
+pre {
+ out: alpha fort three palace; }
+
+div {
+ hello: 5;
+ world: -5; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/list.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/list.css
new file mode 100644
index 0000000..4e54729
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/list.css
@@ -0,0 +1,7 @@
+div {
+ padding: 10px 20px 30px 40px;
+ margin: 0 10px 10px 10px;
+ background: linear-gradient(black, white); }
+
+p {
+ background: linear-gradient(red, blue); }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/looping.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/looping.css
new file mode 100644
index 0000000..db58f4a
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/looping.css
@@ -0,0 +1,45 @@
+div {
+ color: what;
+ color: is;
+ color: this;
+ font: what;
+ font: is;
+ font: this;
+ background: what;
+ background: is;
+ background: this;
+ border: what;
+ border: is;
+ border: this; }
+
+span {
+ color: 0;
+ color: 1;
+ color: 2;
+ color: 3;
+ color: 4;
+ color: 5;
+ color: 6;
+ color: 7;
+ color: 8;
+ color: 9;
+ color: 10; }
+
+pre {
+ color: 1;
+ color: 2;
+ color: 3;
+ color: 4;
+ height: 1;
+ height: 2;
+ height: 3;
+ height: 4;
+ height: 5;
+ cool: 10;
+ cool: 9;
+ cool: 8;
+ cool: 7;
+ cool: 6;
+ cool: 5;
+ cool: 4;
+ cool: 3; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/media.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/media.css
new file mode 100644
index 0000000..6627652
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/media.css
@@ -0,0 +1,103 @@
+@media {
+ div {
+ color: blue; } }
+
+@media what {
+ div {
+ color: blue; } }
+
+@media (cool) {
+ div {
+ color: blue; } }
+
+@media (cool: blue) {
+ div {
+ color: blue; } }
+
+@media hello and (world) and (butt: man) {
+ div {
+ color: blue; } }
+
+@media (max-width: 940px) {
+ color: red; }
+
+@media not hello and (world) {
+ color: blue;
+ pre {
+ color: blue; } }
+ @media butt and (world) {
+ color: red;
+ div {
+ color: red; } }
+
+div {
+ color: blue; }
+ @media screen and (-webkit-min-device-pixel-ratio: 1.5) {
+ div .sidebar {
+ width: 500px; } }
+
+div {
+ position: absolute; }
+ @media screen {
+ div {
+ top: 0;
+ bottom: 8em;
+ color: red; }
+ div p {
+ margin: 5px; }
+
+ div .success {
+ color: green; } }
+
+.button {
+ width: 300px;
+ height: 100px;
+ background: #eee; }
+ .button :hover {
+ background: #aaa; }
+ @media only screen and (max-width: 300px) {
+ .button {
+ width: 100px;
+ height: 100px; } }
+
+code {
+ position: absolute; }
+ @media screen {
+ code {
+ height: 10px; }
+ code pre {
+ height: 20px; } }
+
+@media screen and (color: blue) {
+ dt {
+ height: 10px; } }
+
+@media screen {
+ .screen {
+ width: 12px; } }
+ @media only screen {
+ .only-screen {
+ height: 11px; } }
+
+@media only screen {
+ .only-screen {
+ width: 14px; } }
+ @media only screen {
+ .only-screen {
+ height: 16px; } }
+
+@media print {
+ .only-print {
+ height: 12px; } }
+
+@media screen {
+ .only-print {
+ height: 12px; } }
+
+@media not screen {
+ .not-screen {
+ height: 15px; } }
+
+@media only screen and (color: blue) and (width: 13) {
+ .only-screen {
+ height: 15px; } }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/mixins.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/mixins.css
new file mode 100644
index 0000000..92bb1c0
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/mixins.css
@@ -0,0 +1,83 @@
+div {
+ color: blue;
+ color: red; }
+ div pre {
+ height: 200px; }
+
+span {
+ color: blue; }
+ span div {
+ height: 20px; }
+
+html {
+ height: 43px; }
+
+del {
+ height: 20px; }
+
+div {
+ color: white;
+ color: blue;
+ color: white; }
+
+div {
+ background-image: linear-gradient(left top, red, green); }
+
+div {
+ -moz-box-shadow: 10px 10px 5px #888;
+ -webkit-box-shadow: 10px 10px 5px #888;
+ box-shadow: 10px 10px 5px #888;
+ -moz-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4;
+ -webkit-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4;
+ box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; }
+
+div p {
+ color: red;
+ color: blue; }
+ div p .class {
+ color: red; }
+ div p .class div {
+ height: 20px; }
+ div p div {
+ height: 20px; }
+ div p .top {
+ top: 0; }
+ div p .top div {
+ color: red; }
+
+div.mixin-content-simple {
+ color: red; }
+
+div.mixin-content-with-arg {
+ background: blue;
+ color: red; }
+
+div.mixin-content-with-arg {
+ background: purple;
+ height: 20px; }
+
+div.mixin-content-simple {
+ height: 43px; }
+
+div.mixin-content-simple {
+ color: orange; }
+ div.mixin-content-simple div {
+ height: 20px; }
+
+div.mixin-content-with-arg {
+ background: purple;
+ height: 43px; }
+
+div.mixin-content-with-arg {
+ background: purple;
+ color: orange; }
+ div.mixin-content-with-arg div {
+ height: 20px; }
+
+#please-wait {
+ background: url(/images/logo.png);
+ position: absolute;
+ top: 1em;
+ right: 0;
+ bottom: 3em;
+ left: 4em; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/nesting.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/nesting.css
new file mode 100644
index 0000000..23be188
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/nesting.css
@@ -0,0 +1,22 @@
+div: blue;
+body {
+ color: red; }
+
+div {
+ color: red;
+ height: yes; }
+ div pre {
+ color: blue; }
+
+div {
+ font: 10px hello world;
+ font-size: 10px;
+ font-color: blue;
+ border-left: 1px solid blue;
+ border-right: 2px dashed green; }
+
+#nested-nesting {
+ bar: baz;
+ bang-bop: bar;
+ bang-bip: 1px;
+ bang-blat-baf: bort; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/null.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/null.css
new file mode 100644
index 0000000..b21aa46
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/null.css
@@ -0,0 +1,21 @@
+.div {
+ one: null;
+ one: world;
+ one: NULL world;
+ one: a, b;
+ two: a, b; }
+
+p:before {
+ content: "I ate pies!"; }
+
+.foo {
+ -webkit-border-radius: 10;
+ border-radius: 10; }
+
+.fu {
+ -webkit-border-radius: 20;
+ border-radius: 20; }
+
+.bar {
+ -webkit-border-top-left-radius: 30;
+ border-top-left-radius: 30; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/operators.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/operators.css
new file mode 100644
index 0000000..3cae96a
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/operators.css
@@ -0,0 +1,105 @@
+body {
+ color: 8;
+ color: 16;
+ height: 10px/10px;
+ color: 6px;
+ color: 5px;
+ bottom: 2px;
+ top: 1.5em;
+ left: -1cm;
+ top: 6.29921; }
+
+div {
+ color: false;
+ color: true;
+ color: true;
+ color: false;
+ color: what > 3; }
+
+#units {
+ test: 2.5748in;
+ test: 13mm;
+ test: 4em;
+ test: 11mm;
+ test: 1.1cm; }
+
+#modulo {
+ test: 1;
+ test: 1cm; }
+
+#colors {
+ color: #ff0203;
+ color: #fe0000;
+ color: rgba(3, 8, 15, 0.5);
+ color: rgba(5, 8, 10, 0.5);
+ color: rgba(2, 4, 6, 0.5);
+ color: rgba(1, 1, 2, 0.5);
+ color: rgba(3, 4, 5, 0.5);
+ color: rgba(0, 0, 1, 0.5);
+ color: #22f;
+ color: false;
+ color: true;
+ color: true;
+ color: false; }
+
+#preserve {
+ hello: what -going;
+ hello: what - going; }
+
+#strings {
+ hello: what -going;
+ hello: whatgoing;
+ hello: whatgoing;
+ hello: whatgoing;
+ hello: whatgoing;
+ hello: "whatgoing";
+ hello: goingwhat;
+ hello: "whatwhat"; }
+
+#negation {
+ a: -60;
+ b: 10 -100;
+ b: -90; }
+
+#bools-fail {
+ and: false and two;
+ and: one and two;
+ and: one and false;
+ or: false or two;
+ or: one or two;
+ or: one or false; }
+
+#bools {
+ and: false;
+ and: two;
+ and: false;
+ or: two;
+ or: one;
+ or: one; }
+
+#nots-fail {
+ not: false2;
+ not: not false;
+ not: not 0;
+ not: not 1;
+ not: not "";
+ not: not hello; }
+
+#nots {
+ not: false2;
+ not: true;
+ not: false;
+ not: false;
+ not: false;
+ not: false; }
+
+#string-test {
+ str: true;
+ str: false;
+ str: true;
+ str: true;
+ str: xhellohellofalse;
+ str: true; }
+
+#special {
+ cancel-unit: 1; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/placeholder_selector.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/placeholder_selector.css
new file mode 100644
index 0000000..938ffeb
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/placeholder_selector.css
@@ -0,0 +1,7 @@
+p a.notice span, p a.error span, #context a.notice span, #context a.error span {
+ color: blue;
+ font-weight: bold;
+ font-size: 2em; }
+
+p {
+ padding: 2em; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/scss_css.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/scss_css.css
new file mode 100644
index 0000000..21af8e6
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/scss_css.css
@@ -0,0 +1,741 @@
+@import "foo.css";
+@import 'foo.css';
+@import url("foo.css");
+@import url('foo.css');
+@import url(foo.css);
+@import "foo.css" screen;
+@import "foo.css" screen, print;
+/* Foo
+ * Bar */
+/* Baz
+ * Bang */
+@charset "UTF-8";
+[foo~=bar] {
+ a: b; }
+
+[foo^=bar] {
+ a: b; }
+
+[foo$=bar] {
+ a: b; }
+
+[foo*=bar] {
+ a: b; }
+
+[foo|=en] {
+ a: b; }
+
+foo {
+ a: 2;
+ b: 2.3em;
+ c: 50%;
+ d: "fraz bran";
+ e: flanny-blanny-blan;
+ f: url(http://sass-lang.com);
+ h: #abc; }
+
+selector {
+ property: value;
+ property2: value; }
+
+sel {
+ p: v; }
+
+.foo {
+ a: b; }
+
+.foo {
+ a: b; }
+
+.foo {
+ a: b; }
+
+.foo {
+ a: b; }
+
+@foo {
+ a: b;
+ rule {
+ a: b; } }
+
+@foo {
+ a: b; }
+
+@bar {
+ a: b; }
+
+@foo "bar"
+
+foo {
+ a: 12px calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
+
+foo {
+ bar: baz; }
+
+bar {
+ bar: baz; }
+
+baz {
+ bar: baz;
+ /*
+ * foo
+ */ }
+
+bar {
+ baz: bang; }
+
+E, F {
+ a: b; }
+
+E F, G H {
+ a: b; }
+
+E > F, G > H {
+ a: b;
+ /* This is a CSS comment. */ }
+
+.one {
+ color: green;
+ /* Another comment */
+ /* The following should not be used:
+.two {color: red;} */ }
+
+.three {
+ /* color: red; */
+ color: green;
+ /**
+.four {color: red;} */ }
+
+.five {
+ color: green;
+ /**/ }
+
+.six {
+ color: green;
+ /*********/ }
+
+.seven {
+ color: green;
+ /* a comment **/ }
+
+.eight {
+ color: green; }
+
+foo {
+ a: \foo bar;
+ b: foo\ bar;
+ c: \2022 \0020;
+ d: foo\\bar;
+ e: foo\"\'bar; }
+
+foo {
+ a: "\foo bar";
+ b: "foo\ bar";
+ c: "\2022 \0020";
+ d: "foo\\bar";
+ e: "foo\"'bar"; }
+
+foo {
+ _name: val;
+ *name: val;
+ :name: val;
+ .name: val;
+ #name: val;
+ name/**/: val;
+ name/*\**/: val;
+ name: val; }
+
+@foo "bar" ;
+
+foo {
+ a: -moz-element(#foo);
+ b: -webkit-element(#foo);
+ b: -foobar-element(#foo); }
+
+@foo ;
+
+foo {
+ bar: baz; }
+
+0% {
+ a: b; }
+
+60% {
+ a: b; }
+
+100% {
+ a: b; }
+
+12px {
+ a: b; }
+
+"foo" {
+ a: b; }
+
+foo {
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
+
+:foo("bar") {
+ a: b; }
+
+:foo(bar) {
+ a: b; }
+
+:foo(12px) {
+ a: b; }
+
+:foo(+) {
+ a: b; }
+
+:foo(-) {
+ a: b; }
+
+:foo(+"bar") {
+ a: b; }
+
+:foo(-++--baz-"bar"12px) {
+ a: b; }
+
+foo {
+ a: foo-bar(12);
+ b: -foo-bar-baz(13, 14 15); }
+
+@import "foo.css" screen, print and (foo: 0);
+
+@import "foo.css" screen, only print, screen and (foo: 0);
+
+foo {
+ a: foo !important;
+ b: foo bar !important;
+ b: foo, bar !important; }
+
+foo {
+ a: -moz-bar-baz;
+ b: foo -o-bar-baz; }
+
+foo {
+ /* b; c: */
+ a: d; }
+
+foo {
+ /*: b; c */
+ a : d;
+ /* Foo
+ * Bar */ }
+
+[foo] {
+ a: b; }
+
+[foo="bar"] {
+ a: b; }
+
+[foo~="bar"] {
+ a: b; }
+
+[foo^="bar"] {
+ a: b; }
+
+[foo$="bar"] {
+ a: b; }
+
+[foo*="bar"] {
+ a: b; }
+
+[foo|="en"] {
+ a: b; }
+
+:root {
+ a: b; }
+
+:nth-child(n) {
+ a: b; }
+
+:nth-last-child(n) {
+ a: b; }
+
+:nth-of-type(n) {
+ a: b; }
+
+:nth-last-of-type(n) {
+ a: b; }
+
+:first-child {
+ a: b; }
+
+:last-child {
+ a: b; }
+
+:first-of-type {
+ a: b; }
+
+:last-of-type {
+ a: b; }
+
+:only-child {
+ a: b; }
+
+:only-of-type {
+ a: b; }
+
+:empty {
+ a: b; }
+
+:link {
+ a: b; }
+
+:visited {
+ a: b; }
+
+:active {
+ a: b; }
+
+:hover {
+ a: b; }
+
+:focus {
+ a: b; }
+
+:target {
+ a: b; }
+
+:lang(fr) {
+ a: b; }
+
+:enabled {
+ a: b; }
+
+:disabled {
+ a: b; }
+
+:checked {
+ a: b; }
+
+::first-line {
+ a: b; }
+
+::first-letter {
+ a: b; }
+
+::before {
+ a: b; }
+
+::after {
+ a: b; }
+
+.warning {
+ a: b; }
+
+#myid {
+ a: b; }
+
+:not(s) {
+ a: b; }
+
+@media all {
+ rule1 {
+ prop: val; }
+
+ rule2 {
+ prop: val; } }
+
+@media screen, print {
+ rule1 {
+ prop: val; }
+
+ rule2 {
+ prop: val; } }
+
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ a: b; }
+
+@media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
+ a: b; }
+
+:-moz-any(h1, h2, h3) {
+ a: b; }
+
+:-moz-any(.foo) {
+ a: b; }
+
+:-moz-any(foo bar, .baz > .bang) {
+ a: b; }
+
+@-moz-document url(http://www.w3.org/),
+ url-prefix(http://www.w3.org/Style/),
+ domain(mozilla.org),
+ regexp("^https:.*") {
+ .foo {
+ a: b; } }
+
+foo {
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
+
+foo {
+ filter: alpha(opacity=20);
+ filter: alpha(opacity=20, enabled=true);
+ filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); }
+
+@foo bar {
+ a: b; }
+
+@bar baz {
+ c: d; }
+
+@namespace "http://www.w3.org/Profiles/xhtml1-strict";
+
+@namespace url(http://www.w3.org/Profiles/xhtml1-strict);
+
+@namespace html url("http://www.w3.org/Profiles/xhtml1-strict");
+
+[foo|bar=baz] {
+ a: b; }
+
+[*|bar=baz] {
+ a: b; }
+
+[foo|bar|=baz] {
+ a: b; }
+
+foo|E {
+ a: b; }
+
+*|E {
+ a: b; }
+
+foo|* {
+ a: b; }
+
+*|* {
+ a: b; }
+
+:not(foo|bar) {
+ a: b; }
+
+:not(*|bar) {
+ a: b; }
+
+:not(foo|*) {
+ a: b; }
+
+:not(*|*) {
+ a: b; }
+
+:not(#blah) {
+ a: b; }
+
+:not(.blah) {
+ a: b; }
+
+:not([foo]) {
+ a: b; }
+
+:not([foo^="bar"]) {
+ a: b; }
+
+:not([baz|foo~="bar"]) {
+ a: b; }
+
+:not(:hover) {
+ a: b; }
+
+:not(:nth-child(2n + 3)) {
+ a: b; }
+
+:not(:not(#foo)) {
+ a: b; }
+
+:not(a#foo.bar) {
+ a: b; }
+
+:not(#foo .bar > baz) {
+ a: b; }
+
+:not(h1, h2, h3) {
+ a: b; }
+
+foo {
+ a: "bang 1 bar bip"; }
+
+:nth-child(-n) {
+ a: b; }
+
+:nth-child(+n) {
+ a: b; }
+
+:nth-child(even) {
+ a: b; }
+
+:nth-child(odd) {
+ a: b; }
+
+:nth-child(50) {
+ a: b; }
+
+:nth-child(-50) {
+ a: b; }
+
+:nth-child(+50) {
+ a: b; }
+
+:nth-child(2n+3) {
+ a: b; }
+
+:nth-child(2n-3) {
+ a: b; }
+
+:nth-child(+2n-3) {
+ a: b; }
+
+:nth-child(-2n+3) {
+ a: b; }
+
+:nth-child(-2n+ 3) {
+ a: b; }
+
+:nth-child( 2n + 3) {
+ a: b; }
+
+foo {
+ a: foo bar baz;
+ b: foo, #abc, -12;
+ c: 1px/2px/-3px;
+ d: foo bar, baz/bang; }
+
+@page {
+ prop1: val;
+ prop2: val; }
+
+@page flap {
+ prop1: val;
+ prop2: val; }
+
+@page :first {
+ prop1: val;
+ prop2: val; }
+
+@page flap:first {
+ prop1: val;
+ prop2: val; }
+
+.foo {
+ a: b; }
+
+.foo {
+ a: b;
+ /* Foo */ }
+
+.foo {
+ a: b;
+ /* Foo
+ * Bar */ }
+
+.foo {
+ a: b; }
+
+.foo #bar:baz(/* bang )*/ bip) {
+ a: b; }
+
+> E {
+ a: b; }
+
++ E {
+ a: b; }
+
+~ E {
+ a: b; }
+
+> > E {
+ a: b; }
+
+>> E {
+ a: b; }
+
+E* {
+ a: b; }
+
+E*.foo {
+ a: b; }
+
+E*:hover {
+ a: b; }
+
+E, F {
+ a: b; }
+
+E F {
+ a: b; }
+
+E, F G, H {
+ a: b; }
+
+E > F {
+ a: b; }
+
+E ~ F {
+ a: b; }
+
+E + F {
+ a: b; }
+
+* {
+ a: b; }
+
+E {
+ a: b; }
+
+E[foo] {
+ a: b; }
+
+E[foo="bar"] {
+ a: b; }
+
+E[foo~="bar"] {
+ a: b; }
+
+E[foo^="bar"] {
+ a: b; }
+
+E[foo$="bar"] {
+ a: b; }
+
+E[foo*="bar"] {
+ a: b; }
+
+E[foo|="en"] {
+ a: b; }
+
+E:root {
+ a: b; }
+
+E:nth-child(n) {
+ a: b; }
+
+E:nth-last-child(n) {
+ a: b; }
+
+E:nth-of-type(n) {
+ a: b; }
+
+E:nth-last-of-type(n) {
+ a: b; }
+
+E:first-child {
+ a: b; }
+
+E:last-child {
+ a: b; }
+
+E:first-of-type {
+ a: b; }
+
+E:last-of-type {
+ a: b; }
+
+E:only-child {
+ a: b; }
+
+E:only-of-type {
+ a: b; }
+
+E:empty {
+ a: b; }
+
+E:link {
+ a: b; }
+
+E:visited {
+ a: b; }
+
+E:active {
+ a: b; }
+
+E:hover {
+ a: b; }
+
+E:focus {
+ a: b; }
+
+E:target {
+ a: b; }
+
+E:lang(fr) {
+ a: b; }
+
+E:enabled {
+ a: b; }
+
+E:disabled {
+ a: b; }
+
+E:checked {
+ a: b; }
+
+E::first-line {
+ a: b; }
+
+E::first-letter {
+ a: b; }
+
+E::before {
+ a: b; }
+
+E::after {
+ a: b; }
+
+E.warning {
+ a: b; }
+
+E#myid {
+ a: b; }
+
+E:not(s) {
+ a: b; }
+
+E F {
+ a: b; }
+
+E > F {
+ a: b; }
+
+E + F {
+ a: b; }
+
+E ~ F {
+ a: b; }
+
+@supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+ .foo {
+ a: b; } }
+
+@-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+ .foo {
+ a: b; } }
+
+foo {
+ foo: bar;
+ #baz: bang;
+ #bip: bop; }
+
+foo {
+ a: -2;
+ b: -2.3em;
+ c: -50%;
+ d: -foo(bar baz); }
+
+foo {
+ a: -0.5em;
+ b: 0.5em;
+ c: -foo(12px);
+ d: +foo(12px); }
+
+foo {
+ -moz-foo-bar: blat;
+ -o-flat-blang: wibble; }
+
+foo {
+ a: foo();
+ b: bar baz-bang() bip; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/selectors.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/selectors.css
new file mode 100644
index 0000000..f87383a
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/selectors.css
@@ -0,0 +1,335 @@
+* {
+ color: blue; }
+
+E {
+ color: blue; }
+
+E:not(:link) {
+ color: blue; }
+
+E:not(:link):not(:visited) {
+ color: blue; }
+
+E:not(:link, :visited) {
+ color: blue; }
+
+E:matches(:hover, :focus) {
+ color: blue; }
+
+E.warning {
+ color: blue; }
+
+E#id {
+ color: blue; }
+
+E[foo] {
+ color: blue; }
+
+E[foo="barbar"] {
+ color: blue; }
+
+E[foo="barbar" i] {
+ color: blue; }
+
+E[foo~="hello#$@%@$#^"] {
+ color: blue; }
+
+E[foo^="color: green;"] {
+ color: blue; }
+
+E[foo$="239023"] {
+ color: blue; }
+
+E[foo*="29302"] {
+ color: blue; }
+
+E[foo|="239032"] {
+ color: blue; }
+
+[foo] {
+ color: blue; }
+
+[foo] .helloWorld {
+ color: blue; }
+
+[foo].helloWorld {
+ color: blue; }
+
+[foo="barbar"] {
+ color: blue; }
+
+[foo~="hello#$@%@$#^"] {
+ color: blue; }
+
+[foo^="color: green;"] {
+ color: blue; }
+
+[foo$="239023"] {
+ color: blue; }
+
+[foo*="29302"] {
+ color: blue; }
+
+[foo|="239032"] {
+ color: blue; }
+
+E:dir(ltr) {
+ color: blue; }
+
+E:lang(en) {
+ color: blue; }
+
+E:lang(en, fr) {
+ color: blue; }
+
+E:any-link {
+ color: blue; }
+
+E:link {
+ color: blue; }
+
+E:visited {
+ color: blue; }
+
+E:local-link {
+ color: blue; }
+
+E:local-link(0) {
+ color: red; }
+
+E:local-link(1) {
+ color: white; }
+
+E:local-link(2) {
+ color: red; }
+
+E:target {
+ color: blue; }
+
+E:scope {
+ color: blue; }
+
+E:current {
+ color: blue; }
+
+E:current(:link) {
+ color: blue; }
+
+E:past {
+ color: blue; }
+
+E:future {
+ color: blue; }
+
+E:active {
+ color: blue; }
+
+E:hover {
+ color: blue; }
+
+E:focus {
+ color: blue; }
+
+E:enabled {
+ color: blue; }
+
+E:disabled {
+ color: blue; }
+
+E:indeterminate {
+ color: blue; }
+
+E:default {
+ color: blue; }
+
+E:in-range {
+ color: blue; }
+
+E:out-of-range {
+ color: blue; }
+
+E:required {
+ color: blue; }
+
+E:optional {
+ color: blue; }
+
+E:read-only {
+ color: blue; }
+
+E:read-write {
+ color: blue; }
+
+E:root {
+ color: blue; }
+
+E:empty {
+ color: blue; }
+
+E:first-child {
+ color: blue; }
+
+E:nth-child(odd) {
+ color: blue; }
+
+E:nth-child(2n+1) {
+ color: blue; }
+
+E:nth-child(5) {
+ color: blue; }
+
+E:last-child {
+ color: blue; }
+
+E:nth-last-child(-n+2) {
+ color: blue; }
+
+E:only-child {
+ color: blue; }
+
+E:first-of-type {
+ color: blue; }
+
+E:nth-of-type(2n) {
+ color: blue; }
+
+E:last-of-type {
+ color: blue; }
+
+E:nth-last-of-type(n) {
+ color: blue; }
+
+E:only-of-type {
+ color: blue; }
+
+E:nth-match(odd) {
+ color: blue; }
+
+E:nth-last-match(odd) {
+ color: blue; }
+
+E:column(n) {
+ color: blue; }
+
+E:nth-column(n) {
+ color: blue; }
+
+E:nth-last-column(n) {
+ color: blue; }
+
+E F {
+ color: blue; }
+
+E > F {
+ color: blue; }
+
+E + F {
+ color: blue; }
+
+E ~ F {
+ color: blue; }
+
+E /foo/ F {
+ color: blue; }
+
+E! > F {
+ color: blue; }
+
+[foo|att=val] {
+ color: blue; }
+
+[*|att] {
+ color: yellow; }
+
+[|att] {
+ color: green; }
+
+[att] {
+ color: green; }
+
+E::first-line {
+ color: blue; }
+
+E::first-letter {
+ color: blue; }
+
+E::before {
+ color: blue; }
+
+E::after {
+ color: blue; }
+
+E::choices {
+ color: blue; }
+
+E::value {
+ color: blue; }
+
+E::repeat-index {
+ color: blue; }
+
+E::repeat-item {
+ color: blue; }
+
+E:first {
+ color: blue; }
+
+E:first-line {
+ color: blue; }
+
+E:first-letter {
+ color: blue; }
+
+E:before {
+ color: blue; }
+
+E:after {
+ color: blue; }
+
+E:checked {
+ color: blue; }
+
+E:invalid {
+ color: blue; }
+
+E:valid {
+ color: blue; }
+
+E:left {
+ color: blue; }
+
+E:right {
+ color: blue; }
+
+E:any(ol) {
+ color: blue; }
+
+E::selection {
+ color: blue; }
+
+div {
+ font: something;
+ font-size: 30em; }
+ div font:something {
+ size: 30em; }
+
+.something.world {
+ color: blue; }
+ .something .mold {
+ height: 200px; }
+ .dog .something {
+ color: blue; }
+
+.dad .simple .wolf {
+ color: blue; }
+ .rad.simple.bad {
+ color: blue; }
+
+.something div .what.world {
+ color: blue; }
+
+div.foo div {
+ color: blue; }
+
+.nice-fonts .main .message div .title, .nice-fonts div .message div .title {
+ font-size: 24px; }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/values.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/values.css
new file mode 100644
index 0000000..7c0e2ff
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/values.css
@@ -0,0 +1,34 @@
+#values {
+ color: #eee;
+ color: #eee;
+ height: 20px;
+ width: 80%;
+ color: "hello world";
+ height: url("http://google.com");
+ dads: url(http://leafo.net);
+ padding: 10px 10px 10px 10px, 3px 3px 3px;
+ textblock: "This is a \
+multiline block \
+#not { color: #eee;}";
+ margin: 4, 3, 1;
+ content: "This is a \
+multiline string.";
+ border-radius: -1px -1px -1px black; }
+
+#subtraction {
+ lit: 10 -11;
+ lit: -1;
+ lit: -1;
+ lit: -1;
+ var: 10 -100;
+ var: -90;
+ var: -90;
+ var: -90; }
+
+#special {
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
+
+#unary {
+ b: 0.5em;
+ c: -foo(12px);
+ d: +foo(12px); }
diff --git a/public/system/storage/vendor/leafo/scssphp/tests/outputs/variables.css b/public/system/storage/vendor/leafo/scssphp/tests/outputs/variables.css
new file mode 100644
index 0000000..8676338
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/tests/outputs/variables.css
@@ -0,0 +1,24 @@
+cool: 100px;
+div {
+ height: red, two, three; }
+
+div {
+ num: 1000; }
+
+div {
+ num: 2000; }
+
+pre {
+ color: blue; }
+
+del {
+ color: red; }
+ del div pre {
+ color: red; }
+
+body {
+ font-family: Arial;
+ font-family: Helvetica Neue;
+ font-family: "Helvetica Neue";
+ font-family: Helvetica, Arial, sans-serif;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
diff --git a/public/system/storage/vendor/leafo/scssphp/todo b/public/system/storage/vendor/leafo/scssphp/todo
new file mode 100644
index 0000000..ab271c5
--- /dev/null
+++ b/public/system/storage/vendor/leafo/scssphp/todo
@@ -0,0 +1,47 @@
+
+* change all calls to reduce to not suppress division where appropriate
+* store count in elements so we can have position of compile time errors
+* failed parsing paths can add comments early
+
+* fix indentation for @content, see @content tests
+
+misc:
+
+# sequence merging:
+
+a b c d { color: red; }
+x y z w { @extend a; }
+
+ a b c d, x y z w b c d { color: red; }
+
+
+a b c d { color: red; }
+x y z w { @extend b; }
+
+ a b c d, a x y z w c d, x y z a w c d { color: red; }
+
+
+a b c d { color: red; }
+x y z w { @extend c; }
+
+ a b c d, a b x y z w d, x y z a b w d { color: red; }
+
+ x y z a b w d
+
+ before: a b
+ after: d
+ new: x y z w
+
+
+a b c d { color: red; }
+x y z w { @extend d; }
+
+ a b c d, a b c x y z w, x y z a b c w { color: red; }
+
+
+->> new[:-1] . before . new[-1] . after
+
+ new.len > 1
+ before not empty
+
+
diff --git a/public/system/storage/vendor/psr/log/.gitignore b/public/system/storage/vendor/psr/log/.gitignore
new file mode 100644
index 0000000..22d0d82
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/.gitignore
@@ -0,0 +1 @@
+vendor
diff --git a/public/system/storage/vendor/psr/log/LICENSE b/public/system/storage/vendor/psr/log/LICENSE
new file mode 100644
index 0000000..474c952
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 PHP Framework Interoperability Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/AbstractLogger.php b/public/system/storage/vendor/psr/log/Psr/Log/AbstractLogger.php
new file mode 100644
index 0000000..90e721a
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/AbstractLogger.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * This is a simple Logger implementation that other Loggers can inherit from.
+ *
+ * It simply delegates all log-level-specific methods to the `log` method to
+ * reduce boilerplate code that a simple Logger that does the same thing with
+ * messages regardless of the error level has to implement.
+ */
+abstract class AbstractLogger implements LoggerInterface
+{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function emergency($message, array $context = array())
+ {
+ $this->log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/public/system/storage/vendor/psr/log/Psr/Log/InvalidArgumentException.php
new file mode 100644
index 0000000..67f852d
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/InvalidArgumentException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Psr\Log;
+
+class InvalidArgumentException extends \InvalidArgumentException
+{
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/LogLevel.php b/public/system/storage/vendor/psr/log/Psr/Log/LogLevel.php
new file mode 100644
index 0000000..9cebcac
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/LogLevel.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Describes log levels.
+ */
+class LogLevel
+{
+ const EMERGENCY = 'emergency';
+ const ALERT = 'alert';
+ const CRITICAL = 'critical';
+ const ERROR = 'error';
+ const WARNING = 'warning';
+ const NOTICE = 'notice';
+ const INFO = 'info';
+ const DEBUG = 'debug';
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareInterface.php b/public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareInterface.php
new file mode 100644
index 0000000..4d64f47
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareInterface.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Describes a logger-aware instance.
+ */
+interface LoggerAwareInterface
+{
+ /**
+ * Sets a logger instance on the object.
+ *
+ * @param LoggerInterface $logger
+ *
+ * @return void
+ */
+ public function setLogger(LoggerInterface $logger);
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareTrait.php b/public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareTrait.php
new file mode 100644
index 0000000..639f79b
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/LoggerAwareTrait.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Basic Implementation of LoggerAwareInterface.
+ */
+trait LoggerAwareTrait
+{
+ /**
+ * The logger instance.
+ *
+ * @var LoggerInterface
+ */
+ protected $logger;
+
+ /**
+ * Sets a logger.
+ *
+ * @param LoggerInterface $logger
+ */
+ public function setLogger(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/LoggerInterface.php b/public/system/storage/vendor/psr/log/Psr/Log/LoggerInterface.php
new file mode 100644
index 0000000..5ea7243
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/LoggerInterface.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Describes a logger instance.
+ *
+ * The message MUST be a string or object implementing __toString().
+ *
+ * The message MAY contain placeholders in the form: {foo} where foo
+ * will be replaced by the context data in key "foo".
+ *
+ * The context array can contain arbitrary data. The only assumption that
+ * can be made by implementors is that if an Exception instance is given
+ * to produce a stack trace, it MUST be in a key named "exception".
+ *
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
+ * for the full interface specification.
+ */
+interface LoggerInterface
+{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function emergency($message, array $context = array());
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array());
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array());
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array());
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array());
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array());
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array());
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array());
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function log($level, $message, array $context = array());
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/LoggerTrait.php b/public/system/storage/vendor/psr/log/Psr/Log/LoggerTrait.php
new file mode 100644
index 0000000..867225d
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/LoggerTrait.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * This is a simple Logger trait that classes unable to extend AbstractLogger
+ * (because they extend another class, etc) can include.
+ *
+ * It simply delegates all log-level-specific methods to the `log` method to
+ * reduce boilerplate code that a simple Logger that does the same thing with
+ * messages regardless of the error level has to implement.
+ */
+trait LoggerTrait
+{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function emergency($message, array $context = array())
+ {
+ $this->log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ abstract public function log($level, $message, array $context = array());
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/NullLogger.php b/public/system/storage/vendor/psr/log/Psr/Log/NullLogger.php
new file mode 100644
index 0000000..d8cd682
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/NullLogger.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * This Logger can be used to avoid conditional log calls.
+ *
+ * Logging should always be optional, and if no logger is provided to your
+ * library creating a NullLogger instance to have something to throw logs at
+ * is a good way to avoid littering your code with `if ($this->logger) { }`
+ * blocks.
+ */
+class NullLogger extends AbstractLogger
+{
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function log($level, $message, array $context = array())
+ {
+ // noop
+ }
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/public/system/storage/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
new file mode 100644
index 0000000..4b861c3
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace Psr\Log\Test;
+
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * Provides a base test class for ensuring compliance with the LoggerInterface.
+ *
+ * Implementors can extend the class and implement abstract methods to run this
+ * as part of their test suite.
+ */
+abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @return LoggerInterface
+ */
+ abstract public function getLogger();
+
+ /**
+ * This must return the log messages in order.
+ *
+ * The simple formatting of the messages is: "<LOG LEVEL> <MESSAGE>".
+ *
+ * Example ->error('Foo') would yield "error Foo".
+ *
+ * @return string[]
+ */
+ abstract public function getLogs();
+
+ public function testImplements()
+ {
+ $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
+ }
+
+ /**
+ * @dataProvider provideLevelsAndMessages
+ */
+ public function testLogsAtAllLevels($level, $message)
+ {
+ $logger = $this->getLogger();
+ $logger->{$level}($message, array('user' => 'Bob'));
+ $logger->log($level, $message, array('user' => 'Bob'));
+
+ $expected = array(
+ $level.' message of level '.$level.' with context: Bob',
+ $level.' message of level '.$level.' with context: Bob',
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function provideLevelsAndMessages()
+ {
+ return array(
+ LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
+ LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
+ LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
+ LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
+ LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
+ LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
+ LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
+ LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
+ );
+ }
+
+ /**
+ * @expectedException \Psr\Log\InvalidArgumentException
+ */
+ public function testThrowsOnInvalidLevel()
+ {
+ $logger = $this->getLogger();
+ $logger->log('invalid level', 'Foo');
+ }
+
+ public function testContextReplacement()
+ {
+ $logger = $this->getLogger();
+ $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
+
+ $expected = array('info {Message {nothing} Bob Bar a}');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testObjectCastToString()
+ {
+ if (method_exists($this, 'createPartialMock')) {
+ $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
+ } else {
+ $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
+ }
+ $dummy->expects($this->once())
+ ->method('__toString')
+ ->will($this->returnValue('DUMMY'));
+
+ $this->getLogger()->warning($dummy);
+
+ $expected = array('warning DUMMY');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextCanContainAnything()
+ {
+ $closed = fopen('php://memory', 'r');
+ fclose($closed);
+
+ $context = array(
+ 'bool' => true,
+ 'null' => null,
+ 'string' => 'Foo',
+ 'int' => 0,
+ 'float' => 0.5,
+ 'nested' => array('with object' => new DummyTest),
+ 'object' => new \DateTime,
+ 'resource' => fopen('php://memory', 'r'),
+ 'closed' => $closed,
+ );
+
+ $this->getLogger()->warning('Crazy context data', $context);
+
+ $expected = array('warning Crazy context data');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextExceptionKeyCanBeExceptionOrOtherValues()
+ {
+ $logger = $this->getLogger();
+ $logger->warning('Random message', array('exception' => 'oops'));
+ $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
+
+ $expected = array(
+ 'warning Random message',
+ 'critical Uncaught Exception!'
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+}
+
+class DummyTest
+{
+ public function __toString()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/psr/log/Psr/Log/Test/TestLogger.php b/public/system/storage/vendor/psr/log/Psr/Log/Test/TestLogger.php
new file mode 100644
index 0000000..0cdffe4
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/Psr/Log/Test/TestLogger.php
@@ -0,0 +1,146 @@
+<?php
+
+namespace Psr\Log\Test;
+
+use Psr\Log\AbstractLogger;
+
+/**
+ * Used for testing purposes.
+ *
+ * It records all records and gives you access to them for verification.
+ *
+ * @method bool hasEmergency($record)
+ * @method bool hasAlert($record)
+ * @method bool hasCritical($record)
+ * @method bool hasError($record)
+ * @method bool hasWarning($record)
+ * @method bool hasNotice($record)
+ * @method bool hasInfo($record)
+ * @method bool hasDebug($record)
+ *
+ * @method bool hasEmergencyRecords()
+ * @method bool hasAlertRecords()
+ * @method bool hasCriticalRecords()
+ * @method bool hasErrorRecords()
+ * @method bool hasWarningRecords()
+ * @method bool hasNoticeRecords()
+ * @method bool hasInfoRecords()
+ * @method bool hasDebugRecords()
+ *
+ * @method bool hasEmergencyThatContains($message)
+ * @method bool hasAlertThatContains($message)
+ * @method bool hasCriticalThatContains($message)
+ * @method bool hasErrorThatContains($message)
+ * @method bool hasWarningThatContains($message)
+ * @method bool hasNoticeThatContains($message)
+ * @method bool hasInfoThatContains($message)
+ * @method bool hasDebugThatContains($message)
+ *
+ * @method bool hasEmergencyThatMatches($message)
+ * @method bool hasAlertThatMatches($message)
+ * @method bool hasCriticalThatMatches($message)
+ * @method bool hasErrorThatMatches($message)
+ * @method bool hasWarningThatMatches($message)
+ * @method bool hasNoticeThatMatches($message)
+ * @method bool hasInfoThatMatches($message)
+ * @method bool hasDebugThatMatches($message)
+ *
+ * @method bool hasEmergencyThatPasses($message)
+ * @method bool hasAlertThatPasses($message)
+ * @method bool hasCriticalThatPasses($message)
+ * @method bool hasErrorThatPasses($message)
+ * @method bool hasWarningThatPasses($message)
+ * @method bool hasNoticeThatPasses($message)
+ * @method bool hasInfoThatPasses($message)
+ * @method bool hasDebugThatPasses($message)
+ */
+class TestLogger extends AbstractLogger
+{
+ /**
+ * @var array
+ */
+ public $records = [];
+
+ public $recordsByLevel = [];
+
+ /**
+ * @inheritdoc
+ */
+ public function log($level, $message, array $context = [])
+ {
+ $record = [
+ 'level' => $level,
+ 'message' => $message,
+ 'context' => $context,
+ ];
+
+ $this->recordsByLevel[$record['level']][] = $record;
+ $this->records[] = $record;
+ }
+
+ public function hasRecords($level)
+ {
+ return isset($this->recordsByLevel[$level]);
+ }
+
+ public function hasRecord($record, $level)
+ {
+ if (is_string($record)) {
+ $record = ['message' => $record];
+ }
+ return $this->hasRecordThatPasses(function ($rec) use ($record) {
+ if ($rec['message'] !== $record['message']) {
+ return false;
+ }
+ if (isset($record['context']) && $rec['context'] !== $record['context']) {
+ return false;
+ }
+ return true;
+ }, $level);
+ }
+
+ public function hasRecordThatContains($message, $level)
+ {
+ return $this->hasRecordThatPasses(function ($rec) use ($message) {
+ return strpos($rec['message'], $message) !== false;
+ }, $level);
+ }
+
+ public function hasRecordThatMatches($regex, $level)
+ {
+ return $this->hasRecordThatPasses(function ($rec) use ($regex) {
+ return preg_match($regex, $rec['message']) > 0;
+ }, $level);
+ }
+
+ public function hasRecordThatPasses(callable $predicate, $level)
+ {
+ if (!isset($this->recordsByLevel[$level])) {
+ return false;
+ }
+ foreach ($this->recordsByLevel[$level] as $i => $rec) {
+ if (call_user_func($predicate, $rec, $i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function __call($method, $args)
+ {
+ if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
+ $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
+ $level = strtolower($matches[2]);
+ if (method_exists($this, $genericMethod)) {
+ $args[] = $level;
+ return call_user_func_array([$this, $genericMethod], $args);
+ }
+ }
+ throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
+ }
+
+ public function reset()
+ {
+ $this->records = [];
+ }
+}
diff --git a/public/system/storage/vendor/psr/log/README.md b/public/system/storage/vendor/psr/log/README.md
new file mode 100644
index 0000000..5571a25
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/README.md
@@ -0,0 +1,52 @@
+PSR Log
+=======
+
+This repository holds all interfaces/classes/traits related to
+[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).
+
+Note that this is not a logger of its own. It is merely an interface that
+describes a logger. See the specification for more details.
+
+Installation
+------------
+
+```bash
+composer require psr/log
+```
+
+Usage
+-----
+
+If you need a logger, you can use the interface like this:
+
+```php
+<?php
+
+use Psr\Log\LoggerInterface;
+
+class Foo
+{
+ private $logger;
+
+ public function __construct(LoggerInterface $logger = null)
+ {
+ $this->logger = $logger;
+ }
+
+ public function doSomething()
+ {
+ if ($this->logger) {
+ $this->logger->info('Doing work');
+ }
+
+ // do something useful
+ }
+}
+```
+
+You can then pick one of the implementations of the interface to get a logger.
+
+If you want to implement the interface, you can require this package and
+implement `Psr\Log\LoggerInterface` in your code. Please read the
+[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
+for details.
diff --git a/public/system/storage/vendor/psr/log/composer.json b/public/system/storage/vendor/psr/log/composer.json
new file mode 100644
index 0000000..87934d7
--- /dev/null
+++ b/public/system/storage/vendor/psr/log/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "psr/log",
+ "description": "Common interface for logging libraries",
+ "keywords": ["psr", "psr-3", "log"],
+ "homepage": "https://github.com/php-fig/log",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/.gitignore b/public/system/storage/vendor/react/promise/.gitignore
new file mode 100644
index 0000000..5241c60
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/.gitignore
@@ -0,0 +1,5 @@
+composer.lock
+composer.phar
+phpunit.xml
+build/
+vendor/
diff --git a/public/system/storage/vendor/react/promise/.travis.yml b/public/system/storage/vendor/react/promise/.travis.yml
new file mode 100644
index 0000000..bcbe642
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/.travis.yml
@@ -0,0 +1,28 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+ - nightly # ignore errors, see below
+ - hhvm # ignore errors, see below
+
+# lock distro so new future defaults will not break the build
+dist: trusty
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ - php: nightly
+
+install:
+ - composer install
+
+script:
+ - ./vendor/bin/phpunit -v --coverage-text --coverage-clover=./build/logs/clover.xml
+
+after_script:
+ - if [ -f ./build/logs/clover.xml ]; then travis_retry composer require satooshi/php-coveralls --no-interaction --update-with-dependencies; fi
+ - if [ -f ./build/logs/clover.xml ]; then php vendor/bin/coveralls -v; fi
diff --git a/public/system/storage/vendor/react/promise/CHANGELOG.md b/public/system/storage/vendor/react/promise/CHANGELOG.md
new file mode 100644
index 0000000..11f007d
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/CHANGELOG.md
@@ -0,0 +1,135 @@
+CHANGELOG for 2.x
+=================
+
+* 2.7.1 (2018-01-07)
+
+ * Fix: file_exists warning when resolving with long strings.
+ (#130 by @sbesselsen)
+ * Improve performance by prefixing all global functions calls with \ to skip the look up and resolve process and go straight to the global function.
+ (#133 by @WyriHaximus)
+
+* 2.7.0 (2018-06-13)
+
+ * Feature: Improve memory consumption for pending promises by using static internal callbacks without binding to self.
+ (#124 by @clue)
+
+* 2.6.0 (2018-06-11)
+
+ * Feature: Significantly improve memory consumption and performance by only passing resolver args
+ to resolver and canceller if callback requires them. Also use static callbacks without
+ binding to promise, clean up canceller function reference when they are no longer
+ needed and hide resolver and canceller references from call stack on PHP 7+.
+ (#113, #115, #116, #117, #118, #119 and #123 by @clue)
+
+ These changes combined mean that rejecting promises with an `Exception` should
+ no longer cause any internal circular references which could cause some unexpected
+ memory growth in previous versions. By explicitly avoiding and explicitly
+ cleaning up said references, we can avoid relying on PHP's circular garbage collector
+ to kick in which significantly improves performance when rejecting many promises.
+
+ * Mark legacy progress support / notification API as deprecated
+ (#112 by @clue)
+
+ * Recommend rejecting promises by throwing an exception
+ (#114 by @jsor)
+
+ * Improve documentation to properly instantiate LazyPromise
+ (#121 by @holtkamp)
+
+ * Follower cancellation propagation was originally planned for this release
+ but has been reverted for now and is planned for a future release.
+ (#99 by @jsor and #122 by @clue)
+
+* 2.5.1 (2017-03-25)
+
+ * Fix circular references when resolving with a promise which follows
+ itself (#94).
+
+* 2.5.0 (2016-12-22)
+
+ * Revert automatic cancellation of pending collection promises once the
+ output promise resolves. This was introduced in 42d86b7 (PR #36, released
+ in [v2.3.0](https://github.com/reactphp/promise/releases/tag/v2.3.0)) and
+ was both unintended and backward incompatible.
+
+ If you need automatic cancellation, you can use something like:
+
+ ```php
+ function allAndCancel(array $promises)
+ {
+ return \React\Promise\all($promises)
+ ->always(function() use ($promises) {
+ foreach ($promises as $promise) {
+ if ($promise instanceof \React\Promise\CancellablePromiseInterface) {
+ $promise->cancel();
+ }
+ }
+ });
+ }
+ ```
+ * `all()` and `map()` functions now preserve the order of the array (#77).
+ * Fix circular references when resolving a promise with itself (#71).
+
+* 2.4.1 (2016-05-03)
+
+ * Fix `some()` not cancelling pending promises when too much input promises
+ reject (16ff799).
+
+* 2.4.0 (2016-03-31)
+
+ * Support foreign thenables in `resolve()`.
+ Any object that provides a `then()` method is now assimilated to a trusted
+ promise that follows the state of this thenable (#52).
+ * Fix `some()` and `any()` for input arrays containing not enough items
+ (#34).
+
+* 2.3.0 (2016-03-24)
+
+ * Allow cancellation of promises returned by functions working on promise
+ collections (#36).
+ * Handle `\Throwable` in the same way as `\Exception` (#51 by @joshdifabio).
+
+* 2.2.2 (2016-02-26)
+
+ * Fix cancellation handlers called multiple times (#47 by @clue).
+
+* 2.2.1 (2015-07-03)
+
+ * Fix stack error when resolving a promise in its own fulfillment or
+ rejection handlers.
+
+* 2.2.0 (2014-12-30)
+
+ * Introduce new `ExtendedPromiseInterface` implemented by all promises.
+ * Add new `done()` method (part of the `ExtendedPromiseInterface`).
+ * Add new `otherwise()` method (part of the `ExtendedPromiseInterface`).
+ * Add new `always()` method (part of the `ExtendedPromiseInterface`).
+ * Add new `progress()` method (part of the `ExtendedPromiseInterface`).
+ * Rename `Deferred::progress` to `Deferred::notify` to avoid confusion with
+ `ExtendedPromiseInterface::progress` (a `Deferred::progress` alias is
+ still available for backward compatibility)
+ * `resolve()` now always returns a `ExtendedPromiseInterface`.
+
+* 2.1.0 (2014-10-15)
+
+ * Introduce new `CancellablePromiseInterface` implemented by all promises.
+ * Add new `cancel()` method (part of the `CancellablePromiseInterface`).
+
+* 2.0.0 (2013-12-10)
+
+ New major release. The goal is to streamline the API and to make it more
+ compliant with other promise libraries and especially with the new upcoming
+ [ES6 promises specification](https://github.com/domenic/promises-unwrapping/).
+
+ * Add standalone Promise class.
+ * Add new `race()` function.
+ * BC break: Bump minimum PHP version to PHP 5.4.
+ * BC break: Remove `ResolverInterface` and `PromiseInterface` from
+ `Deferred`.
+ * BC break: Change signature of `PromiseInterface`.
+ * BC break: Remove `When` and `Util` classes and move static methods to
+ functions.
+ * BC break: `FulfilledPromise` and `RejectedPromise` now throw an exception
+ when initialized with a promise instead of a value/reason.
+ * BC break: `Deferred::resolve()` and `Deferred::reject()` no longer return
+ a promise.
diff --git a/public/system/storage/vendor/react/promise/LICENSE b/public/system/storage/vendor/react/promise/LICENSE
new file mode 100644
index 0000000..5919d20
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012-2016 Jan Sorgalla
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/public/system/storage/vendor/react/promise/README.md b/public/system/storage/vendor/react/promise/README.md
new file mode 100644
index 0000000..3685566
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/README.md
@@ -0,0 +1,870 @@
+Promise
+=======
+
+A lightweight implementation of
+[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.
+
+[![Build Status](https://travis-ci.org/reactphp/promise.svg?branch=master)](http://travis-ci.org/reactphp/promise)
+[![Coverage Status](https://coveralls.io/repos/github/reactphp/promise/badge.svg?branch=master)](https://coveralls.io/github/reactphp/promise?branch=master)
+
+Table of Contents
+-----------------
+
+1. [Introduction](#introduction)
+2. [Concepts](#concepts)
+ * [Deferred](#deferred)
+ * [Promise](#promise-1)
+3. [API](#api)
+ * [Deferred](#deferred-1)
+ * [Deferred::promise()](#deferredpromise)
+ * [Deferred::resolve()](#deferredresolve)
+ * [Deferred::reject()](#deferredreject)
+ * [Deferred::notify()](#deferrednotify)
+ * [PromiseInterface](#promiseinterface)
+ * [PromiseInterface::then()](#promiseinterfacethen)
+ * [ExtendedPromiseInterface](#extendedpromiseinterface)
+ * [ExtendedPromiseInterface::done()](#extendedpromiseinterfacedone)
+ * [ExtendedPromiseInterface::otherwise()](#extendedpromiseinterfaceotherwise)
+ * [ExtendedPromiseInterface::always()](#extendedpromiseinterfacealways)
+ * [ExtendedPromiseInterface::progress()](#extendedpromiseinterfaceprogress)
+ * [CancellablePromiseInterface](#cancellablepromiseinterface)
+ * [CancellablePromiseInterface::cancel()](#cancellablepromiseinterfacecancel)
+ * [Promise](#promise-2)
+ * [FulfilledPromise](#fulfilledpromise)
+ * [RejectedPromise](#rejectedpromise)
+ * [LazyPromise](#lazypromise)
+ * [Functions](#functions)
+ * [resolve()](#resolve)
+ * [reject()](#reject)
+ * [all()](#all)
+ * [race()](#race)
+ * [any()](#any)
+ * [some()](#some)
+ * [map()](#map)
+ * [reduce()](#reduce)
+ * [PromisorInterface](#promisorinterface)
+4. [Examples](#examples)
+ * [How to use Deferred](#how-to-use-deferred)
+ * [How promise forwarding works](#how-promise-forwarding-works)
+ * [Resolution forwarding](#resolution-forwarding)
+ * [Rejection forwarding](#rejection-forwarding)
+ * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding)
+ * [Progress event forwarding](#progress-event-forwarding)
+ * [done() vs. then()](#done-vs-then)
+5. [Install](#install)
+6. [Credits](#credits)
+7. [License](#license)
+
+Introduction
+------------
+
+Promise is a library implementing
+[CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP.
+
+It also provides several other useful promise-related concepts, such as joining
+multiple promises and mapping and reducing collections of promises.
+
+If you've never heard about promises before,
+[read this first](https://gist.github.com/3889970).
+
+Concepts
+--------
+
+### Deferred
+
+A **Deferred** represents a computation or unit of work that may not have
+completed yet. Typically (but not always), that computation will be something
+that executes asynchronously and completes at some point in the future.
+
+### Promise
+
+While a deferred represents the computation itself, a **Promise** represents
+the result of that computation. Thus, each deferred has a promise that acts as
+a placeholder for its actual result.
+
+API
+---
+
+### Deferred
+
+A deferred represents an operation whose resolution is pending. It has separate
+promise and resolver parts.
+
+```php
+$deferred = new React\Promise\Deferred();
+
+$promise = $deferred->promise();
+
+$deferred->resolve(mixed $value = null);
+$deferred->reject(mixed $reason = null);
+$deferred->notify(mixed $update = null);
+```
+
+The `promise` method returns the promise of the deferred.
+
+The `resolve` and `reject` methods control the state of the deferred.
+
+The deprecated `notify` method is for progress notification.
+
+The constructor of the `Deferred` accepts an optional `$canceller` argument.
+See [Promise](#promise-2) for more information.
+
+#### Deferred::promise()
+
+```php
+$promise = $deferred->promise();
+```
+
+Returns the promise of the deferred, which you can hand out to others while
+keeping the authority to modify its state to yourself.
+
+#### Deferred::resolve()
+
+```php
+$deferred->resolve(mixed $value = null);
+```
+
+Resolves the promise returned by `promise()`. All consumers are notified by
+having `$onFulfilled` (which they registered via `$promise->then()`) called with
+`$value`.
+
+If `$value` itself is a promise, the promise will transition to the state of
+this promise once it is resolved.
+
+#### Deferred::reject()
+
+```php
+$deferred->reject(mixed $reason = null);
+```
+
+Rejects the promise returned by `promise()`, signalling that the deferred's
+computation failed.
+All consumers are notified by having `$onRejected` (which they registered via
+`$promise->then()`) called with `$reason`.
+
+If `$reason` itself is a promise, the promise will be rejected with the outcome
+of this promise regardless whether it fulfills or rejects.
+
+#### Deferred::notify()
+
+> Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore.
+
+```php
+$deferred->notify(mixed $update = null);
+```
+
+Triggers progress notifications, to indicate to consumers that the computation
+is making progress toward its result.
+
+All consumers are notified by having `$onProgress` (which they registered via
+`$promise->then()`) called with `$update`.
+
+### PromiseInterface
+
+The promise interface provides the common interface for all promise
+implementations.
+
+A promise represents an eventual outcome, which is either fulfillment (success)
+and an associated value, or rejection (failure) and an associated reason.
+
+Once in the fulfilled or rejected state, a promise becomes immutable.
+Neither its state nor its result (or error) can be modified.
+
+#### Implementations
+
+* [Promise](#promise-2)
+* [FulfilledPromise](#fulfilledpromise)
+* [RejectedPromise](#rejectedpromise)
+* [LazyPromise](#lazypromise)
+
+#### PromiseInterface::then()
+
+```php
+$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
+```
+
+Transforms a promise's value by applying a function to the promise's fulfillment
+or rejection value. Returns a new promise for the transformed result.
+
+The `then()` method registers new fulfilled, rejection and progress handlers
+with a promise (all parameters are optional):
+
+ * `$onFulfilled` will be invoked once the promise is fulfilled and passed
+ the result as the first argument.
+ * `$onRejected` will be invoked once the promise is rejected and passed the
+ reason as the first argument.
+ * `$onProgress` (deprecated) will be invoked whenever the producer of the promise
+ triggers progress notifications and passed a single argument (whatever it
+ wants) to indicate progress.
+
+It returns a new promise that will fulfill with the return value of either
+`$onFulfilled` or `$onRejected`, whichever is called, or will reject with
+the thrown exception if either throws.
+
+A promise makes the following guarantees about handlers registered in
+the same call to `then()`:
+
+ 1. Only one of `$onFulfilled` or `$onRejected` will be called,
+ never both.
+ 2. `$onFulfilled` and `$onRejected` will never be called more
+ than once.
+ 3. `$onProgress` (deprecated) may be called multiple times.
+
+#### See also
+
+* [resolve()](#resolve) - Creating a resolved promise
+* [reject()](#reject) - Creating a rejected promise
+* [ExtendedPromiseInterface::done()](#extendedpromiseinterfacedone)
+* [done() vs. then()](#done-vs-then)
+
+### ExtendedPromiseInterface
+
+The ExtendedPromiseInterface extends the PromiseInterface with useful shortcut
+and utility methods which are not part of the Promises/A specification.
+
+#### Implementations
+
+* [Promise](#promise-1)
+* [FulfilledPromise](#fulfilledpromise)
+* [RejectedPromise](#rejectedpromise)
+* [LazyPromise](#lazypromise)
+
+#### ExtendedPromiseInterface::done()
+
+```php
+$promise->done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
+```
+
+Consumes the promise's ultimate value if the promise fulfills, or handles the
+ultimate error.
+
+It will cause a fatal error if either `$onFulfilled` or `$onRejected` throw or
+return a rejected promise.
+
+Since the purpose of `done()` is consumption rather than transformation,
+`done()` always returns `null`.
+
+#### See also
+
+* [PromiseInterface::then()](#promiseinterfacethen)
+* [done() vs. then()](#done-vs-then)
+
+#### ExtendedPromiseInterface::otherwise()
+
+```php
+$promise->otherwise(callable $onRejected);
+```
+
+Registers a rejection handler for promise. It is a shortcut for:
+
+```php
+$promise->then(null, $onRejected);
+```
+
+Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
+only specific errors.
+
+```php
+$promise
+ ->otherwise(function (\RuntimeException $reason) {
+ // Only catch \RuntimeException instances
+ // All other types of errors will propagate automatically
+ })
+ ->otherwise(function ($reason) {
+ // Catch other errors
+ )};
+```
+
+#### ExtendedPromiseInterface::always()
+
+```php
+$newPromise = $promise->always(callable $onFulfilledOrRejected);
+```
+
+Allows you to execute "cleanup" type tasks in a promise chain.
+
+It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
+when the promise is either fulfilled or rejected.
+
+* If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
+ `$newPromise` will fulfill with the same value as `$promise`.
+* If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
+ rejected promise, `$newPromise` will reject with the thrown exception or
+ rejected promise's reason.
+* If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
+ `$newPromise` will reject with the same reason as `$promise`.
+* If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
+ rejected promise, `$newPromise` will reject with the thrown exception or
+ rejected promise's reason.
+
+`always()` behaves similarly to the synchronous finally statement. When combined
+with `otherwise()`, `always()` allows you to write code that is similar to the familiar
+synchronous catch/finally pair.
+
+Consider the following synchronous code:
+
+```php
+try {
+ return doSomething();
+} catch(\Exception $e) {
+ return handleError($e);
+} finally {
+ cleanup();
+}
+```
+
+Similar asynchronous code (with `doSomething()` that returns a promise) can be
+written:
+
+```php
+return doSomething()
+ ->otherwise('handleError')
+ ->always('cleanup');
+```
+
+#### ExtendedPromiseInterface::progress()
+
+> Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore.
+
+```php
+$promise->progress(callable $onProgress);
+```
+
+Registers a handler for progress updates from promise. It is a shortcut for:
+
+```php
+$promise->then(null, null, $onProgress);
+```
+
+### CancellablePromiseInterface
+
+A cancellable promise provides a mechanism for consumers to notify the creator
+of the promise that they are not longer interested in the result of an
+operation.
+
+#### CancellablePromiseInterface::cancel()
+
+``` php
+$promise->cancel();
+```
+
+The `cancel()` method notifies the creator of the promise that there is no
+further interest in the results of the operation.
+
+Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
+a promise has no effect.
+
+#### Implementations
+
+* [Promise](#promise-1)
+* [FulfilledPromise](#fulfilledpromise)
+* [RejectedPromise](#rejectedpromise)
+* [LazyPromise](#lazypromise)
+
+### Promise
+
+Creates a promise whose state is controlled by the functions passed to
+`$resolver`.
+
+```php
+$resolver = function (callable $resolve, callable $reject, callable $notify) {
+ // Do some work, possibly asynchronously, and then
+ // resolve or reject. You can notify of progress events (deprecated)
+ // along the way if you want/need.
+
+ $resolve($awesomeResult);
+ // or throw new Exception('Promise rejected');
+ // or $resolve($anotherPromise);
+ // or $reject($nastyError);
+ // or $notify($progressNotification);
+};
+
+$canceller = function () {
+ // Cancel/abort any running operations like network connections, streams etc.
+
+ // Reject promise by throwing an exception
+ throw new Exception('Promise cancelled');
+};
+
+$promise = new React\Promise\Promise($resolver, $canceller);
+```
+
+The promise constructor receives a resolver function and an optional canceller
+function which both will be called with 3 arguments:
+
+ * `$resolve($value)` - Primary function that seals the fate of the
+ returned promise. Accepts either a non-promise value, or another promise.
+ When called with a non-promise value, fulfills promise with that value.
+ When called with another promise, e.g. `$resolve($otherPromise)`, promise's
+ fate will be equivalent to that of `$otherPromise`.
+ * `$reject($reason)` - Function that rejects the promise. It is recommended to
+ just throw an exception instead of using `$reject()`.
+ * `$notify($update)` - Deprecated function that issues progress events for the promise.
+
+If the resolver or canceller throw an exception, the promise will be rejected
+with that thrown exception as the rejection reason.
+
+The resolver function will be called immediately, the canceller function only
+once all consumers called the `cancel()` method of the promise.
+
+### FulfilledPromise
+
+Creates a already fulfilled promise.
+
+```php
+$promise = React\Promise\FulfilledPromise($value);
+```
+
+Note, that `$value` **cannot** be a promise. It's recommended to use
+[resolve()](#resolve) for creating resolved promises.
+
+### RejectedPromise
+
+Creates a already rejected promise.
+
+```php
+$promise = React\Promise\RejectedPromise($reason);
+```
+
+Note, that `$reason` **cannot** be a promise. It's recommended to use
+[reject()](#reject) for creating rejected promises.
+
+### LazyPromise
+
+Creates a promise which will be lazily initialized by `$factory` once a consumer
+calls the `then()` method.
+
+```php
+$factory = function () {
+ $deferred = new React\Promise\Deferred();
+
+ // Do some heavy stuff here and resolve the deferred once completed
+
+ return $deferred->promise();
+};
+
+$promise = new React\Promise\LazyPromise($factory);
+
+// $factory will only be executed once we call then()
+$promise->then(function ($value) {
+});
+```
+
+### Functions
+
+Useful functions for creating, joining, mapping and reducing collections of
+promises.
+
+All functions working on promise collections (like `all()`, `race()`, `some()`
+etc.) support cancellation. This means, if you call `cancel()` on the returned
+promise, all promises in the collection are cancelled. If the collection itself
+is a promise which resolves to an array, this promise is also cancelled.
+
+#### resolve()
+
+```php
+$promise = React\Promise\resolve(mixed $promiseOrValue);
+```
+
+Creates a promise for the supplied `$promiseOrValue`.
+
+If `$promiseOrValue` is a value, it will be the resolution value of the
+returned promise.
+
+If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
+a trusted promise that follows the state of the thenable is returned.
+
+If `$promiseOrValue` is a promise, it will be returned as is.
+
+Note: The promise returned is always a promise implementing
+[ExtendedPromiseInterface](#extendedpromiseinterface). If you pass in a custom
+promise which only implements [PromiseInterface](#promiseinterface), this
+promise will be assimilated to a extended promise following `$promiseOrValue`.
+
+#### reject()
+
+```php
+$promise = React\Promise\reject(mixed $promiseOrValue);
+```
+
+Creates a rejected promise for the supplied `$promiseOrValue`.
+
+If `$promiseOrValue` is a value, it will be the rejection value of the
+returned promise.
+
+If `$promiseOrValue` is a promise, its completion value will be the rejected
+value of the returned promise.
+
+This can be useful in situations where you need to reject a promise without
+throwing an exception. For example, it allows you to propagate a rejection with
+the value of another promise.
+
+#### all()
+
+```php
+$promise = React\Promise\all(array|React\Promise\PromiseInterface $promisesOrValues);
+```
+
+Returns a promise that will resolve only once all the items in
+`$promisesOrValues` have resolved. The resolution value of the returned promise
+will be an array containing the resolution values of each of the items in
+`$promisesOrValues`.
+
+#### race()
+
+```php
+$promise = React\Promise\race(array|React\Promise\PromiseInterface $promisesOrValues);
+```
+
+Initiates a competitive race that allows one winner. Returns a promise which is
+resolved in the same way the first settled promise resolves.
+
+#### any()
+
+```php
+$promise = React\Promise\any(array|React\Promise\PromiseInterface $promisesOrValues);
+```
+
+Returns a promise that will resolve when any one of the items in
+`$promisesOrValues` resolves. The resolution value of the returned promise
+will be the resolution value of the triggering item.
+
+The returned promise will only reject if *all* items in `$promisesOrValues` are
+rejected. The rejection value will be an array of all rejection reasons.
+
+The returned promise will also reject with a `React\Promise\Exception\LengthException`
+if `$promisesOrValues` contains 0 items.
+
+#### some()
+
+```php
+$promise = React\Promise\some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany);
+```
+
+Returns a promise that will resolve when `$howMany` of the supplied items in
+`$promisesOrValues` resolve. The resolution value of the returned promise
+will be an array of length `$howMany` containing the resolution values of the
+triggering items.
+
+The returned promise will reject if it becomes impossible for `$howMany` items
+to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
+reject). The rejection value will be an array of
+`(count($promisesOrValues) - $howMany) + 1` rejection reasons.
+
+The returned promise will also reject with a `React\Promise\Exception\LengthException`
+if `$promisesOrValues` contains less items than `$howMany`.
+
+#### map()
+
+```php
+$promise = React\Promise\map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc);
+```
+
+Traditional map function, similar to `array_map()`, but allows input to contain
+promises and/or values, and `$mapFunc` may return either a value or a promise.
+
+The map function receives each item as argument, where item is a fully resolved
+value of a promise or value in `$promisesOrValues`.
+
+#### reduce()
+
+```php
+$promise = React\Promise\reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null);
+```
+
+Traditional reduce function, similar to `array_reduce()`, but input may contain
+promises and/or values, and `$reduceFunc` may return either a value or a
+promise, *and* `$initialValue` may be a promise or a value for the starting
+value.
+
+### PromisorInterface
+
+The `React\Promise\PromisorInterface` provides a common interface for objects
+that provide a promise. `React\Promise\Deferred` implements it, but since it
+is part of the public API anyone can implement it.
+
+Examples
+--------
+
+### How to use Deferred
+
+```php
+function getAwesomeResultPromise()
+{
+ $deferred = new React\Promise\Deferred();
+
+ // Execute a Node.js-style function using the callback pattern
+ computeAwesomeResultAsynchronously(function ($error, $result) use ($deferred) {
+ if ($error) {
+ $deferred->reject($error);
+ } else {
+ $deferred->resolve($result);
+ }
+ });
+
+ // Return the promise
+ return $deferred->promise();
+}
+
+getAwesomeResultPromise()
+ ->then(
+ function ($value) {
+ // Deferred resolved, do something with $value
+ },
+ function ($reason) {
+ // Deferred rejected, do something with $reason
+ },
+ function ($update) {
+ // Progress notification triggered, do something with $update
+ }
+ );
+```
+
+### How promise forwarding works
+
+A few simple examples to show how the mechanics of Promises/A forwarding works.
+These examples are contrived, of course, and in real usage, promise chains will
+typically be spread across several function calls, or even several levels of
+your application architecture.
+
+#### Resolution forwarding
+
+Resolved promises forward resolution values to the next promise.
+The first promise, `$deferred->promise()`, will resolve with the value passed
+to `$deferred->resolve()` below.
+
+Each call to `then()` returns a new promise that will resolve with the return
+value of the previous handler. This creates a promise "pipeline".
+
+```php
+$deferred = new React\Promise\Deferred();
+
+$deferred->promise()
+ ->then(function ($x) {
+ // $x will be the value passed to $deferred->resolve() below
+ // and returns a *new promise* for $x + 1
+ return $x + 1;
+ })
+ ->then(function ($x) {
+ // $x === 2
+ // This handler receives the return value of the
+ // previous handler.
+ return $x + 1;
+ })
+ ->then(function ($x) {
+ // $x === 3
+ // This handler receives the return value of the
+ // previous handler.
+ return $x + 1;
+ })
+ ->then(function ($x) {
+ // $x === 4
+ // This handler receives the return value of the
+ // previous handler.
+ echo 'Resolve ' . $x;
+ });
+
+$deferred->resolve(1); // Prints "Resolve 4"
+```
+
+#### Rejection forwarding
+
+Rejected promises behave similarly, and also work similarly to try/catch:
+When you catch an exception, you must rethrow for it to propagate.
+
+Similarly, when you handle a rejected promise, to propagate the rejection,
+"rethrow" it by either returning a rejected promise, or actually throwing
+(since promise translates thrown exceptions into rejections)
+
+```php
+$deferred = new React\Promise\Deferred();
+
+$deferred->promise()
+ ->then(function ($x) {
+ throw new \Exception($x + 1);
+ })
+ ->otherwise(function (\Exception $x) {
+ // Propagate the rejection
+ throw $x;
+ })
+ ->otherwise(function (\Exception $x) {
+ // Can also propagate by returning another rejection
+ return React\Promise\reject(
+ new \Exception($x->getMessage() + 1)
+ );
+ })
+ ->otherwise(function ($x) {
+ echo 'Reject ' . $x->getMessage(); // 3
+ });
+
+$deferred->resolve(1); // Prints "Reject 3"
+```
+
+#### Mixed resolution and rejection forwarding
+
+Just like try/catch, you can choose to propagate or not. Mixing resolutions and
+rejections will still forward handler results in a predictable way.
+
+```php
+$deferred = new React\Promise\Deferred();
+
+$deferred->promise()
+ ->then(function ($x) {
+ return $x + 1;
+ })
+ ->then(function ($x) {
+ throw new \Exception($x + 1);
+ })
+ ->otherwise(function (\Exception $x) {
+ // Handle the rejection, and don't propagate.
+ // This is like catch without a rethrow
+ return $x->getMessage() + 1;
+ })
+ ->then(function ($x) {
+ echo 'Mixed ' . $x; // 4
+ });
+
+$deferred->resolve(1); // Prints "Mixed 4"
+```
+
+#### Progress event forwarding
+
+> Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore.
+
+In the same way as resolution and rejection handlers, your progress handler
+**MUST** return a progress event to be propagated to the next link in the chain.
+If you return nothing, `null` will be propagated.
+
+Also in the same way as resolutions and rejections, if you don't register a
+progress handler, the update will be propagated through.
+
+If your progress handler throws an exception, the exception will be propagated
+to the next link in the chain. The best thing to do is to ensure your progress
+handlers do not throw exceptions.
+
+This gives you the opportunity to transform progress events at each step in the
+chain so that they are meaningful to the next step. It also allows you to choose
+not to transform them, and simply let them propagate untransformed, by not
+registering a progress handler.
+
+```php
+$deferred = new React\Promise\Deferred();
+
+$deferred->promise()
+ ->progress(function ($update) {
+ return $update + 1;
+ })
+ ->progress(function ($update) {
+ echo 'Progress ' . $update; // 2
+ });
+
+$deferred->notify(1); // Prints "Progress 2"
+```
+
+### done() vs. then()
+
+The golden rule is:
+
+ Either return your promise, or call done() on it.
+
+At a first glance, `then()` and `done()` seem very similar. However, there are
+important distinctions.
+
+The intent of `then()` is to transform a promise's value and to pass or return
+a new promise for the transformed value along to other parts of your code.
+
+The intent of `done()` is to consume a promise's value, transferring
+responsibility for the value to your code.
+
+In addition to transforming a value, `then()` allows you to recover from, or
+propagate intermediate errors. Any errors that are not handled will be caught
+by the promise machinery and used to reject the promise returned by `then()`.
+
+Calling `done()` transfers all responsibility for errors to your code. If an
+error (either a thrown exception or returned rejection) escapes the
+`$onFulfilled` or `$onRejected` callbacks you provide to done, it will be
+rethrown in an uncatchable way causing a fatal error.
+
+```php
+function getJsonResult()
+{
+ return queryApi()
+ ->then(
+ // Transform API results to an object
+ function ($jsonResultString) {
+ return json_decode($jsonResultString);
+ },
+ // Transform API errors to an exception
+ function ($jsonErrorString) {
+ $object = json_decode($jsonErrorString);
+ throw new ApiErrorException($object->errorMessage);
+ }
+ );
+}
+
+// Here we provide no rejection handler. If the promise returned has been
+// rejected, the ApiErrorException will be thrown
+getJsonResult()
+ ->done(
+ // Consume transformed object
+ function ($jsonResultObject) {
+ // Do something with $jsonResultObject
+ }
+ );
+
+// Here we provide a rejection handler which will either throw while debugging
+// or log the exception
+getJsonResult()
+ ->done(
+ function ($jsonResultObject) {
+ // Do something with $jsonResultObject
+ },
+ function (ApiErrorException $exception) {
+ if (isDebug()) {
+ throw $exception;
+ } else {
+ logException($exception);
+ }
+ }
+ );
+```
+
+Note that if a rejection value is not an instance of `\Exception`, it will be
+wrapped in an exception of the type `React\Promise\UnhandledRejectionException`.
+
+You can get the original rejection reason by calling `$exception->getReason()`.
+
+Install
+-------
+
+The recommended way to install this library is [through Composer](https://getcomposer.org).
+[New to Composer?](https://getcomposer.org/doc/00-intro.md)
+
+This project follows [SemVer](https://semver.org/).
+This will install the latest supported version:
+
+```bash
+$ composer require react/promise:^2.7
+```
+
+See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
+
+This project aims to run on any platform and thus does not require any PHP
+extensions and supports running on legacy PHP 5.4 through current PHP 7+ and HHVM.
+It's *highly recommended to use PHP 7+* for this project due to its vast
+performance improvements.
+
+Credits
+-------
+
+Promise is a port of [when.js](https://github.com/cujojs/when)
+by [Brian Cavalier](https://github.com/briancavalier).
+
+Also, large parts of the documentation have been ported from the when.js
+[Wiki](https://github.com/cujojs/when/wiki) and the
+[API docs](https://github.com/cujojs/when/blob/master/docs/api.md).
+
+License
+-------
+
+Released under the [MIT](LICENSE) license.
diff --git a/public/system/storage/vendor/react/promise/composer.json b/public/system/storage/vendor/react/promise/composer.json
new file mode 100644
index 0000000..2fc4809
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "react/promise",
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "license": "MIT",
+ "authors": [
+ {"name": "Jan Sorgalla", "email": "jsorgalla@gmail.com"}
+ ],
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ },
+ "autoload": {
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ },
+ "files": ["src/functions_include.php"]
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "React\\Promise\\": "tests/fixtures"
+ }
+ },
+ "keywords": [
+ "promise",
+ "promises"
+ ]
+}
diff --git a/public/system/storage/vendor/react/promise/phpunit.xml.dist b/public/system/storage/vendor/react/promise/phpunit.xml.dist
new file mode 100644
index 0000000..b9a689d
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/phpunit.xml.dist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false"
+ bootstrap="tests/bootstrap.php"
+>
+ <testsuites>
+ <testsuite name="Promise Test Suite">
+ <directory>./tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./src/</directory>
+ <exclude>
+ <file>./src/functions_include.php</file>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/react/promise/src/CancellablePromiseInterface.php b/public/system/storage/vendor/react/promise/src/CancellablePromiseInterface.php
new file mode 100644
index 0000000..896db2d
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/CancellablePromiseInterface.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace React\Promise;
+
+interface CancellablePromiseInterface extends PromiseInterface
+{
+ /**
+ * @return void
+ */
+ public function cancel();
+}
diff --git a/public/system/storage/vendor/react/promise/src/CancellationQueue.php b/public/system/storage/vendor/react/promise/src/CancellationQueue.php
new file mode 100644
index 0000000..4b26ef9
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/CancellationQueue.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace React\Promise;
+
+class CancellationQueue
+{
+ private $started = false;
+ private $queue = [];
+
+ public function __invoke()
+ {
+ if ($this->started) {
+ return;
+ }
+
+ $this->started = true;
+ $this->drain();
+ }
+
+ public function enqueue($cancellable)
+ {
+ if (!\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) {
+ return;
+ }
+
+ $length = \array_push($this->queue, $cancellable);
+
+ if ($this->started && 1 === $length) {
+ $this->drain();
+ }
+ }
+
+ private function drain()
+ {
+ for ($i = key($this->queue); isset($this->queue[$i]); $i++) {
+ $cancellable = $this->queue[$i];
+
+ $exception = null;
+
+ try {
+ $cancellable->cancel();
+ } catch (\Throwable $exception) {
+ } catch (\Exception $exception) {
+ }
+
+ unset($this->queue[$i]);
+
+ if ($exception) {
+ throw $exception;
+ }
+ }
+
+ $this->queue = [];
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/Deferred.php b/public/system/storage/vendor/react/promise/src/Deferred.php
new file mode 100644
index 0000000..3ca034b
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/Deferred.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace React\Promise;
+
+class Deferred implements PromisorInterface
+{
+ private $promise;
+ private $resolveCallback;
+ private $rejectCallback;
+ private $notifyCallback;
+ private $canceller;
+
+ public function __construct(callable $canceller = null)
+ {
+ $this->canceller = $canceller;
+ }
+
+ public function promise()
+ {
+ if (null === $this->promise) {
+ $this->promise = new Promise(function ($resolve, $reject, $notify) {
+ $this->resolveCallback = $resolve;
+ $this->rejectCallback = $reject;
+ $this->notifyCallback = $notify;
+ }, $this->canceller);
+ $this->canceller = null;
+ }
+
+ return $this->promise;
+ }
+
+ public function resolve($value = null)
+ {
+ $this->promise();
+
+ \call_user_func($this->resolveCallback, $value);
+ }
+
+ public function reject($reason = null)
+ {
+ $this->promise();
+
+ \call_user_func($this->rejectCallback, $reason);
+ }
+
+ /**
+ * @deprecated 2.6.0 Progress support is deprecated and should not be used anymore.
+ * @param mixed $update
+ */
+ public function notify($update = null)
+ {
+ $this->promise();
+
+ \call_user_func($this->notifyCallback, $update);
+ }
+
+ /**
+ * @deprecated 2.2.0
+ * @see Deferred::notify()
+ */
+ public function progress($update = null)
+ {
+ $this->notify($update);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/Exception/LengthException.php b/public/system/storage/vendor/react/promise/src/Exception/LengthException.php
new file mode 100644
index 0000000..775c48d
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/Exception/LengthException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace React\Promise\Exception;
+
+class LengthException extends \LengthException
+{
+}
diff --git a/public/system/storage/vendor/react/promise/src/ExtendedPromiseInterface.php b/public/system/storage/vendor/react/promise/src/ExtendedPromiseInterface.php
new file mode 100644
index 0000000..3654177
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/ExtendedPromiseInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace React\Promise;
+
+interface ExtendedPromiseInterface extends PromiseInterface
+{
+ /**
+ *
+ * The `$onProgress` argument is deprecated and should not be used anymore.
+ *
+ * @return void
+ */
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
+
+ /**
+ * @return ExtendedPromiseInterface
+ */
+ public function otherwise(callable $onRejected);
+
+ /**
+ * @return ExtendedPromiseInterface
+ */
+ public function always(callable $onFulfilledOrRejected);
+
+ /**
+ * @return ExtendedPromiseInterface
+ * @deprecated 2.6.0 Progress support is deprecated and should not be used anymore.
+ */
+ public function progress(callable $onProgress);
+}
diff --git a/public/system/storage/vendor/react/promise/src/FulfilledPromise.php b/public/system/storage/vendor/react/promise/src/FulfilledPromise.php
new file mode 100644
index 0000000..914bb5c
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/FulfilledPromise.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace React\Promise;
+
+class FulfilledPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
+{
+ private $value;
+
+ public function __construct($value = null)
+ {
+ if ($value instanceof PromiseInterface) {
+ throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.');
+ }
+
+ $this->value = $value;
+ }
+
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ if (null === $onFulfilled) {
+ return $this;
+ }
+
+ try {
+ return resolve($onFulfilled($this->value));
+ } catch (\Throwable $exception) {
+ return new RejectedPromise($exception);
+ } catch (\Exception $exception) {
+ return new RejectedPromise($exception);
+ }
+ }
+
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ if (null === $onFulfilled) {
+ return;
+ }
+
+ $result = $onFulfilled($this->value);
+
+ if ($result instanceof ExtendedPromiseInterface) {
+ $result->done();
+ }
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this;
+ }
+
+ public function always(callable $onFulfilledOrRejected)
+ {
+ return $this->then(function ($value) use ($onFulfilledOrRejected) {
+ return resolve($onFulfilledOrRejected())->then(function () use ($value) {
+ return $value;
+ });
+ });
+ }
+
+ public function progress(callable $onProgress)
+ {
+ return $this;
+ }
+
+ public function cancel()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/LazyPromise.php b/public/system/storage/vendor/react/promise/src/LazyPromise.php
new file mode 100644
index 0000000..7546524
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/LazyPromise.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace React\Promise;
+
+class LazyPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
+{
+ private $factory;
+ private $promise;
+
+ public function __construct(callable $factory)
+ {
+ $this->factory = $factory;
+ }
+
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
+ }
+
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ return $this->promise()->done($onFulfilled, $onRejected, $onProgress);
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this->promise()->otherwise($onRejected);
+ }
+
+ public function always(callable $onFulfilledOrRejected)
+ {
+ return $this->promise()->always($onFulfilledOrRejected);
+ }
+
+ public function progress(callable $onProgress)
+ {
+ return $this->promise()->progress($onProgress);
+ }
+
+ public function cancel()
+ {
+ return $this->promise()->cancel();
+ }
+
+ /**
+ * @internal
+ * @see Promise::settle()
+ */
+ public function promise()
+ {
+ if (null === $this->promise) {
+ try {
+ $this->promise = resolve(\call_user_func($this->factory));
+ } catch (\Throwable $exception) {
+ $this->promise = new RejectedPromise($exception);
+ } catch (\Exception $exception) {
+ $this->promise = new RejectedPromise($exception);
+ }
+ }
+
+ return $this->promise;
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/Promise.php b/public/system/storage/vendor/react/promise/src/Promise.php
new file mode 100644
index 0000000..33759e6
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/Promise.php
@@ -0,0 +1,256 @@
+<?php
+
+namespace React\Promise;
+
+class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface
+{
+ private $canceller;
+ private $result;
+
+ private $handlers = [];
+ private $progressHandlers = [];
+
+ private $requiredCancelRequests = 0;
+ private $cancelRequests = 0;
+
+ public function __construct(callable $resolver, callable $canceller = null)
+ {
+ $this->canceller = $canceller;
+
+ // Explicitly overwrite arguments with null values before invoking
+ // resolver function. This ensure that these arguments do not show up
+ // in the stack trace in PHP 7+ only.
+ $cb = $resolver;
+ $resolver = $canceller = null;
+ $this->call($cb);
+ }
+
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ if (null !== $this->result) {
+ return $this->result->then($onFulfilled, $onRejected, $onProgress);
+ }
+
+ if (null === $this->canceller) {
+ return new static($this->resolver($onFulfilled, $onRejected, $onProgress));
+ }
+
+ // This promise has a canceller, so we create a new child promise which
+ // has a canceller that invokes the parent canceller if all other
+ // followers are also cancelled. We keep a reference to this promise
+ // instance for the static canceller function and clear this to avoid
+ // keeping a cyclic reference between parent and follower.
+ $parent = $this;
+ ++$parent->requiredCancelRequests;
+
+ return new static(
+ $this->resolver($onFulfilled, $onRejected, $onProgress),
+ static function () use (&$parent) {
+ if (++$parent->cancelRequests >= $parent->requiredCancelRequests) {
+ $parent->cancel();
+ }
+
+ $parent = null;
+ }
+ );
+ }
+
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ if (null !== $this->result) {
+ return $this->result->done($onFulfilled, $onRejected, $onProgress);
+ }
+
+ $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected) {
+ $promise
+ ->done($onFulfilled, $onRejected);
+ };
+
+ if ($onProgress) {
+ $this->progressHandlers[] = $onProgress;
+ }
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this->then(null, static function ($reason) use ($onRejected) {
+ if (!_checkTypehint($onRejected, $reason)) {
+ return new RejectedPromise($reason);
+ }
+
+ return $onRejected($reason);
+ });
+ }
+
+ public function always(callable $onFulfilledOrRejected)
+ {
+ return $this->then(static function ($value) use ($onFulfilledOrRejected) {
+ return resolve($onFulfilledOrRejected())->then(function () use ($value) {
+ return $value;
+ });
+ }, static function ($reason) use ($onFulfilledOrRejected) {
+ return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
+ return new RejectedPromise($reason);
+ });
+ });
+ }
+
+ public function progress(callable $onProgress)
+ {
+ return $this->then(null, null, $onProgress);
+ }
+
+ public function cancel()
+ {
+ if (null === $this->canceller || null !== $this->result) {
+ return;
+ }
+
+ $canceller = $this->canceller;
+ $this->canceller = null;
+
+ $this->call($canceller);
+ }
+
+ private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ return function ($resolve, $reject, $notify) use ($onFulfilled, $onRejected, $onProgress) {
+ if ($onProgress) {
+ $progressHandler = static function ($update) use ($notify, $onProgress) {
+ try {
+ $notify($onProgress($update));
+ } catch (\Throwable $e) {
+ $notify($e);
+ } catch (\Exception $e) {
+ $notify($e);
+ }
+ };
+ } else {
+ $progressHandler = $notify;
+ }
+
+ $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
+ $promise
+ ->then($onFulfilled, $onRejected)
+ ->done($resolve, $reject, $progressHandler);
+ };
+
+ $this->progressHandlers[] = $progressHandler;
+ };
+ }
+
+ private function reject($reason = null)
+ {
+ if (null !== $this->result) {
+ return;
+ }
+
+ $this->settle(reject($reason));
+ }
+
+ private function settle(ExtendedPromiseInterface $promise)
+ {
+ $promise = $this->unwrap($promise);
+
+ if ($promise === $this) {
+ $promise = new RejectedPromise(
+ new \LogicException('Cannot resolve a promise with itself.')
+ );
+ }
+
+ $handlers = $this->handlers;
+
+ $this->progressHandlers = $this->handlers = [];
+ $this->result = $promise;
+ $this->canceller = null;
+
+ foreach ($handlers as $handler) {
+ $handler($promise);
+ }
+ }
+
+ private function unwrap($promise)
+ {
+ $promise = $this->extract($promise);
+
+ while ($promise instanceof self && null !== $promise->result) {
+ $promise = $this->extract($promise->result);
+ }
+
+ return $promise;
+ }
+
+ private function extract($promise)
+ {
+ if ($promise instanceof LazyPromise) {
+ $promise = $promise->promise();
+ }
+
+ return $promise;
+ }
+
+ private function call(callable $cb)
+ {
+ // Explicitly overwrite argument with null value. This ensure that this
+ // argument does not show up in the stack trace in PHP 7+ only.
+ $callback = $cb;
+ $cb = null;
+
+ // Use reflection to inspect number of arguments expected by this callback.
+ // We did some careful benchmarking here: Using reflection to avoid unneeded
+ // function arguments is actually faster than blindly passing them.
+ // Also, this helps avoiding unnecessary function arguments in the call stack
+ // if the callback creates an Exception (creating garbage cycles).
+ if (\is_array($callback)) {
+ $ref = new \ReflectionMethod($callback[0], $callback[1]);
+ } elseif (\is_object($callback) && !$callback instanceof \Closure) {
+ $ref = new \ReflectionMethod($callback, '__invoke');
+ } else {
+ $ref = new \ReflectionFunction($callback);
+ }
+ $args = $ref->getNumberOfParameters();
+
+ try {
+ if ($args === 0) {
+ $callback();
+ } else {
+ // Keep references to this promise instance for the static resolve/reject functions.
+ // By using static callbacks that are not bound to this instance
+ // and passing the target promise instance by reference, we can
+ // still execute its resolving logic and still clear this
+ // reference when settling the promise. This helps avoiding
+ // garbage cycles if any callback creates an Exception.
+ // These assumptions are covered by the test suite, so if you ever feel like
+ // refactoring this, go ahead, any alternative suggestions are welcome!
+ $target =& $this;
+ $progressHandlers =& $this->progressHandlers;
+
+ $callback(
+ static function ($value = null) use (&$target) {
+ if ($target !== null) {
+ $target->settle(resolve($value));
+ $target = null;
+ }
+ },
+ static function ($reason = null) use (&$target) {
+ if ($target !== null) {
+ $target->reject($reason);
+ $target = null;
+ }
+ },
+ static function ($update = null) use (&$progressHandlers) {
+ foreach ($progressHandlers as $handler) {
+ $handler($update);
+ }
+ }
+ );
+ }
+ } catch (\Throwable $e) {
+ $target = null;
+ $this->reject($e);
+ } catch (\Exception $e) {
+ $target = null;
+ $this->reject($e);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/PromiseInterface.php b/public/system/storage/vendor/react/promise/src/PromiseInterface.php
new file mode 100644
index 0000000..fcd763d
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/PromiseInterface.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace React\Promise;
+
+interface PromiseInterface
+{
+ /**
+ *
+ * The `$onProgress` argument is deprecated and should not be used anymore.
+ *
+ * @return PromiseInterface
+ */
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
+}
diff --git a/public/system/storage/vendor/react/promise/src/PromisorInterface.php b/public/system/storage/vendor/react/promise/src/PromisorInterface.php
new file mode 100644
index 0000000..9341a4f
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/PromisorInterface.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace React\Promise;
+
+interface PromisorInterface
+{
+ /**
+ * @return PromiseInterface
+ */
+ public function promise();
+}
diff --git a/public/system/storage/vendor/react/promise/src/RejectedPromise.php b/public/system/storage/vendor/react/promise/src/RejectedPromise.php
new file mode 100644
index 0000000..479a746
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/RejectedPromise.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace React\Promise;
+
+class RejectedPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
+{
+ private $reason;
+
+ public function __construct($reason = null)
+ {
+ if ($reason instanceof PromiseInterface) {
+ throw new \InvalidArgumentException('You cannot create React\Promise\RejectedPromise with a promise. Use React\Promise\reject($promiseOrValue) instead.');
+ }
+
+ $this->reason = $reason;
+ }
+
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ if (null === $onRejected) {
+ return $this;
+ }
+
+ try {
+ return resolve($onRejected($this->reason));
+ } catch (\Throwable $exception) {
+ return new RejectedPromise($exception);
+ } catch (\Exception $exception) {
+ return new RejectedPromise($exception);
+ }
+ }
+
+ public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ if (null === $onRejected) {
+ throw UnhandledRejectionException::resolve($this->reason);
+ }
+
+ $result = $onRejected($this->reason);
+
+ if ($result instanceof self) {
+ throw UnhandledRejectionException::resolve($result->reason);
+ }
+
+ if ($result instanceof ExtendedPromiseInterface) {
+ $result->done();
+ }
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ if (!_checkTypehint($onRejected, $this->reason)) {
+ return $this;
+ }
+
+ return $this->then(null, $onRejected);
+ }
+
+ public function always(callable $onFulfilledOrRejected)
+ {
+ return $this->then(null, function ($reason) use ($onFulfilledOrRejected) {
+ return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
+ return new RejectedPromise($reason);
+ });
+ });
+ }
+
+ public function progress(callable $onProgress)
+ {
+ return $this;
+ }
+
+ public function cancel()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/UnhandledRejectionException.php b/public/system/storage/vendor/react/promise/src/UnhandledRejectionException.php
new file mode 100644
index 0000000..e7fe2f7
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/UnhandledRejectionException.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace React\Promise;
+
+class UnhandledRejectionException extends \RuntimeException
+{
+ private $reason;
+
+ public static function resolve($reason)
+ {
+ if ($reason instanceof \Exception || $reason instanceof \Throwable) {
+ return $reason;
+ }
+
+ return new static($reason);
+ }
+
+ public function __construct($reason)
+ {
+ $this->reason = $reason;
+
+ $message = \sprintf('Unhandled Rejection: %s', \json_encode($reason));
+
+ parent::__construct($message, 0);
+ }
+
+ public function getReason()
+ {
+ return $this->reason;
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/src/functions.php b/public/system/storage/vendor/react/promise/src/functions.php
new file mode 100644
index 0000000..c549e4e
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/functions.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace React\Promise;
+
+function resolve($promiseOrValue = null)
+{
+ if ($promiseOrValue instanceof ExtendedPromiseInterface) {
+ return $promiseOrValue;
+ }
+
+ // Check is_object() first to avoid method_exists() triggering
+ // class autoloaders if $promiseOrValue is a string.
+ if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) {
+ $canceller = null;
+
+ if (\method_exists($promiseOrValue, 'cancel')) {
+ $canceller = [$promiseOrValue, 'cancel'];
+ }
+
+ return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) {
+ $promiseOrValue->then($resolve, $reject, $notify);
+ }, $canceller);
+ }
+
+ return new FulfilledPromise($promiseOrValue);
+}
+
+function reject($promiseOrValue = null)
+{
+ if ($promiseOrValue instanceof PromiseInterface) {
+ return resolve($promiseOrValue)->then(function ($value) {
+ return new RejectedPromise($value);
+ });
+ }
+
+ return new RejectedPromise($promiseOrValue);
+}
+
+function all($promisesOrValues)
+{
+ return map($promisesOrValues, function ($val) {
+ return $val;
+ });
+}
+
+function race($promisesOrValues)
+{
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($promisesOrValues);
+
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $cancellationQueue) {
+ resolve($promisesOrValues)
+ ->done(function ($array) use ($cancellationQueue, $resolve, $reject, $notify) {
+ if (!is_array($array) || !$array) {
+ $resolve();
+ return;
+ }
+
+ foreach ($array as $promiseOrValue) {
+ $cancellationQueue->enqueue($promiseOrValue);
+
+ resolve($promiseOrValue)
+ ->done($resolve, $reject, $notify);
+ }
+ }, $reject, $notify);
+ }, $cancellationQueue);
+}
+
+function any($promisesOrValues)
+{
+ return some($promisesOrValues, 1)
+ ->then(function ($val) {
+ return \array_shift($val);
+ });
+}
+
+function some($promisesOrValues, $howMany)
+{
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($promisesOrValues);
+
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $howMany, $cancellationQueue) {
+ resolve($promisesOrValues)
+ ->done(function ($array) use ($howMany, $cancellationQueue, $resolve, $reject, $notify) {
+ if (!\is_array($array) || $howMany < 1) {
+ $resolve([]);
+ return;
+ }
+
+ $len = \count($array);
+
+ if ($len < $howMany) {
+ throw new Exception\LengthException(
+ \sprintf(
+ 'Input array must contain at least %d item%s but contains only %s item%s.',
+ $howMany,
+ 1 === $howMany ? '' : 's',
+ $len,
+ 1 === $len ? '' : 's'
+ )
+ );
+ }
+
+ $toResolve = $howMany;
+ $toReject = ($len - $toResolve) + 1;
+ $values = [];
+ $reasons = [];
+
+ foreach ($array as $i => $promiseOrValue) {
+ $fulfiller = function ($val) use ($i, &$values, &$toResolve, $toReject, $resolve) {
+ if ($toResolve < 1 || $toReject < 1) {
+ return;
+ }
+
+ $values[$i] = $val;
+
+ if (0 === --$toResolve) {
+ $resolve($values);
+ }
+ };
+
+ $rejecter = function ($reason) use ($i, &$reasons, &$toReject, $toResolve, $reject) {
+ if ($toResolve < 1 || $toReject < 1) {
+ return;
+ }
+
+ $reasons[$i] = $reason;
+
+ if (0 === --$toReject) {
+ $reject($reasons);
+ }
+ };
+
+ $cancellationQueue->enqueue($promiseOrValue);
+
+ resolve($promiseOrValue)
+ ->done($fulfiller, $rejecter, $notify);
+ }
+ }, $reject, $notify);
+ }, $cancellationQueue);
+}
+
+function map($promisesOrValues, callable $mapFunc)
+{
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($promisesOrValues);
+
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $mapFunc, $cancellationQueue) {
+ resolve($promisesOrValues)
+ ->done(function ($array) use ($mapFunc, $cancellationQueue, $resolve, $reject, $notify) {
+ if (!\is_array($array) || !$array) {
+ $resolve([]);
+ return;
+ }
+
+ $toResolve = \count($array);
+ $values = [];
+
+ foreach ($array as $i => $promiseOrValue) {
+ $cancellationQueue->enqueue($promiseOrValue);
+ $values[$i] = null;
+
+ resolve($promiseOrValue)
+ ->then($mapFunc)
+ ->done(
+ function ($mapped) use ($i, &$values, &$toResolve, $resolve) {
+ $values[$i] = $mapped;
+
+ if (0 === --$toResolve) {
+ $resolve($values);
+ }
+ },
+ $reject,
+ $notify
+ );
+ }
+ }, $reject, $notify);
+ }, $cancellationQueue);
+}
+
+function reduce($promisesOrValues, callable $reduceFunc, $initialValue = null)
+{
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($promisesOrValues);
+
+ return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $reduceFunc, $initialValue, $cancellationQueue) {
+ resolve($promisesOrValues)
+ ->done(function ($array) use ($reduceFunc, $initialValue, $cancellationQueue, $resolve, $reject, $notify) {
+ if (!\is_array($array)) {
+ $array = [];
+ }
+
+ $total = \count($array);
+ $i = 0;
+
+ // Wrap the supplied $reduceFunc with one that handles promises and then
+ // delegates to the supplied.
+ $wrappedReduceFunc = function ($current, $val) use ($reduceFunc, $cancellationQueue, $total, &$i) {
+ $cancellationQueue->enqueue($val);
+
+ return $current
+ ->then(function ($c) use ($reduceFunc, $total, &$i, $val) {
+ return resolve($val)
+ ->then(function ($value) use ($reduceFunc, $total, &$i, $c) {
+ return $reduceFunc($c, $value, $i++, $total);
+ });
+ });
+ };
+
+ $cancellationQueue->enqueue($initialValue);
+
+ \array_reduce($array, $wrappedReduceFunc, resolve($initialValue))
+ ->done($resolve, $reject, $notify);
+ }, $reject, $notify);
+ }, $cancellationQueue);
+}
+
+// Internal functions
+function _checkTypehint(callable $callback, $object)
+{
+ if (!\is_object($object)) {
+ return true;
+ }
+
+ if (\is_array($callback)) {
+ $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
+ } elseif (\is_object($callback) && !$callback instanceof \Closure) {
+ $callbackReflection = new \ReflectionMethod($callback, '__invoke');
+ } else {
+ $callbackReflection = new \ReflectionFunction($callback);
+ }
+
+ $parameters = $callbackReflection->getParameters();
+
+ if (!isset($parameters[0])) {
+ return true;
+ }
+
+ $expectedException = $parameters[0];
+
+ if (!$expectedException->getClass()) {
+ return true;
+ }
+
+ return $expectedException->getClass()->isInstance($object);
+}
diff --git a/public/system/storage/vendor/react/promise/src/functions_include.php b/public/system/storage/vendor/react/promise/src/functions_include.php
new file mode 100644
index 0000000..bd0c54f
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/src/functions_include.php
@@ -0,0 +1,5 @@
+<?php
+
+if (!\function_exists('React\Promise\resolve')) {
+ require __DIR__.'/functions.php';
+}
diff --git a/public/system/storage/vendor/react/promise/tests/CancellationQueueTest.php b/public/system/storage/vendor/react/promise/tests/CancellationQueueTest.php
new file mode 100644
index 0000000..32cedf4
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/CancellationQueueTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace React\Promise;
+
+class CancellationQueueTest extends TestCase
+{
+ /** @test */
+ public function acceptsSimpleCancellableThenable()
+ {
+ $p = new SimpleTestCancellableThenable();
+
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($p);
+
+ $cancellationQueue();
+
+ $this->assertTrue($p->cancelCalled);
+ }
+
+ /** @test */
+ public function ignoresSimpleCancellable()
+ {
+ $p = new SimpleTestCancellable();
+
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($p);
+
+ $cancellationQueue();
+
+ $this->assertFalse($p->cancelCalled);
+ }
+
+ /** @test */
+ public function callsCancelOnPromisesEnqueuedBeforeStart()
+ {
+ $d1 = $this->getCancellableDeferred();
+ $d2 = $this->getCancellableDeferred();
+
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($d1->promise());
+ $cancellationQueue->enqueue($d2->promise());
+
+ $cancellationQueue();
+ }
+
+ /** @test */
+ public function callsCancelOnPromisesEnqueuedAfterStart()
+ {
+ $d1 = $this->getCancellableDeferred();
+ $d2 = $this->getCancellableDeferred();
+
+ $cancellationQueue = new CancellationQueue();
+
+ $cancellationQueue();
+
+ $cancellationQueue->enqueue($d2->promise());
+ $cancellationQueue->enqueue($d1->promise());
+ }
+
+ /** @test */
+ public function doesNotCallCancelTwiceWhenStartedTwice()
+ {
+ $d = $this->getCancellableDeferred();
+
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($d->promise());
+
+ $cancellationQueue();
+ $cancellationQueue();
+ }
+
+ /** @test */
+ public function rethrowsExceptionsThrownFromCancel()
+ {
+ $this->setExpectedException('\Exception', 'test');
+
+ $mock = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock
+ ->expects($this->once())
+ ->method('cancel')
+ ->will($this->throwException(new \Exception('test')));
+
+ $cancellationQueue = new CancellationQueue();
+ $cancellationQueue->enqueue($mock);
+
+ $cancellationQueue();
+ }
+
+ private function getCancellableDeferred()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke');
+
+ return new Deferred($mock);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/DeferredTest.php b/public/system/storage/vendor/react/promise/tests/DeferredTest.php
new file mode 100644
index 0000000..8ee40b8
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/DeferredTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
+
+class DeferredTest extends TestCase
+{
+ use PromiseTest\FullTestTrait;
+
+ public function getPromiseTestAdapter(callable $canceller = null)
+ {
+ $d = new Deferred($canceller);
+
+ return new CallbackPromiseAdapter([
+ 'promise' => [$d, 'promise'],
+ 'resolve' => [$d, 'resolve'],
+ 'reject' => [$d, 'reject'],
+ 'notify' => [$d, 'progress'],
+ 'settle' => [$d, 'resolve'],
+ ]);
+ }
+
+ /** @test */
+ public function progressIsAnAliasForNotify()
+ {
+ $deferred = new Deferred();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ $deferred->promise()
+ ->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
+
+ $deferred->progress($sentinel);
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException()
+ {
+ gc_collect_cycles();
+ $deferred = new Deferred(function ($resolve, $reject) {
+ $reject(new \Exception('foo'));
+ });
+ $deferred->promise()->cancel();
+ unset($deferred);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException()
+ {
+ gc_collect_cycles();
+ $deferred = new Deferred(function ($resolve, $reject) {
+ $reject(new \Exception('foo'));
+ });
+ $deferred->promise()->then()->cancel();
+ unset($deferred);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndExplicitlyRejectWithException()
+ {
+ gc_collect_cycles();
+ $deferred = new Deferred(function () use (&$deferred) { });
+ $deferred->reject(new \Exception('foo'));
+ unset($deferred);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingDeferred()
+ {
+ gc_collect_cycles();
+ $deferred = new Deferred();
+ $deferred->promise();
+ unset($deferred);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingDeferredWithUnusedCanceller()
+ {
+ gc_collect_cycles();
+ $deferred = new Deferred(function () { });
+ $deferred->promise();
+ unset($deferred);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingDeferredWithNoopCanceller()
+ {
+ gc_collect_cycles();
+ $deferred = new Deferred(function () { });
+ $deferred->promise()->cancel();
+ unset($deferred);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FulfilledPromiseTest.php b/public/system/storage/vendor/react/promise/tests/FulfilledPromiseTest.php
new file mode 100644
index 0000000..f5a2da8
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FulfilledPromiseTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
+
+class FulfilledPromiseTest extends TestCase
+{
+ use PromiseTest\PromiseSettledTestTrait,
+ PromiseTest\PromiseFulfilledTestTrait;
+
+ public function getPromiseTestAdapter(callable $canceller = null)
+ {
+ $promise = null;
+
+ return new CallbackPromiseAdapter([
+ 'promise' => function () use (&$promise) {
+ if (!$promise) {
+ throw new \LogicException('FulfilledPromise must be resolved before obtaining the promise');
+ }
+
+ return $promise;
+ },
+ 'resolve' => function ($value = null) use (&$promise) {
+ if (!$promise) {
+ $promise = new FulfilledPromise($value);
+ }
+ },
+ 'reject' => function () {
+ throw new \LogicException('You cannot call reject() for React\Promise\FulfilledPromise');
+ },
+ 'notify' => function () {
+ // no-op
+ },
+ 'settle' => function ($value = null) use (&$promise) {
+ if (!$promise) {
+ $promise = new FulfilledPromise($value);
+ }
+ },
+ ]);
+ }
+
+ /** @test */
+ public function shouldThrowExceptionIfConstructedWithAPromise()
+ {
+ $this->setExpectedException('\InvalidArgumentException');
+
+ return new FulfilledPromise(new FulfilledPromise());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToFulfilledPromiseWithAlwaysFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new FulfilledPromise(1);
+ $promise->always(function () {
+ throw new \RuntimeException();
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToFulfilledPromiseWithThenFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new FulfilledPromise(1);
+ $promise = $promise->then(function () {
+ throw new \RuntimeException();
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionAllTest.php b/public/system/storage/vendor/react/promise/tests/FunctionAllTest.php
new file mode 100644
index 0000000..74c1d7c
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionAllTest.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionAllTest extends TestCase
+{
+ /** @test */
+ public function shouldResolveEmptyInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([]));
+
+ all([])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveValuesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2, 3]));
+
+ all([1, 2, 3])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolvePromisesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2, 3]));
+
+ all([resolve(1), resolve(2), resolve(3)])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveSparseArrayInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([null, 1, null, 1, 1]));
+
+ all([null, 1, null, 1, 1])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectIfAnyInputPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ all([resolve(1), reject(2), resolve(3)])
+ ->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldAcceptAPromiseForAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2, 3]));
+
+ all(resolve([1, 2, 3]))
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([]));
+
+ all(resolve(1))
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldPreserveTheOrderOfArrayWhenResolvingAsyncPromises()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2, 3]));
+
+ $deferred = new Deferred();
+
+ all([resolve(1), $deferred->promise(), resolve(3)])
+ ->then($mock);
+
+ $deferred->resolve(2);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionAnyTest.php b/public/system/storage/vendor/react/promise/tests/FunctionAnyTest.php
new file mode 100644
index 0000000..140b551
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionAnyTest.php
@@ -0,0 +1,204 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\Exception\LengthException;
+
+class FunctionAnyTest extends TestCase
+{
+ /** @test */
+ public function shouldRejectWithLengthExceptionWithEmptyInputArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with(
+ $this->callback(function($exception){
+ return $exception instanceof LengthException &&
+ 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage();
+ })
+ );
+
+ any([])
+ ->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldResolveToNullWithNonArrayInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ any(null)
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveWithAnInputValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ any([1, 2, 3])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveWithAPromisedInputValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ any([resolve(1), resolve(2), resolve(3)])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([0 => 1, 1 => 2, 2 => 3]));
+
+ any([reject(1), reject(2), reject(3)])
+ ->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldResolveWhenFirstInputPromiseResolves()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ any([resolve(1), reject(2), reject(3)])
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldAcceptAPromiseForAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ any(resolve([1, 2, 3]))
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveToNullArrayWhenInputPromiseDoesNotResolveToArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ any(resolve(1))
+ ->then($mock);
+ }
+
+ /** @test */
+ public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $d1 = new Deferred();
+ $d2 = new Deferred();
+
+ any(['abc' => $d1->promise(), 1 => $d2->promise()])
+ ->then($mock);
+
+ $d2->resolve(2);
+ $d1->resolve(1);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ any(reject())
+ ->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldCancelInputPromise()
+ {
+ $mock = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock
+ ->expects($this->once())
+ ->method('cancel');
+
+ any($mock)->cancel();
+ }
+
+ /** @test */
+ public function shouldCancelInputArrayPromises()
+ {
+ $mock1 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock1
+ ->expects($this->once())
+ ->method('cancel');
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->once())
+ ->method('cancel');
+
+ any([$mock1, $mock2])->cancel();
+ }
+
+ /** @test */
+ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->never())
+ ->method('__invoke');
+
+
+ $deferred = New Deferred($mock);
+ $deferred->resolve();
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->never())
+ ->method('cancel');
+
+ some([$deferred->promise(), $mock2], 1)->cancel();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionCheckTypehintTest.php b/public/system/storage/vendor/react/promise/tests/FunctionCheckTypehintTest.php
new file mode 100644
index 0000000..8449bc1
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionCheckTypehintTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionCheckTypehintTest extends TestCase
+{
+ /** @test */
+ public function shouldAcceptClosureCallbackWithTypehint()
+ {
+ $this->assertTrue(_checkTypehint(function (\InvalidArgumentException $e) {
+ }, new \InvalidArgumentException()));
+ $this->assertfalse(_checkTypehint(function (\InvalidArgumentException $e) {
+ }, new \Exception()));
+ }
+
+ /** @test */
+ public function shouldAcceptFunctionStringCallbackWithTypehint()
+ {
+ $this->assertTrue(_checkTypehint('React\Promise\testCallbackWithTypehint', new \InvalidArgumentException()));
+ $this->assertfalse(_checkTypehint('React\Promise\testCallbackWithTypehint', new \Exception()));
+ }
+
+ /** @test */
+ public function shouldAcceptInvokableObjectCallbackWithTypehint()
+ {
+ $this->assertTrue(_checkTypehint(new TestCallbackWithTypehintClass(), new \InvalidArgumentException()));
+ $this->assertfalse(_checkTypehint(new TestCallbackWithTypehintClass(), new \Exception()));
+ }
+
+ /** @test */
+ public function shouldAcceptObjectMethodCallbackWithTypehint()
+ {
+ $this->assertTrue(_checkTypehint([new TestCallbackWithTypehintClass(), 'testCallback'], new \InvalidArgumentException()));
+ $this->assertfalse(_checkTypehint([new TestCallbackWithTypehintClass(), 'testCallback'], new \Exception()));
+ }
+
+ /** @test */
+ public function shouldAcceptStaticClassCallbackWithTypehint()
+ {
+ $this->assertTrue(_checkTypehint(['React\Promise\TestCallbackWithTypehintClass', 'testCallbackStatic'], new \InvalidArgumentException()));
+ $this->assertfalse(_checkTypehint(['React\Promise\TestCallbackWithTypehintClass', 'testCallbackStatic'], new \Exception()));
+ }
+
+ /** @test */
+ public function shouldAcceptClosureCallbackWithoutTypehint()
+ {
+ $this->assertTrue(_checkTypehint(function (\InvalidArgumentException $e) {
+ }, new \InvalidArgumentException()));
+ }
+
+ /** @test */
+ public function shouldAcceptFunctionStringCallbackWithoutTypehint()
+ {
+ $this->assertTrue(_checkTypehint('React\Promise\testCallbackWithoutTypehint', new \InvalidArgumentException()));
+ }
+
+ /** @test */
+ public function shouldAcceptInvokableObjectCallbackWithoutTypehint()
+ {
+ $this->assertTrue(_checkTypehint(new TestCallbackWithoutTypehintClass(), new \InvalidArgumentException()));
+ }
+
+ /** @test */
+ public function shouldAcceptObjectMethodCallbackWithoutTypehint()
+ {
+ $this->assertTrue(_checkTypehint([new TestCallbackWithoutTypehintClass(), 'testCallback'], new \InvalidArgumentException()));
+ }
+
+ /** @test */
+ public function shouldAcceptStaticClassCallbackWithoutTypehint()
+ {
+ $this->assertTrue(_checkTypehint(['React\Promise\TestCallbackWithoutTypehintClass', 'testCallbackStatic'], new \InvalidArgumentException()));
+ }
+}
+
+function testCallbackWithTypehint(\InvalidArgumentException $e)
+{
+}
+
+function testCallbackWithoutTypehint()
+{
+}
+
+class TestCallbackWithTypehintClass
+{
+ public function __invoke(\InvalidArgumentException $e)
+ {
+
+ }
+
+ public function testCallback(\InvalidArgumentException $e)
+ {
+
+ }
+
+ public static function testCallbackStatic(\InvalidArgumentException $e)
+ {
+
+ }
+}
+
+class TestCallbackWithoutTypehintClass
+{
+ public function __invoke()
+ {
+
+ }
+
+ public function testCallback()
+ {
+
+ }
+
+ public static function testCallbackStatic()
+ {
+
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionMapTest.php b/public/system/storage/vendor/react/promise/tests/FunctionMapTest.php
new file mode 100644
index 0000000..1ea560a
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionMapTest.php
@@ -0,0 +1,198 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionMapTest extends TestCase
+{
+ protected function mapper()
+ {
+ return function ($val) {
+ return $val * 2;
+ };
+ }
+
+ protected function promiseMapper()
+ {
+ return function ($val) {
+ return resolve($val * 2);
+ };
+ }
+
+ /** @test */
+ public function shouldMapInputValuesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([2, 4, 6]));
+
+ map(
+ [1, 2, 3],
+ $this->mapper()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldMapInputPromisesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([2, 4, 6]));
+
+ map(
+ [resolve(1), resolve(2), resolve(3)],
+ $this->mapper()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldMapMixedInputArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([2, 4, 6]));
+
+ map(
+ [1, resolve(2), 3],
+ $this->mapper()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldMapInputWhenMapperReturnsAPromise()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([2, 4, 6]));
+
+ map(
+ [1, 2, 3],
+ $this->promiseMapper()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldAcceptAPromiseForAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([2, 4, 6]));
+
+ map(
+ resolve([1, resolve(2), 3]),
+ $this->mapper()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([]));
+
+ map(
+ resolve(1),
+ $this->mapper()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldPreserveTheOrderOfArrayWhenResolvingAsyncPromises()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([2, 4, 6]));
+
+ $deferred = new Deferred();
+
+ map(
+ [resolve(1), $deferred->promise(), resolve(3)],
+ $this->mapper()
+ )->then($mock);
+
+ $deferred->resolve(2);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputContainsRejection()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ map(
+ [resolve(1), reject(2), resolve(3)],
+ $this->mapper()
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ map(
+ reject(),
+ $this->mapper()
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldCancelInputPromise()
+ {
+ $mock = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock
+ ->expects($this->once())
+ ->method('cancel');
+
+ map(
+ $mock,
+ $this->mapper()
+ )->cancel();
+ }
+
+ /** @test */
+ public function shouldCancelInputArrayPromises()
+ {
+ $mock1 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock1
+ ->expects($this->once())
+ ->method('cancel');
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->once())
+ ->method('cancel');
+
+ map(
+ [$mock1, $mock2],
+ $this->mapper()
+ )->cancel();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionRaceTest.php b/public/system/storage/vendor/react/promise/tests/FunctionRaceTest.php
new file mode 100644
index 0000000..83770ec
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionRaceTest.php
@@ -0,0 +1,211 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionRaceTest extends TestCase
+{
+ /** @test */
+ public function shouldResolveEmptyInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ race(
+ []
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveValuesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ race(
+ [1, 2, 3]
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolvePromisesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $d1 = new Deferred();
+ $d2 = new Deferred();
+ $d3 = new Deferred();
+
+ race(
+ [$d1->promise(), $d2->promise(), $d3->promise()]
+ )->then($mock);
+
+ $d2->resolve(2);
+
+ $d1->resolve(1);
+ $d3->resolve(3);
+ }
+
+ /** @test */
+ public function shouldResolveSparseArrayInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ race(
+ [null, 1, null, 2, 3]
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectIfFirstSettledPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $d1 = new Deferred();
+ $d2 = new Deferred();
+ $d3 = new Deferred();
+
+ race(
+ [$d1->promise(), $d2->promise(), $d3->promise()]
+ )->then($this->expectCallableNever(), $mock);
+
+ $d2->reject(2);
+
+ $d1->resolve(1);
+ $d3->resolve(3);
+ }
+
+ /** @test */
+ public function shouldAcceptAPromiseForAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ race(
+ resolve([1, 2, 3])
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveToNullWhenInputPromiseDoesNotResolveToArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ race(
+ resolve(1)
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ race(
+ reject()
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldCancelInputPromise()
+ {
+ $mock = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock
+ ->expects($this->once())
+ ->method('cancel');
+
+ race($mock)->cancel();
+ }
+
+ /** @test */
+ public function shouldCancelInputArrayPromises()
+ {
+ $mock1 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock1
+ ->expects($this->once())
+ ->method('cancel');
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->once())
+ ->method('cancel');
+
+ race([$mock1, $mock2])->cancel();
+ }
+
+ /** @test */
+ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->never())
+ ->method('__invoke');
+
+ $deferred = New Deferred($mock);
+ $deferred->resolve();
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->never())
+ ->method('cancel');
+
+ race([$deferred->promise(), $mock2])->cancel();
+ }
+
+ /** @test */
+ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->never())
+ ->method('__invoke');
+
+ $deferred = New Deferred($mock);
+ $deferred->reject();
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->never())
+ ->method('cancel');
+
+ race([$deferred->promise(), $mock2])->cancel();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionReduceTest.php b/public/system/storage/vendor/react/promise/tests/FunctionReduceTest.php
new file mode 100644
index 0000000..8b43a87
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionReduceTest.php
@@ -0,0 +1,347 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionReduceTest extends TestCase
+{
+ protected function plus()
+ {
+ return function ($sum, $val) {
+ return $sum + $val;
+ };
+ }
+
+ protected function append()
+ {
+ return function ($sum, $val) {
+ return $sum . $val;
+ };
+ }
+
+ /** @test */
+ public function shouldReduceValuesWithoutInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(6));
+
+ reduce(
+ [1, 2, 3],
+ $this->plus()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReduceValuesWithInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(7));
+
+ reduce(
+ [1, 2, 3],
+ $this->plus(),
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReduceValuesWithInitialPromise()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(7));
+
+ reduce(
+ [1, 2, 3],
+ $this->plus(),
+ resolve(1)
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReducePromisedValuesWithoutInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(6));
+
+ reduce(
+ [resolve(1), resolve(2), resolve(3)],
+ $this->plus()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReducePromisedValuesWithInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(7));
+
+ reduce(
+ [resolve(1), resolve(2), resolve(3)],
+ $this->plus(),
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReducePromisedValuesWithInitialPromise()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(7));
+
+ reduce(
+ [resolve(1), resolve(2), resolve(3)],
+ $this->plus(),
+ resolve(1)
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReduceEmptyInputWithInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ reduce(
+ [],
+ $this->plus(),
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReduceEmptyInputWithInitialPromise()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ reduce(
+ [],
+ $this->plus(),
+ resolve(1)
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputContainsRejection()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ reduce(
+ [resolve(1), reject(2), resolve(3)],
+ $this->plus(),
+ resolve(1)
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldResolveWithNullWhenInputIsEmptyAndNoInitialValueOrPromiseProvided()
+ {
+ // Note: this is different from when.js's behavior!
+ // In when.reduce(), this rejects with a TypeError exception (following
+ // JavaScript's [].reduce behavior.
+ // We're following PHP's array_reduce behavior and resolve with NULL.
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ reduce(
+ [],
+ $this->plus()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldAllowSparseArrayInputWithoutInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(3));
+
+ reduce(
+ [null, null, 1, null, 1, 1],
+ $this->plus()
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldAllowSparseArrayInputWithInitialValue()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(4));
+
+ reduce(
+ [null, null, 1, null, 1, 1],
+ $this->plus(),
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldReduceInInputOrder()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo('123'));
+
+ reduce(
+ [1, 2, 3],
+ $this->append(),
+ ''
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldAcceptAPromiseForAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo('123'));
+
+ reduce(
+ resolve([1, 2, 3]),
+ $this->append(),
+ ''
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveToInitialValueWhenInputPromiseDoesNotResolveToAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ reduce(
+ resolve(1),
+ $this->plus(),
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldProvideCorrectBasisValue()
+ {
+ $insertIntoArray = function ($arr, $val, $i) {
+ $arr[$i] = $val;
+
+ return $arr;
+ };
+
+ $d1 = new Deferred();
+ $d2 = new Deferred();
+ $d3 = new Deferred();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2, 3]));
+
+ reduce(
+ [$d1->promise(), $d2->promise(), $d3->promise()],
+ $insertIntoArray,
+ []
+ )->then($mock);
+
+ $d3->resolve(3);
+ $d1->resolve(1);
+ $d2->resolve(2);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ reduce(
+ reject(),
+ $this->plus(),
+ 1
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldCancelInputPromise()
+ {
+ $mock = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock
+ ->expects($this->once())
+ ->method('cancel');
+
+ reduce(
+ $mock,
+ $this->plus(),
+ 1
+ )->cancel();
+ }
+
+ /** @test */
+ public function shouldCancelInputArrayPromises()
+ {
+ $mock1 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock1
+ ->expects($this->once())
+ ->method('cancel');
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->once())
+ ->method('cancel');
+
+ reduce(
+ [$mock1, $mock2],
+ $this->plus(),
+ 1
+ )->cancel();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionRejectTest.php b/public/system/storage/vendor/react/promise/tests/FunctionRejectTest.php
new file mode 100644
index 0000000..84b8ec6
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionRejectTest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionRejectTest extends TestCase
+{
+ /** @test */
+ public function shouldRejectAnImmediateValue()
+ {
+ $expected = 123;
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($expected));
+
+ reject($expected)
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+
+ /** @test */
+ public function shouldRejectAFulfilledPromise()
+ {
+ $expected = 123;
+
+ $resolved = new FulfilledPromise($expected);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($expected));
+
+ reject($resolved)
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+
+ /** @test */
+ public function shouldRejectARejectedPromise()
+ {
+ $expected = 123;
+
+ $resolved = new RejectedPromise($expected);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($expected));
+
+ reject($resolved)
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionResolveTest.php b/public/system/storage/vendor/react/promise/tests/FunctionResolveTest.php
new file mode 100644
index 0000000..53126bc
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionResolveTest.php
@@ -0,0 +1,171 @@
+<?php
+
+namespace React\Promise;
+
+class FunctionResolveTest extends TestCase
+{
+ /** @test */
+ public function shouldResolveAnImmediateValue()
+ {
+ $expected = 123;
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($expected));
+
+ resolve($expected)
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function shouldResolveAFulfilledPromise()
+ {
+ $expected = 123;
+
+ $resolved = new FulfilledPromise($expected);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($expected));
+
+ resolve($resolved)
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function shouldResolveAThenable()
+ {
+ $thenable = new SimpleFulfilledTestThenable();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo('foo'));
+
+ resolve($thenable)
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function shouldResolveACancellableThenable()
+ {
+ $thenable = new SimpleTestCancellableThenable();
+
+ $promise = resolve($thenable);
+ $promise->cancel();
+
+ $this->assertTrue($thenable->cancelCalled);
+ }
+
+ /** @test */
+ public function shouldRejectARejectedPromise()
+ {
+ $expected = 123;
+
+ $resolved = new RejectedPromise($expected);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($expected));
+
+ resolve($resolved)
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+
+ /** @test */
+ public function shouldSupportDeepNestingInPromiseChains()
+ {
+ $d = new Deferred();
+ $d->resolve(false);
+
+ $result = resolve(resolve($d->promise()->then(function ($val) {
+ $d = new Deferred();
+ $d->resolve($val);
+
+ $identity = function ($val) {
+ return $val;
+ };
+
+ return resolve($d->promise()->then($identity))->then(
+ function ($val) {
+ return !$val;
+ }
+ );
+ })));
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(true));
+
+ $result->then($mock);
+ }
+
+ /** @test */
+ public function shouldSupportVeryDeepNestedPromises()
+ {
+ $deferreds = [];
+
+ // @TODO Increase count once global-queue is merged
+ for ($i = 0; $i < 10; $i++) {
+ $deferreds[] = $d = new Deferred();
+ $p = $d->promise();
+
+ $last = $p;
+ for ($j = 0; $j < 10; $j++) {
+ $last = $last->then(function($result) {
+ return $result;
+ });
+ }
+ }
+
+ $p = null;
+ foreach ($deferreds as $d) {
+ if ($p) {
+ $d->resolve($p);
+ }
+
+ $p = $d->promise();
+ }
+
+ $deferreds[0]->resolve(true);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(true));
+
+ $deferreds[0]->promise()->then($mock);
+ }
+
+ /** @test */
+ public function returnsExtendePromiseForSimplePromise()
+ {
+ $promise = $this
+ ->getMockBuilder('React\Promise\PromiseInterface')
+ ->getMock();
+
+ $this->assertInstanceOf('React\Promise\ExtendedPromiseInterface', resolve($promise));
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/FunctionSomeTest.php b/public/system/storage/vendor/react/promise/tests/FunctionSomeTest.php
new file mode 100644
index 0000000..276b54b
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/FunctionSomeTest.php
@@ -0,0 +1,258 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\Exception\LengthException;
+
+class FunctionSomeTest extends TestCase
+{
+ /** @test */
+ public function shouldRejectWithLengthExceptionWithEmptyInputArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with(
+ $this->callback(function($exception){
+ return $exception instanceof LengthException &&
+ 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage();
+ })
+ );
+
+ some(
+ [],
+ 1
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldRejectWithLengthExceptionWithInputArrayContainingNotEnoughItems()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with(
+ $this->callback(function($exception){
+ return $exception instanceof LengthException &&
+ 'Input array must contain at least 4 items but contains only 3 items.' === $exception->getMessage();
+ })
+ );
+
+ some(
+ [1, 2, 3],
+ 4
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldResolveToEmptyArrayWithNonArrayInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([]));
+
+ some(
+ null,
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveValuesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2]));
+
+ some(
+ [1, 2, 3],
+ 2
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolvePromisesArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2]));
+
+ some(
+ [resolve(1), resolve(2), resolve(3)],
+ 2
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveSparseArrayInput()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([null, 1]));
+
+ some(
+ [null, 1, null, 2, 3],
+ 2
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectIfAnyInputPromiseRejectsBeforeDesiredNumberOfInputsAreResolved()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1 => 2, 2 => 3]));
+
+ some(
+ [resolve(1), reject(2), reject(3)],
+ 2
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldAcceptAPromiseForAnArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([1, 2]));
+
+ some(
+ resolve([1, 2, 3]),
+ 2
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveWithEmptyArrayIfHowManyIsLessThanOne()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([]));
+
+ some(
+ [1],
+ 0
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo([]));
+
+ some(
+ resolve(1),
+ 1
+ )->then($mock);
+ }
+
+ /** @test */
+ public function shouldRejectWhenInputPromiseRejects()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(null));
+
+ some(
+ reject(),
+ 1
+ )->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldCancelInputPromise()
+ {
+ $mock = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock
+ ->expects($this->once())
+ ->method('cancel');
+
+ some($mock, 1)->cancel();
+ }
+
+ /** @test */
+ public function shouldCancelInputArrayPromises()
+ {
+ $mock1 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock1
+ ->expects($this->once())
+ ->method('cancel');
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->once())
+ ->method('cancel');
+
+ some([$mock1, $mock2], 1)->cancel();
+ }
+
+ /** @test */
+ public function shouldNotCancelOtherPendingInputArrayPromisesIfEnoughPromisesFulfill()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->never())
+ ->method('__invoke');
+
+ $deferred = New Deferred($mock);
+ $deferred->resolve();
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->never())
+ ->method('cancel');
+
+ some([$deferred->promise(), $mock2], 1);
+ }
+
+ /** @test */
+ public function shouldNotCancelOtherPendingInputArrayPromisesIfEnoughPromisesReject()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->never())
+ ->method('__invoke');
+
+ $deferred = New Deferred($mock);
+ $deferred->reject();
+
+ $mock2 = $this
+ ->getMockBuilder('React\Promise\CancellablePromiseInterface')
+ ->getMock();
+ $mock2
+ ->expects($this->never())
+ ->method('cancel');
+
+ some([$deferred->promise(), $mock2], 2);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/LazyPromiseTest.php b/public/system/storage/vendor/react/promise/tests/LazyPromiseTest.php
new file mode 100644
index 0000000..b630881
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/LazyPromiseTest.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
+
+class LazyPromiseTest extends TestCase
+{
+ use PromiseTest\FullTestTrait;
+
+ public function getPromiseTestAdapter(callable $canceller = null)
+ {
+ $d = new Deferred($canceller);
+
+ $factory = function () use ($d) {
+ return $d->promise();
+ };
+
+ return new CallbackPromiseAdapter([
+ 'promise' => function () use ($factory) {
+ return new LazyPromise($factory);
+ },
+ 'resolve' => [$d, 'resolve'],
+ 'reject' => [$d, 'reject'],
+ 'notify' => [$d, 'progress'],
+ 'settle' => [$d, 'resolve'],
+ ]);
+ }
+
+ /** @test */
+ public function shouldNotCallFactoryIfThenIsNotInvoked()
+ {
+ $factory = $this->createCallableMock();
+ $factory
+ ->expects($this->never())
+ ->method('__invoke');
+
+ new LazyPromise($factory);
+ }
+
+ /** @test */
+ public function shouldCallFactoryIfThenIsInvoked()
+ {
+ $factory = $this->createCallableMock();
+ $factory
+ ->expects($this->once())
+ ->method('__invoke');
+
+ $p = new LazyPromise($factory);
+ $p->then();
+ }
+
+ /** @test */
+ public function shouldReturnPromiseFromFactory()
+ {
+ $factory = $this->createCallableMock();
+ $factory
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->returnValue(new FulfilledPromise(1)));
+
+ $onFulfilled = $this->createCallableMock();
+ $onFulfilled
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $p = new LazyPromise($factory);
+
+ $p->then($onFulfilled);
+ }
+
+ /** @test */
+ public function shouldReturnPromiseIfFactoryReturnsNull()
+ {
+ $factory = $this->createCallableMock();
+ $factory
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->returnValue(null));
+
+ $p = new LazyPromise($factory);
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $p->then());
+ }
+
+ /** @test */
+ public function shouldReturnRejectedPromiseIfFactoryThrowsException()
+ {
+ $exception = new \Exception();
+
+ $factory = $this->createCallableMock();
+ $factory
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->throwException($exception));
+
+ $onRejected = $this->createCallableMock();
+ $onRejected
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $p = new LazyPromise($factory);
+
+ $p->then($this->expectCallableNever(), $onRejected);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseAdapter/CallbackPromiseAdapter.php b/public/system/storage/vendor/react/promise/tests/PromiseAdapter/CallbackPromiseAdapter.php
new file mode 100644
index 0000000..bdedf46
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseAdapter/CallbackPromiseAdapter.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace React\Promise\PromiseAdapter;
+
+use React\Promise;
+
+class CallbackPromiseAdapter implements PromiseAdapterInterface
+{
+ private $callbacks;
+
+ public function __construct(array $callbacks)
+ {
+ $this->callbacks = $callbacks;
+ }
+
+ public function promise()
+ {
+ return call_user_func_array($this->callbacks['promise'], func_get_args());
+ }
+
+ public function resolve()
+ {
+ return call_user_func_array($this->callbacks['resolve'], func_get_args());
+ }
+
+ public function reject()
+ {
+ return call_user_func_array($this->callbacks['reject'], func_get_args());
+ }
+
+ public function notify()
+ {
+ return call_user_func_array($this->callbacks['notify'], func_get_args());
+ }
+
+ public function settle()
+ {
+ return call_user_func_array($this->callbacks['settle'], func_get_args());
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseAdapter/PromiseAdapterInterface.php b/public/system/storage/vendor/react/promise/tests/PromiseAdapter/PromiseAdapterInterface.php
new file mode 100644
index 0000000..9157cd4
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseAdapter/PromiseAdapterInterface.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace React\Promise\PromiseAdapter;
+
+use React\Promise;
+
+interface PromiseAdapterInterface
+{
+ public function promise();
+ public function resolve();
+ public function reject();
+ public function notify();
+ public function settle();
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest.php b/public/system/storage/vendor/react/promise/tests/PromiseTest.php
new file mode 100644
index 0000000..344b411
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest.php
@@ -0,0 +1,293 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
+
+class PromiseTest extends TestCase
+{
+ use PromiseTest\FullTestTrait;
+
+ public function getPromiseTestAdapter(callable $canceller = null)
+ {
+ $resolveCallback = $rejectCallback = $progressCallback = null;
+
+ $promise = new Promise(function ($resolve, $reject, $progress) use (&$resolveCallback, &$rejectCallback, &$progressCallback) {
+ $resolveCallback = $resolve;
+ $rejectCallback = $reject;
+ $progressCallback = $progress;
+ }, $canceller);
+
+ return new CallbackPromiseAdapter([
+ 'promise' => function () use ($promise) {
+ return $promise;
+ },
+ 'resolve' => $resolveCallback,
+ 'reject' => $rejectCallback,
+ 'notify' => $progressCallback,
+ 'settle' => $resolveCallback,
+ ]);
+ }
+
+ /** @test */
+ public function shouldRejectIfResolverThrowsException()
+ {
+ $exception = new \Exception('foo');
+
+ $promise = new Promise(function () use ($exception) {
+ throw $exception;
+ });
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $promise
+ ->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function ($resolve) {
+ $resolve(new \Exception('foo'));
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptionWithoutResolver()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () {
+ throw new \Exception('foo');
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function ($resolve, $reject) {
+ $reject(new \Exception('foo'));
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function ($resolve, $reject) { }, function ($resolve, $reject) {
+ $reject(new \Exception('foo'));
+ });
+ $promise->cancel();
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function ($resolve, $reject) { }, function ($resolve, $reject) {
+ $reject(new \Exception('foo'));
+ });
+ $promise->then()->then()->then()->cancel();
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function ($resolve, $reject) {
+ throw new \Exception('foo');
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /**
+ * Test that checks number of garbage cycles after throwing from a canceller
+ * that explicitly uses a reference to the promise. This is rather synthetic,
+ * actual use cases often have implicit (hidden) references which ought not
+ * to be stored in the stack trace.
+ *
+ * Reassigned arguments only show up in the stack trace in PHP 7, so we can't
+ * avoid this on legacy PHP. As an alternative, consider explicitly unsetting
+ * any references before throwing.
+ *
+ * @test
+ * @requires PHP 7
+ */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () {}, function () use (&$promise) {
+ throw new \Exception('foo');
+ });
+ $promise->cancel();
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /**
+ * @test
+ * @requires PHP 7
+ * @see self::shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException
+ */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfResolverWithReferenceThrowsException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () use (&$promise) {
+ throw new \Exception('foo');
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /**
+ * @test
+ * @requires PHP 7
+ * @see self::shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException
+ */
+ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndResolverThrowsException()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () {
+ throw new \Exception('foo');
+ }, function () use (&$promise) { });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldIgnoreNotifyAfterReject()
+ {
+ $promise = new Promise(function () { }, function ($resolve, $reject, $notify) {
+ $reject(new \Exception('foo'));
+ $notify(42);
+ });
+
+ $promise->then(null, null, $this->expectCallableNever());
+ $promise->cancel();
+ }
+
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () { });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () { });
+ $promise->then()->then()->then();
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithDoneFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () { });
+ $promise->done();
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () { });
+ $promise->otherwise(function () { });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () { });
+ $promise->always(function () { });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithProgressFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new Promise(function () { });
+ $promise->then(null, null, function () { });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldFulfillIfFullfilledWithSimplePromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo('foo'));
+
+ $adapter->promise()
+ ->then($mock);
+
+ $adapter->resolve(new SimpleFulfilledTestPromise());
+ }
+
+ /** @test */
+ public function shouldRejectIfRejectedWithSimplePromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo('foo'));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->resolve(new SimpleRejectedTestPromise());
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/CancelTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/CancelTestTrait.php
new file mode 100644
index 0000000..2baab02
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/CancelTestTrait.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+use React\Promise;
+
+trait CancelTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function cancelShouldCallCancellerWithResolverArguments()
+ {
+ $args = null;
+ $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject, $notify) use (&$args) {
+ $args = func_get_args();
+ });
+
+ $adapter->promise()->cancel();
+
+ $this->assertCount(3, $args);
+ $this->assertTrue(is_callable($args[0]));
+ $this->assertTrue(is_callable($args[1]));
+ $this->assertTrue(is_callable($args[2]));
+ }
+
+ /** @test */
+ public function cancelShouldCallCancellerWithoutArgumentsIfNotAccessed()
+ {
+ $args = null;
+ $adapter = $this->getPromiseTestAdapter(function () use (&$args) {
+ $args = func_num_args();
+ });
+
+ $adapter->promise()->cancel();
+
+ $this->assertSame(0, $args);
+ }
+
+ /** @test */
+ public function cancelShouldFulfillPromiseIfCancellerFulfills()
+ {
+ $adapter = $this->getPromiseTestAdapter(function ($resolve) {
+ $resolve(1);
+ });
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($mock, $this->expectCallableNever());
+
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldRejectPromiseIfCancellerRejects()
+ {
+ $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) {
+ $reject(1);
+ });
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows()
+ {
+ $e = new \Exception();
+
+ $adapter = $this->getPromiseTestAdapter(function () use ($e) {
+ throw $e;
+ });
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($e));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldProgressPromiseIfCancellerNotifies()
+ {
+ $adapter = $this->getPromiseTestAdapter(function ($resolve, $reject, $progress) {
+ $progress(1);
+ });
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
+
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->returnCallback(function ($resolve) {
+ $resolve();
+ }));
+
+ $adapter = $this->getPromiseTestAdapter($mock);
+
+ $adapter->promise()->cancel();
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldHaveNoEffectIfCancellerDoesNothing()
+ {
+ $adapter = $this->getPromiseTestAdapter(function () {});
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $this->expectCallableNever());
+
+ $adapter->promise()->cancel();
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldCallCancellerFromDeepNestedPromiseChain()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke');
+
+ $adapter = $this->getPromiseTestAdapter($mock);
+
+ $promise = $adapter->promise()
+ ->then(function () {
+ return new Promise\Promise(function () {});
+ })
+ ->then(function () {
+ $d = new Promise\Deferred();
+
+ return $d->promise();
+ })
+ ->then(function () {
+ return new Promise\Promise(function () {});
+ });
+
+ $promise->cancel();
+ }
+
+ /** @test */
+ public function cancelCalledOnChildrenSouldOnlyCancelWhenAllChildrenCancelled()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
+
+ $child1 = $adapter->promise()
+ ->then()
+ ->then();
+
+ $adapter->promise()
+ ->then();
+
+ $child1->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldTriggerCancellerWhenAllChildrenCancel()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce());
+
+ $child1 = $adapter->promise()
+ ->then()
+ ->then();
+
+ $child2 = $adapter->promise()
+ ->then();
+
+ $child1->cancel();
+ $child2->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldNotTriggerCancellerWhenCancellingOneChildrenMultipleTimes()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
+
+ $child1 = $adapter->promise()
+ ->then()
+ ->then();
+
+ $child2 = $adapter->promise()
+ ->then();
+
+ $child1->cancel();
+ $child1->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldTriggerCancellerOnlyOnceWhenCancellingMultipleTimes()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce());
+
+ $adapter->promise()->cancel();
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce());
+
+ $adapter->promise()
+ ->then()
+ ->then();
+
+ $adapter->promise()
+ ->then();
+
+ $adapter->promise()->cancel();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/FullTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/FullTestTrait.php
new file mode 100644
index 0000000..3ce45d6
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/FullTestTrait.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+trait FullTestTrait
+{
+ use PromisePendingTestTrait,
+ PromiseSettledTestTrait,
+ PromiseFulfilledTestTrait,
+ PromiseRejectedTestTrait,
+ ResolveTestTrait,
+ RejectTestTrait,
+ NotifyTestTrait,
+ CancelTestTrait;
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/NotifyTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/NotifyTestTrait.php
new file mode 100644
index 0000000..4501df6
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/NotifyTestTrait.php
@@ -0,0 +1,336 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+trait NotifyTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function notifyShouldProgress()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
+
+ $adapter->notify($sentinel);
+ }
+
+ /** @test */
+ public function notifyShouldPropagateProgressToDownstreamPromises()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->returnArgument(0));
+
+ $mock2 = $this->createCallableMock();
+ $mock2
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock2
+ );
+
+ $adapter->notify($sentinel);
+ }
+
+ /** @test */
+ public function notifyShouldPropagateTransformedProgressToDownstreamPromises()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->returnValue($sentinel));
+
+ $mock2 = $this->createCallableMock();
+ $mock2
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock2
+ );
+
+ $adapter->notify(1);
+ }
+
+ /** @test */
+ public function notifyShouldPropagateCaughtExceptionValueAsProgress()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->throwException($exception));
+
+ $mock2 = $this->createCallableMock();
+ $mock2
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock2
+ );
+
+ $adapter->notify(1);
+ }
+
+ /** @test */
+ public function notifyShouldForwardProgressEventsWhenIntermediaryCallbackTiedToAResolvedPromiseReturnsAPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+ $adapter2 = $this->getPromiseTestAdapter();
+
+ $promise2 = $adapter2->promise();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ // resolve BEFORE attaching progress handler
+ $adapter->resolve();
+
+ $adapter->promise()
+ ->then(function () use ($promise2) {
+ return $promise2;
+ })
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ $adapter2->notify($sentinel);
+ }
+
+ /** @test */
+ public function notifyShouldForwardProgressEventsWhenIntermediaryCallbackTiedToAnUnresolvedPromiseReturnsAPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+ $adapter2 = $this->getPromiseTestAdapter();
+
+ $promise2 = $adapter2->promise();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ $adapter->promise()
+ ->then(function () use ($promise2) {
+ return $promise2;
+ })
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ // resolve AFTER attaching progress handler
+ $adapter->resolve();
+ $adapter2->notify($sentinel);
+ }
+
+ /** @test */
+ public function notifyShouldForwardProgressWhenResolvedWithAnotherPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+ $adapter2 = $this->getPromiseTestAdapter();
+
+ $sentinel = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->returnValue($sentinel));
+
+ $mock2 = $this->createCallableMock();
+ $mock2
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($sentinel);
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $this->expectCallableNever(),
+ $mock2
+ );
+
+ $adapter->resolve($adapter2->promise());
+ $adapter2->notify($sentinel);
+ }
+
+ /** @test */
+ public function notifyShouldAllowResolveAfterProgress()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->at(0))
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+ $mock
+ ->expects($this->at(1))
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->promise()
+ ->then(
+ $mock,
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ $adapter->notify(1);
+ $adapter->resolve(2);
+ }
+
+ /** @test */
+ public function notifyShouldAllowRejectAfterProgress()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->at(0))
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+ $mock
+ ->expects($this->at(1))
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $mock,
+ $mock
+ );
+
+ $adapter->notify(1);
+ $adapter->reject(2);
+ }
+
+ /** @test */
+ public function notifyShouldReturnSilentlyOnProgressWhenAlreadyRejected()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->reject(1);
+
+ $this->assertNull($adapter->notify());
+ }
+
+ /** @test */
+ public function notifyShouldInvokeProgressHandler()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()->progress($mock);
+ $adapter->notify(1);
+ }
+
+ /** @test */
+ public function notifyShouldInvokeProgressHandlerFromDone()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $this->assertNull($adapter->promise()->done(null, null, $mock));
+ $adapter->notify(1);
+ }
+
+ /** @test */
+ public function notifyShouldThrowExceptionThrownProgressHandlerFromDone()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done(null, null, function () {
+ throw new \Exception('UnhandledRejectionException');
+ }));
+ $adapter->notify(1);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseFulfilledTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseFulfilledTestTrait.php
new file mode 100644
index 0000000..428230b
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseFulfilledTestTrait.php
@@ -0,0 +1,351 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+trait PromiseFulfilledTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function fulfilledPromiseShouldBeImmutable()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->resolve(1);
+ $adapter->resolve(2);
+
+ $adapter->promise()
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function fulfilledPromiseShouldInvokeNewlyAddedCallback()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->resolve(1);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($mock, $this->expectCallableNever());
+ }
+
+ /** @test */
+ public function thenShouldForwardResultWhenCallbackIsNull()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->then(
+ null,
+ $this->expectCallableNever()
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function thenShouldForwardCallbackResultToNextCallback()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->then(
+ function ($val) {
+ return $val + 1;
+ },
+ $this->expectCallableNever()
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function thenShouldForwardPromisedCallbackResultValueToNextCallback()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->then(
+ function ($val) {
+ return \React\Promise\resolve($val + 1);
+ },
+ $this->expectCallableNever()
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejection()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->then(
+ function ($val) {
+ return \React\Promise\reject($val + 1);
+ },
+ $this->expectCallableNever()
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+
+ /** @test */
+ public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackThrows()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->throwException($exception));
+
+ $mock2 = $this->createCallableMock();
+ $mock2
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $mock2
+ );
+ }
+
+ /** @test */
+ public function cancelShouldReturnNullForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->resolve();
+
+ $this->assertNull($adapter->promise()->cancel());
+ }
+
+ /** @test */
+ public function cancelShouldHaveNoEffectForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
+
+ $adapter->resolve();
+
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function doneShouldInvokeFulfillmentHandlerForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->resolve(1);
+ $this->assertNull($adapter->promise()->done($mock));
+ }
+
+ /** @test */
+ public function doneShouldThrowExceptionThrownFulfillmentHandlerForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $adapter->resolve(1);
+ $this->assertNull($adapter->promise()->done(function () {
+ throw new \Exception('UnhandledRejectionException');
+ }));
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenFulfillmentHandlerRejectsForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $adapter->resolve(1);
+ $this->assertNull($adapter->promise()->done(function () {
+ return \React\Promise\reject();
+ }));
+ }
+
+ /** @test */
+ public function otherwiseShouldNotInvokeRejectionHandlerForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->resolve(1);
+ $adapter->promise()->otherwise($this->expectCallableNever());
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressValueForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $value = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($value));
+
+ $adapter->resolve($value);
+ $adapter->promise()
+ ->always(function () {})
+ ->then($mock);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $value = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($value));
+
+ $adapter->resolve($value);
+ $adapter->promise()
+ ->always(function () {
+ return 1;
+ })
+ ->then($mock);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $value = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($value));
+
+ $adapter->resolve($value);
+ $adapter->promise()
+ ->always(function () {
+ return \React\Promise\resolve(1);
+ })
+ ->then($mock);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->always(function () use ($exception) {
+ throw $exception;
+ })
+ ->then(null, $mock);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerRejectsForFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->resolve(1);
+ $adapter->promise()
+ ->always(function () use ($exception) {
+ return \React\Promise\reject($exception);
+ })
+ ->then(null, $mock);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/PromisePendingTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromisePendingTestTrait.php
new file mode 100644
index 0000000..a4f48ee
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromisePendingTestTrait.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+trait PromisePendingTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function thenShouldReturnAPromiseForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then());
+ }
+
+ /** @test */
+ public function thenShouldReturnAllowNullForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then(null, null, null));
+ }
+
+ /** @test */
+ public function cancelShouldReturnNullForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertNull($adapter->promise()->cancel());
+ }
+
+ /** @test */
+ public function doneShouldReturnNullForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertNull($adapter->promise()->done());
+ }
+
+ /** @test */
+ public function doneShouldReturnAllowNullForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertNull($adapter->promise()->done(null, null, null));
+ }
+
+ /** @test */
+ public function otherwiseShouldNotInvokeRejectionHandlerForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $adapter->promise()->otherwise($this->expectCallableNever());
+ }
+
+ /** @test */
+ public function alwaysShouldReturnAPromiseForPendingPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->always(function () {}));
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseRejectedTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseRejectedTestTrait.php
new file mode 100644
index 0000000..98d1dcf
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseRejectedTestTrait.php
@@ -0,0 +1,512 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+use React\Promise\Deferred;
+use React\Promise\UnhandledRejectionException;
+
+trait PromiseRejectedTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function rejectedPromiseShouldBeImmutable()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->reject(1);
+ $adapter->reject(2);
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+
+ /** @test */
+ public function rejectedPromiseShouldInvokeNewlyAddedCallback()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->reject(1);
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+ }
+
+ /** @test */
+ public function shouldForwardUndefinedRejectionValue()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with(null);
+
+ $adapter->reject(1);
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ function () {
+ // Presence of rejection handler is enough to switch back
+ // to resolve mode, even though it returns undefined.
+ // The ONLY way to propagate a rejection is to re-throw or
+ // return a rejected promise;
+ }
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyPropagate()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->reject(1);
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ function ($val) {
+ return $val + 1;
+ }
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->reject(1);
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ function ($val) {
+ return \React\Promise\resolve($val + 1);
+ }
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+ }
+
+ /** @test */
+ public function shouldPropagateRejectionsWhenErrbackThrows()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->will($this->throwException($exception));
+
+ $mock2 = $this->createCallableMock();
+ $mock2
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->reject(1);
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $mock2
+ );
+ }
+
+ /** @test */
+ public function shouldPropagateRejectionsWhenErrbackReturnsARejection()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(2));
+
+ $adapter->reject(1);
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ function ($val) {
+ return \React\Promise\reject($val + 1);
+ }
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+ }
+
+ /** @test */
+ public function doneShouldInvokeRejectionHandlerForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->reject(1);
+ $this->assertNull($adapter->promise()->done(null, $mock));
+ }
+
+ /** @test */
+ public function doneShouldThrowExceptionThrownByRejectionHandlerForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $adapter->reject(1);
+ $this->assertNull($adapter->promise()->done(null, function () {
+ throw new \Exception('UnhandledRejectionException');
+ }));
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenRejectedWithNonExceptionForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $adapter->reject(1);
+ $this->assertNull($adapter->promise()->done());
+ }
+
+ /** @test */
+ public function unhandledRejectionExceptionThrownByDoneHoldsRejectionValue()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $expected = new \stdClass();
+
+ $adapter->reject($expected);
+
+ try {
+ $adapter->promise()->done();
+ } catch (UnhandledRejectionException $e) {
+ $this->assertSame($expected, $e->getReason());
+ return;
+ }
+
+ $this->fail();
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenRejectionHandlerRejectsForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $adapter->reject(1);
+ $this->assertNull($adapter->promise()->done(null, function () {
+ return \React\Promise\reject();
+ }));
+ }
+
+ /** @test */
+ public function doneShouldThrowRejectionExceptionWhenRejectionHandlerRejectsWithExceptionForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $adapter->reject(1);
+ $this->assertNull($adapter->promise()->done(null, function () {
+ return \React\Promise\reject(new \Exception('UnhandledRejectionException'));
+ }));
+ }
+
+ /** @test */
+ public function doneShouldThrowExceptionProvidedAsRejectionValueForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $adapter->reject(new \Exception('UnhandledRejectionException'));
+ $this->assertNull($adapter->promise()->done());
+ }
+
+ /** @test */
+ public function doneShouldThrowWithDeepNestingPromiseChainsForRejectedPromise()
+ {
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $exception = new \Exception('UnhandledRejectionException');
+
+ $d = new Deferred();
+ $d->resolve();
+
+ $result = \React\Promise\resolve(\React\Promise\resolve($d->promise()->then(function () use ($exception) {
+ $d = new Deferred();
+ $d->resolve();
+
+ return \React\Promise\resolve($d->promise()->then(function () {}))->then(
+ function () use ($exception) {
+ throw $exception;
+ }
+ );
+ })));
+
+ $result->done();
+ }
+
+ /** @test */
+ public function doneShouldRecoverWhenRejectionHandlerCatchesExceptionForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->reject(new \Exception('UnhandledRejectionException'));
+ $this->assertNull($adapter->promise()->done(null, function (\Exception $e) {
+
+ }));
+ }
+
+ /** @test */
+ public function otherwiseShouldInvokeRejectionHandlerForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->reject(1);
+ $adapter->promise()->otherwise($mock);
+ }
+
+ /** @test */
+ public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExceptionForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->reject($exception);
+ $adapter->promise()
+ ->otherwise(function ($reason) use ($mock) {
+ $mock($reason);
+ });
+ }
+
+ /** @test */
+ public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \InvalidArgumentException();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->reject($exception);
+ $adapter->promise()
+ ->otherwise(function (\InvalidArgumentException $reason) use ($mock) {
+ $mock($reason);
+ });
+ }
+
+ /** @test */
+ public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehintForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->expectCallableNever();
+
+ $adapter->reject($exception);
+ $adapter->promise()
+ ->otherwise(function (\InvalidArgumentException $reason) use ($mock) {
+ $mock($reason);
+ });
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressRejectionForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->reject($exception);
+ $adapter->promise()
+ ->always(function () {})
+ ->then(null, $mock);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->reject($exception);
+ $adapter->promise()
+ ->always(function () {
+ return 1;
+ })
+ ->then(null, $mock);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->reject($exception);
+ $adapter->promise()
+ ->always(function () {
+ return \React\Promise\resolve(1);
+ })
+ ->then(null, $mock);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception1 = new \Exception();
+ $exception2 = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception2));
+
+ $adapter->reject($exception1);
+ $adapter->promise()
+ ->always(function () use ($exception2) {
+ throw $exception2;
+ })
+ ->then(null, $mock);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerRejectsForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception1 = new \Exception();
+ $exception2 = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception2));
+
+ $adapter->reject($exception1);
+ $adapter->promise()
+ ->always(function () use ($exception2) {
+ return \React\Promise\reject($exception2);
+ })
+ ->then(null, $mock);
+ }
+
+ /** @test */
+ public function cancelShouldReturnNullForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->reject();
+
+ $this->assertNull($adapter->promise()->cancel());
+ }
+
+ /** @test */
+ public function cancelShouldHaveNoEffectForRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
+
+ $adapter->reject();
+
+ $adapter->promise()->cancel();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseSettledTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseSettledTestTrait.php
new file mode 100644
index 0000000..e363b6d
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/PromiseSettledTestTrait.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+trait PromiseSettledTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function thenShouldReturnAPromiseForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then());
+ }
+
+ /** @test */
+ public function thenShouldReturnAllowNullForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then(null, null, null));
+ }
+
+ /** @test */
+ public function cancelShouldReturnNullForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+
+ $this->assertNull($adapter->promise()->cancel());
+ }
+
+ /** @test */
+ public function cancelShouldHaveNoEffectForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
+
+ $adapter->settle();
+
+ $adapter->promise()->cancel();
+ }
+
+ /** @test */
+ public function doneShouldReturnNullForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $this->assertNull($adapter->promise()->done(null, function () {}));
+ }
+
+ /** @test */
+ public function doneShouldReturnAllowNullForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $this->assertNull($adapter->promise()->done(null, function () {}, null));
+ }
+
+ /** @test */
+ public function progressShouldNotInvokeProgressHandlerForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $adapter->promise()->progress($this->expectCallableNever());
+ $adapter->notify();
+ }
+
+ /** @test */
+ public function alwaysShouldReturnAPromiseForSettledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $adapter->settle();
+ $this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->always(function () {}));
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/RejectTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/RejectTestTrait.php
new file mode 100644
index 0000000..063f178
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/RejectTestTrait.php
@@ -0,0 +1,368 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+use React\Promise;
+use React\Promise\Deferred;
+
+trait RejectTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function rejectShouldRejectWithAnImmediateValue()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function rejectShouldRejectWithFulfilledPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->reject(Promise\resolve(1));
+ }
+
+ /** @test */
+ public function rejectShouldRejectWithRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->reject(Promise\reject(1));
+ }
+
+ /** @test */
+ public function rejectShouldForwardReasonWhenCallbackIsNull()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever()
+ )
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function rejectShouldMakePromiseImmutable()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then(null, function ($value) use ($adapter) {
+ $adapter->reject(3);
+
+ return Promise\reject($value);
+ })
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ $adapter->reject(1);
+ $adapter->reject(2);
+ }
+
+ /** @test */
+ public function notifyShouldInvokeOtherwiseHandler()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->otherwise($mock);
+
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldInvokeRejectionHandler()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $this->assertNull($adapter->promise()->done(null, $mock));
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowExceptionThrownByRejectionHandler()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done(null, function () {
+ throw new \Exception('UnhandledRejectionException');
+ }));
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenRejectedWithNonException()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done());
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenRejectionHandlerRejects()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done(null, function () {
+ return \React\Promise\reject();
+ }));
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowRejectionExceptionWhenRejectionHandlerRejectsWithException()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done(null, function () {
+ return \React\Promise\reject(new \Exception('UnhandledRejectionException'));
+ }));
+ $adapter->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenRejectionHandlerRetunsPendingPromiseWhichRejectsLater()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $d = new Deferred();
+ $promise = $d->promise();
+
+ $this->assertNull($adapter->promise()->done(null, function () use ($promise) {
+ return $promise;
+ }));
+ $adapter->reject(1);
+ $d->reject(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowExceptionProvidedAsRejectionValue()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done());
+ $adapter->reject(new \Exception('UnhandledRejectionException'));
+ }
+
+ /** @test */
+ public function doneShouldThrowWithDeepNestingPromiseChains()
+ {
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $exception = new \Exception('UnhandledRejectionException');
+
+ $d = new Deferred();
+
+ $result = \React\Promise\resolve(\React\Promise\resolve($d->promise()->then(function () use ($exception) {
+ $d = new Deferred();
+ $d->resolve();
+
+ return \React\Promise\resolve($d->promise()->then(function () {}))->then(
+ function () use ($exception) {
+ throw $exception;
+ }
+ );
+ })));
+
+ $result->done();
+
+ $d->resolve();
+ }
+
+ /** @test */
+ public function doneShouldRecoverWhenRejectionHandlerCatchesException()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->assertNull($adapter->promise()->done(null, function (\Exception $e) {
+
+ }));
+ $adapter->reject(new \Exception('UnhandledRejectionException'));
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressRejection()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () {})
+ ->then(null, $mock);
+
+ $adapter->reject($exception);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () {
+ return 1;
+ })
+ ->then(null, $mock);
+
+ $adapter->reject($exception);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () {
+ return \React\Promise\resolve(1);
+ })
+ ->then(null, $mock);
+
+ $adapter->reject($exception);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerThrowsForRejection()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () use ($exception) {
+ throw $exception;
+ })
+ ->then(null, $mock);
+
+ $adapter->reject($exception);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerRejectsForRejection()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () use ($exception) {
+ return \React\Promise\reject($exception);
+ })
+ ->then(null, $mock);
+
+ $adapter->reject($exception);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/PromiseTest/ResolveTestTrait.php b/public/system/storage/vendor/react/promise/tests/PromiseTest/ResolveTestTrait.php
new file mode 100644
index 0000000..0736d35
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/PromiseTest/ResolveTestTrait.php
@@ -0,0 +1,312 @@
+<?php
+
+namespace React\Promise\PromiseTest;
+
+use React\Promise;
+
+trait ResolveTestTrait
+{
+ /**
+ * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
+ */
+ abstract public function getPromiseTestAdapter(callable $canceller = null);
+
+ /** @test */
+ public function resolveShouldResolve()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($mock);
+
+ $adapter->resolve(1);
+ }
+
+ /** @test */
+ public function resolveShouldResolveWithPromisedValue()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($mock);
+
+ $adapter->resolve(Promise\resolve(1));
+ }
+
+ /** @test */
+ public function resolveShouldRejectWhenResolvedWithRejectedPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then($this->expectCallableNever(), $mock);
+
+ $adapter->resolve(Promise\reject(1));
+ }
+
+ /** @test */
+ public function resolveShouldForwardValueWhenCallbackIsNull()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then(
+ null,
+ $this->expectCallableNever()
+ )
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+
+ $adapter->resolve(1);
+ }
+
+ /** @test */
+ public function resolveShouldMakePromiseImmutable()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $adapter->promise()
+ ->then(function ($value) use ($adapter) {
+ $adapter->resolve(3);
+
+ return $value;
+ })
+ ->then(
+ $mock,
+ $this->expectCallableNever()
+ );
+
+ $adapter->resolve(1);
+ $adapter->resolve(2);
+ }
+
+ /**
+ * @test
+ */
+ public function resolveShouldRejectWhenResolvedWithItself()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with(new \LogicException('Cannot resolve a promise with itself.'));
+
+ $adapter->promise()
+ ->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ $adapter->resolve($adapter->promise());
+ }
+
+ /**
+ * @test
+ */
+ public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself()
+ {
+ $adapter1 = $this->getPromiseTestAdapter();
+ $adapter2 = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with(new \LogicException('Cannot resolve a promise with itself.'));
+
+ $promise1 = $adapter1->promise();
+
+ $promise2 = $adapter2->promise();
+
+ $promise2->then(
+ $this->expectCallableNever(),
+ $mock
+ );
+
+ $adapter1->resolve($promise2);
+ $adapter2->resolve($promise1);
+ }
+
+ /** @test */
+ public function doneShouldInvokeFulfillmentHandler()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo(1));
+
+ $this->assertNull($adapter->promise()->done($mock));
+ $adapter->resolve(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowExceptionThrownFulfillmentHandler()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('\Exception', 'UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done(function () {
+ throw new \Exception('UnhandledRejectionException');
+ }));
+ $adapter->resolve(1);
+ }
+
+ /** @test */
+ public function doneShouldThrowUnhandledRejectionExceptionWhenFulfillmentHandlerRejects()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $this->setExpectedException('React\\Promise\\UnhandledRejectionException');
+
+ $this->assertNull($adapter->promise()->done(function () {
+ return \React\Promise\reject();
+ }));
+ $adapter->resolve(1);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressValue()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $value = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($value));
+
+ $adapter->promise()
+ ->always(function () {})
+ ->then($mock);
+
+ $adapter->resolve($value);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $value = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($value));
+
+ $adapter->promise()
+ ->always(function () {
+ return 1;
+ })
+ ->then($mock);
+
+ $adapter->resolve($value);
+ }
+
+ /** @test */
+ public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromise()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $value = new \stdClass();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($value));
+
+ $adapter->promise()
+ ->always(function () {
+ return \React\Promise\resolve(1);
+ })
+ ->then($mock);
+
+ $adapter->resolve($value);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerThrowsForFulfillment()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () use ($exception) {
+ throw $exception;
+ })
+ ->then(null, $mock);
+
+ $adapter->resolve(1);
+ }
+
+ /** @test */
+ public function alwaysShouldRejectWhenHandlerRejectsForFulfillment()
+ {
+ $adapter = $this->getPromiseTestAdapter();
+
+ $exception = new \Exception();
+
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke')
+ ->with($this->identicalTo($exception));
+
+ $adapter->promise()
+ ->always(function () use ($exception) {
+ return \React\Promise\reject($exception);
+ })
+ ->then(null, $mock);
+
+ $adapter->resolve(1);
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/RejectedPromiseTest.php b/public/system/storage/vendor/react/promise/tests/RejectedPromiseTest.php
new file mode 100644
index 0000000..825f56c
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/RejectedPromiseTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace React\Promise;
+
+use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
+
+class RejectedPromiseTest extends TestCase
+{
+ use PromiseTest\PromiseSettledTestTrait,
+ PromiseTest\PromiseRejectedTestTrait;
+
+ public function getPromiseTestAdapter(callable $canceller = null)
+ {
+ $promise = null;
+
+ return new CallbackPromiseAdapter([
+ 'promise' => function () use (&$promise) {
+ if (!$promise) {
+ throw new \LogicException('RejectedPromise must be rejected before obtaining the promise');
+ }
+
+ return $promise;
+ },
+ 'resolve' => function () {
+ throw new \LogicException('You cannot call resolve() for React\Promise\RejectedPromise');
+ },
+ 'reject' => function ($reason = null) use (&$promise) {
+ if (!$promise) {
+ $promise = new RejectedPromise($reason);
+ }
+ },
+ 'notify' => function () {
+ // no-op
+ },
+ 'settle' => function ($reason = null) use (&$promise) {
+ if (!$promise) {
+ $promise = new RejectedPromise($reason);
+ }
+ },
+ ]);
+ }
+
+ /** @test */
+ public function shouldThrowExceptionIfConstructedWithAPromise()
+ {
+ $this->setExpectedException('\InvalidArgumentException');
+
+ return new RejectedPromise(new RejectedPromise());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToRejectedPromiseWithAlwaysFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new RejectedPromise(1);
+ $promise->always(function () {
+ throw new \RuntimeException();
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+
+ /** @test */
+ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToRejectedPromiseWithThenFollowers()
+ {
+ gc_collect_cycles();
+ $promise = new RejectedPromise(1);
+ $promise = $promise->then(null, function () {
+ throw new \RuntimeException();
+ });
+ unset($promise);
+
+ $this->assertSame(0, gc_collect_cycles());
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/Stub/CallableStub.php b/public/system/storage/vendor/react/promise/tests/Stub/CallableStub.php
new file mode 100644
index 0000000..0120893
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/Stub/CallableStub.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace React\Promise\Stub;
+
+class CallableStub
+{
+ public function __invoke()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/TestCase.php b/public/system/storage/vendor/react/promise/tests/TestCase.php
new file mode 100644
index 0000000..c9274f4
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/TestCase.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace React\Promise;
+
+class TestCase extends \PHPUnit_Framework_TestCase
+{
+ public function expectCallableExactly($amount)
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->exactly($amount))
+ ->method('__invoke');
+
+ return $mock;
+ }
+
+ public function expectCallableOnce()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->once())
+ ->method('__invoke');
+
+ return $mock;
+ }
+
+ public function expectCallableNever()
+ {
+ $mock = $this->createCallableMock();
+ $mock
+ ->expects($this->never())
+ ->method('__invoke');
+
+ return $mock;
+ }
+
+ public function createCallableMock()
+ {
+ return $this
+ ->getMockBuilder('React\\Promise\Stub\CallableStub')
+ ->getMock();
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/bootstrap.php b/public/system/storage/vendor/react/promise/tests/bootstrap.php
new file mode 100644
index 0000000..9b7f872
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/bootstrap.php
@@ -0,0 +1,7 @@
+<?php
+
+$loader = @include __DIR__.'/../vendor/autoload.php';
+if (!$loader) {
+ $loader = require __DIR__.'/../../../../vendor/autoload.php';
+}
+$loader->addPsr4('React\\Promise\\', __DIR__);
diff --git a/public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestPromise.php b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestPromise.php
new file mode 100644
index 0000000..ef4d530
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestPromise.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace React\Promise;
+
+class SimpleFulfilledTestPromise implements PromiseInterface
+{
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ try {
+ if ($onFulfilled) {
+ $onFulfilled('foo');
+ }
+
+ return new self();
+ } catch (\Throwable $exception) {
+ return new RejectedPromise($exception);
+ } catch (\Exception $exception) {
+ return new RejectedPromise($exception);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestThenable.php b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestThenable.php
new file mode 100644
index 0000000..3f66f63
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleFulfilledTestThenable.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace React\Promise;
+
+class SimpleFulfilledTestThenable
+{
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ try {
+ if ($onFulfilled) {
+ $onFulfilled('foo');
+ }
+
+ return new self();
+ } catch (\Throwable $exception) {
+ return new RejectedPromise($exception);
+ } catch (\Exception $exception) {
+ return new RejectedPromise($exception);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/fixtures/SimpleRejectedTestPromise.php b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleRejectedTestPromise.php
new file mode 100644
index 0000000..b30a226
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleRejectedTestPromise.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace React\Promise;
+
+class SimpleRejectedTestPromise implements PromiseInterface
+{
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ try {
+ if ($onRejected) {
+ $onRejected('foo');
+ }
+
+ return new self();
+ } catch (\Throwable $exception) {
+ return new RejectedPromise($exception);
+ } catch (\Exception $exception) {
+ return new RejectedPromise($exception);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellable.php b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellable.php
new file mode 100644
index 0000000..f232a68
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellable.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace React\Promise;
+
+class SimpleTestCancellable
+{
+ public $cancelCalled = false;
+
+ public function cancel()
+ {
+ $this->cancelCalled = true;
+ }
+}
diff --git a/public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellableThenable.php b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellableThenable.php
new file mode 100644
index 0000000..c0f1593
--- /dev/null
+++ b/public/system/storage/vendor/react/promise/tests/fixtures/SimpleTestCancellableThenable.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace React\Promise;
+
+class SimpleTestCancellableThenable
+{
+ public $cancelCalled = false;
+
+ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
+ {
+ return new self();
+ }
+
+ public function cancel()
+ {
+ $this->cancelCalled = true;
+ }
+}
diff --git a/public/system/storage/vendor/scss.inc.php b/public/system/storage/vendor/scss.inc.php
new file mode 100644
index 0000000..e60349c
--- /dev/null
+++ b/public/system/storage/vendor/scss.inc.php
@@ -0,0 +1,4574 @@
+<?php
+/**
+ * SCSS compiler written in PHP
+ *
+ * @copyright 2012-2013 Leaf Corcoran
+ *
+ * @license http://opensource.org/licenses/gpl-license GPL-3.0
+ * @license http://opensource.org/licenses/MIT MIT
+ *
+ * @link http://leafo.net/scssphp
+ */
+
+/**
+ * The scss compiler and parser.
+ *
+ * Converting SCSS to CSS is a three stage process. The incoming file is parsed
+ * by `scss_parser` into a syntax tree, then it is compiled into another tree
+ * representing the CSS structure by `scssc`. The CSS tree is fed into a
+ * formatter, like `scss_formatter` which then outputs CSS as a string.
+ *
+ * During the first compile, all values are *reduced*, which means that their
+ * types are brought to the lowest form before being dump as strings. This
+ * handles math equations, variable dereferences, and the like.
+ *
+ * The `parse` function of `scssc` is the entry point.
+ *
+ * In summary:
+ *
+ * The `scssc` class creates an instance of the parser, feeds it SCSS code,
+ * then transforms the resulting tree to a CSS tree. This class also holds the
+ * evaluation context, such as all available mixins and variables at any given
+ * time.
+ *
+ * The `scss_parser` class is only concerned with parsing its input.
+ *
+ * The `scss_formatter` takes a CSS tree, and dumps it to a formatted string,
+ * handling things like indentation.
+ */
+
+/**
+ * SCSS compiler
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scssc {
+ static public $VERSION = 'v0.0.12';
+
+ static protected $operatorNames = array(
+ '+' => "add",
+ '-' => "sub",
+ '*' => "mul",
+ '/' => "div",
+ '%' => "mod",
+
+ '==' => "eq",
+ '!=' => "neq",
+ '<' => "lt",
+ '>' => "gt",
+
+ '<=' => "lte",
+ '>=' => "gte",
+ );
+
+ static protected $namespaces = array(
+ "special" => "%",
+ "mixin" => "@",
+ "function" => "^",
+ );
+
+ static protected $unitTable = array(
+ "in" => array(
+ "in" => 1,
+ "pt" => 72,
+ "pc" => 6,
+ "cm" => 2.54,
+ "mm" => 25.4,
+ "px" => 96,
+ )
+ );
+
+ static public $true = array("keyword", "true");
+ static public $false = array("keyword", "false");
+ static public $null = array("null");
+
+ static public $defaultValue = array("keyword", "");
+ static public $selfSelector = array("self");
+
+ protected $importPaths = array("");
+ protected $importCache = array();
+
+ protected $userFunctions = array();
+ protected $registeredVars = array();
+
+ protected $numberPrecision = 5;
+
+ protected $formatter = "scss_formatter_nested";
+
+ /**
+ * Compile scss
+ *
+ * @param string $code
+ * @param string $name
+ *
+ * @return string
+ */
+ public function compile($code, $name = null)
+ {
+ $this->indentLevel = -1;
+ $this->commentsSeen = array();
+ $this->extends = array();
+ $this->extendsMap = array();
+ $this->parsedFiles = array();
+ $this->env = null;
+ $this->scope = null;
+
+ $locale = setlocale(LC_NUMERIC, 0);
+ setlocale(LC_NUMERIC, "C");
+
+ $this->parser = new scss_parser($name);
+
+ $tree = $this->parser->parse($code);
+
+ $this->formatter = new $this->formatter();
+
+ $this->pushEnv($tree);
+ $this->injectVariables($this->registeredVars);
+ $this->compileRoot($tree);
+ $this->popEnv();
+
+ $out = $this->formatter->format($this->scope);
+
+ setlocale(LC_NUMERIC, $locale);
+
+ return $out;
+ }
+
+ protected function isSelfExtend($target, $origin) {
+ foreach ($origin as $sel) {
+ if (in_array($target, $sel)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected function pushExtends($target, $origin) {
+ if ($this->isSelfExtend($target, $origin)) {
+ return;
+ }
+
+ $i = count($this->extends);
+ $this->extends[] = array($target, $origin);
+
+ foreach ($target as $part) {
+ if (isset($this->extendsMap[$part])) {
+ $this->extendsMap[$part][] = $i;
+ } else {
+ $this->extendsMap[$part] = array($i);
+ }
+ }
+ }
+
+ protected function makeOutputBlock($type, $selectors = null) {
+ $out = new stdClass;
+ $out->type = $type;
+ $out->lines = array();
+ $out->children = array();
+ $out->parent = $this->scope;
+ $out->selectors = $selectors;
+ $out->depth = $this->env->depth;
+
+ return $out;
+ }
+
+ protected function matchExtendsSingle($single, &$outOrigin) {
+ $counts = array();
+ foreach ($single as $part) {
+ if (!is_string($part)) return false; // hmm
+
+ if (isset($this->extendsMap[$part])) {
+ foreach ($this->extendsMap[$part] as $idx) {
+ $counts[$idx] =
+ isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
+ }
+ }
+ }
+
+ $outOrigin = array();
+ $found = false;
+
+ foreach ($counts as $idx => $count) {
+ list($target, $origin) = $this->extends[$idx];
+
+ // check count
+ if ($count != count($target)) continue;
+
+ // check if target is subset of single
+ if (array_diff(array_intersect($single, $target), $target)) continue;
+
+ $rem = array_diff($single, $target);
+
+ foreach ($origin as $j => $new) {
+ // prevent infinite loop when target extends itself
+ foreach ($new as $new_selector) {
+ if (!array_diff($single, $new_selector)) {
+ continue 2;
+ }
+ }
+
+ $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
+ }
+
+ $outOrigin = array_merge($outOrigin, $origin);
+
+ $found = true;
+ }
+
+ return $found;
+ }
+
+ protected function combineSelectorSingle($base, $other) {
+ $tag = null;
+ $out = array();
+
+ foreach (array($base, $other) as $single) {
+ foreach ($single as $part) {
+ if (preg_match('/^[^\[.#:]/', $part)) {
+ $tag = $part;
+ } else {
+ $out[] = $part;
+ }
+ }
+ }
+
+ if ($tag) {
+ array_unshift($out, $tag);
+ }
+
+ return $out;
+ }
+
+ protected function matchExtends($selector, &$out, $from = 0, $initial=true) {
+ foreach ($selector as $i => $part) {
+ if ($i < $from) continue;
+
+ if ($this->matchExtendsSingle($part, $origin)) {
+ $before = array_slice($selector, 0, $i);
+ $after = array_slice($selector, $i + 1);
+
+ foreach ($origin as $new) {
+ $k = 0;
+
+ // remove shared parts
+ if ($initial) {
+ foreach ($before as $k => $val) {
+ if (!isset($new[$k]) || $val != $new[$k]) {
+ break;
+ }
+ }
+ }
+
+ $result = array_merge(
+ $before,
+ $k > 0 ? array_slice($new, $k) : $new,
+ $after);
+
+
+ if ($result == $selector) continue;
+ $out[] = $result;
+
+ // recursively check for more matches
+ $this->matchExtends($result, $out, $i, false);
+
+ // selector sequence merging
+ if (!empty($before) && count($new) > 1) {
+ $result2 = array_merge(
+ array_slice($new, 0, -1),
+ $k > 0 ? array_slice($before, $k) : $before,
+ array_slice($new, -1),
+ $after);
+
+ $out[] = $result2;
+ }
+ }
+ }
+ }
+ }
+
+ protected function flattenSelectors($block, $parentKey = null) {
+ if ($block->selectors) {
+ $selectors = array();
+ foreach ($block->selectors as $s) {
+ $selectors[] = $s;
+ if (!is_array($s)) continue;
+ // check extends
+ if (!empty($this->extendsMap)) {
+ $this->matchExtends($s, $selectors);
+ }
+ }
+
+ $block->selectors = array();
+ $placeholderSelector = false;
+ foreach ($selectors as $selector) {
+ if ($this->hasSelectorPlaceholder($selector)) {
+ $placeholderSelector = true;
+ continue;
+ }
+ $block->selectors[] = $this->compileSelector($selector);
+ }
+
+ if ($placeholderSelector && 0 == count($block->selectors) && null !== $parentKey) {
+ unset($block->parent->children[$parentKey]);
+ return;
+ }
+ }
+
+ foreach ($block->children as $key => $child) {
+ $this->flattenSelectors($child, $key);
+ }
+ }
+
+ protected function compileRoot($rootBlock)
+ {
+ $this->scope = $this->makeOutputBlock('root');
+
+ $this->compileChildren($rootBlock->children, $this->scope);
+ $this->flattenSelectors($this->scope);
+ }
+
+ protected function compileMedia($media) {
+ $this->pushEnv($media);
+
+ $mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
+
+ if (!empty($mediaQuery)) {
+
+ $this->scope = $this->makeOutputBlock("media", array($mediaQuery));
+
+ $parentScope = $this->mediaParent($this->scope);
+
+ $parentScope->children[] = $this->scope;
+
+ // top level properties in a media cause it to be wrapped
+ $needsWrap = false;
+ foreach ($media->children as $child) {
+ $type = $child[0];
+ if ($type !== 'block' && $type !== 'media' && $type !== 'directive') {
+ $needsWrap = true;
+ break;
+ }
+ }
+
+ if ($needsWrap) {
+ $wrapped = (object)array(
+ "selectors" => array(),
+ "children" => $media->children
+ );
+ $media->children = array(array("block", $wrapped));
+ }
+
+ $this->compileChildren($media->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ }
+
+ $this->popEnv();
+ }
+
+ protected function mediaParent($scope) {
+ while (!empty($scope->parent)) {
+ if (!empty($scope->type) && $scope->type != "media") {
+ break;
+ }
+ $scope = $scope->parent;
+ }
+
+ return $scope;
+ }
+
+ // TODO refactor compileNestedBlock and compileMedia into same thing
+ protected function compileNestedBlock($block, $selectors) {
+ $this->pushEnv($block);
+
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->parent->children[] = $this->scope;
+ $this->compileChildren($block->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ /**
+ * Recursively compiles a block.
+ *
+ * A block is analogous to a CSS block in most cases. A single SCSS document
+ * is encapsulated in a block when parsed, but it does not have parent tags
+ * so all of its children appear on the root level when compiled.
+ *
+ * Blocks are made up of selectors and children.
+ *
+ * The children of a block are just all the blocks that are defined within.
+ *
+ * Compiling the block involves pushing a fresh environment on the stack,
+ * and iterating through the props, compiling each one.
+ *
+ * @see scss::compileChild()
+ *
+ * @param \StdClass $block
+ */
+ protected function compileBlock($block) {
+ $env = $this->pushEnv($block);
+
+ $env->selectors =
+ array_map(array($this, "evalSelector"), $block->selectors);
+
+ $out = $this->makeOutputBlock(null, $this->multiplySelectors($env));
+ $this->scope->children[] = $out;
+ $this->compileChildren($block->children, $out);
+
+ $this->popEnv();
+ }
+
+ // joins together .classes and #ids
+ protected function flattenSelectorSingle($single) {
+ $joined = array();
+ foreach ($single as $part) {
+ if (empty($joined) ||
+ !is_string($part) ||
+ preg_match('/[\[.:#%]/', $part))
+ {
+ $joined[] = $part;
+ continue;
+ }
+
+ if (is_array(end($joined))) {
+ $joined[] = $part;
+ } else {
+ $joined[count($joined) - 1] .= $part;
+ }
+ }
+
+ return $joined;
+ }
+
+ // replaces all the interpolates
+ protected function evalSelector($selector) {
+ return array_map(array($this, "evalSelectorPart"), $selector);
+ }
+
+ protected function evalSelectorPart($piece) {
+ foreach ($piece as &$p) {
+ if (!is_array($p)) continue;
+
+ switch ($p[0]) {
+ case "interpolate":
+ $p = $this->compileValue($p);
+ break;
+ case "string":
+ $p = $this->compileValue($p);
+ break;
+ }
+ }
+
+ return $this->flattenSelectorSingle($piece);
+ }
+
+ // compiles to string
+ // self(&) should have been replaced by now
+ protected function compileSelector($selector) {
+ if (!is_array($selector)) return $selector; // media and the like
+
+ return implode(" ", array_map(
+ array($this, "compileSelectorPart"), $selector));
+ }
+
+ protected function compileSelectorPart($piece) {
+ foreach ($piece as &$p) {
+ if (!is_array($p)) continue;
+
+ switch ($p[0]) {
+ case "self":
+ $p = "&";
+ break;
+ default:
+ $p = $this->compileValue($p);
+ break;
+ }
+ }
+
+ return implode($piece);
+ }
+
+ protected function hasSelectorPlaceholder($selector)
+ {
+ if (!is_array($selector)) return false;
+
+ foreach ($selector as $parts) {
+ foreach ($parts as $part) {
+ if ('%' == $part[0]) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected function compileChildren($stms, $out) {
+ foreach ($stms as $stm) {
+ $ret = $this->compileChild($stm, $out);
+ if (isset($ret)) return $ret;
+ }
+ }
+
+ protected function compileMediaQuery($queryList) {
+ $out = "@media";
+ $first = true;
+ foreach ($queryList as $query){
+ $type = null;
+ $parts = array();
+ foreach ($query as $q) {
+ switch ($q[0]) {
+ case "mediaType":
+ if ($type) {
+ $type = $this->mergeMediaTypes($type, array_map(array($this, "compileValue"), array_slice($q, 1)));
+ if (empty($type)) { // merge failed
+ return null;
+ }
+ } else {
+ $type = array_map(array($this, "compileValue"), array_slice($q, 1));
+ }
+ break;
+ case "mediaExp":
+ if (isset($q[2])) {
+ $parts[] = "(". $this->compileValue($q[1]) . $this->formatter->assignSeparator . $this->compileValue($q[2]) . ")";
+ } else {
+ $parts[] = "(" . $this->compileValue($q[1]) . ")";
+ }
+ break;
+ }
+ }
+ if ($type) {
+ array_unshift($parts, implode(' ', array_filter($type)));
+ }
+ if (!empty($parts)) {
+ if ($first) {
+ $first = false;
+ $out .= " ";
+ } else {
+ $out .= $this->formatter->tagSeparator;
+ }
+ $out .= implode(" and ", $parts);
+ }
+ }
+ return $out;
+ }
+
+ protected function mergeMediaTypes($type1, $type2) {
+ if (empty($type1)) {
+ return $type2;
+ }
+ if (empty($type2)) {
+ return $type1;
+ }
+ $m1 = '';
+ $t1 = '';
+ if (count($type1) > 1) {
+ $m1= strtolower($type1[0]);
+ $t1= strtolower($type1[1]);
+ } else {
+ $t1 = strtolower($type1[0]);
+ }
+ $m2 = '';
+ $t2 = '';
+ if (count($type2) > 1) {
+ $m2 = strtolower($type2[0]);
+ $t2 = strtolower($type2[1]);
+ } else {
+ $t2 = strtolower($type2[0]);
+ }
+ if (($m1 == 'not') ^ ($m2 == 'not')) {
+ if ($t1 == $t2) {
+ return null;
+ }
+ return array(
+ $m1 == 'not' ? $m2 : $m1,
+ $m1 == 'not' ? $t2 : $t1
+ );
+ } elseif ($m1 == 'not' && $m2 == 'not') {
+ # CSS has no way of representing "neither screen nor print"
+ if ($t1 != $t2) {
+ return null;
+ }
+ return array('not', $t1);
+ } elseif ($t1 != $t2) {
+ return null;
+ } else { // t1 == t2, neither m1 nor m2 are "not"
+ return array(empty($m1)? $m2 : $m1, $t1);
+ }
+ }
+
+ // returns true if the value was something that could be imported
+ protected function compileImport($rawPath, $out) {
+ if ($rawPath[0] == "string") {
+ $path = $this->compileStringContent($rawPath);
+ if ($path = $this->findImport($path)) {
+ $this->importFile($path, $out);
+ return true;
+ }
+ return false;
+ }
+ if ($rawPath[0] == "list") {
+ // handle a list of strings
+ if (count($rawPath[2]) == 0) return false;
+ foreach ($rawPath[2] as $path) {
+ if ($path[0] != "string") return false;
+ }
+
+ foreach ($rawPath[2] as $path) {
+ $this->compileImport($path, $out);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // return a value to halt execution
+ protected function compileChild($child, $out) {
+ $this->sourcePos = isset($child[-1]) ? $child[-1] : -1;
+ $this->sourceParser = isset($child[-2]) ? $child[-2] : $this->parser;
+
+ switch ($child[0]) {
+ case "import":
+ list(,$rawPath) = $child;
+ $rawPath = $this->reduce($rawPath);
+ if (!$this->compileImport($rawPath, $out)) {
+ $out->lines[] = "@import " . $this->compileValue($rawPath) . ";";
+ }
+ break;
+ case "directive":
+ list(, $directive) = $child;
+ $s = "@" . $directive->name;
+ if (!empty($directive->value)) {
+ $s .= " " . $this->compileValue($directive->value);
+ }
+ $this->compileNestedBlock($directive, array($s));
+ break;
+ case "media":
+ $this->compileMedia($child[1]);
+ break;
+ case "block":
+ $this->compileBlock($child[1]);
+ break;
+ case "charset":
+ $out->lines[] = "@charset ".$this->compileValue($child[1]).";";
+ break;
+ case "assign":
+ list(,$name, $value) = $child;
+ if ($name[0] == "var") {
+ $isDefault = !empty($child[3]);
+
+ if ($isDefault) {
+ $existingValue = $this->get($name[1], true);
+ $shouldSet = $existingValue === true || $existingValue == self::$null;
+ }
+
+ if (!$isDefault || $shouldSet) {
+ $this->set($name[1], $this->reduce($value));
+ }
+ break;
+ }
+
+ // if the value reduces to null from something else then
+ // the property should be discarded
+ if ($value[0] != "null") {
+ $value = $this->reduce($value);
+ if ($value[0] == "null") {
+ break;
+ }
+ }
+
+ $compiledValue = $this->compileValue($value);
+ $out->lines[] = $this->formatter->property(
+ $this->compileValue($name),
+ $compiledValue);
+ break;
+ case "comment":
+ $out->lines[] = $child[1];
+ break;
+ case "mixin":
+ case "function":
+ list(,$block) = $child;
+ $this->set(self::$namespaces[$block->type] . $block->name, $block);
+ break;
+ case "extend":
+ list(, $selectors) = $child;
+ foreach ($selectors as $sel) {
+ // only use the first one
+ $sel = current($this->evalSelector($sel));
+ $this->pushExtends($sel, $out->selectors);
+ }
+ break;
+ case "if":
+ list(, $if) = $child;
+ if ($this->isTruthy($this->reduce($if->cond, true))) {
+ return $this->compileChildren($if->children, $out);
+ } else {
+ foreach ($if->cases as $case) {
+ if ($case->type == "else" ||
+ $case->type == "elseif" && $this->isTruthy($this->reduce($case->cond)))
+ {
+ return $this->compileChildren($case->children, $out);
+ }
+ }
+ }
+ break;
+ case "return":
+ return $this->reduce($child[1], true);
+ case "each":
+ list(,$each) = $child;
+ $list = $this->coerceList($this->reduce($each->list));
+ foreach ($list[2] as $item) {
+ $this->pushEnv();
+ $this->set($each->var, $item);
+ // TODO: allow return from here
+ $this->compileChildren($each->children, $out);
+ $this->popEnv();
+ }
+ break;
+ case "while":
+ list(,$while) = $child;
+ while ($this->isTruthy($this->reduce($while->cond, true))) {
+ $ret = $this->compileChildren($while->children, $out);
+ if ($ret) return $ret;
+ }
+ break;
+ case "for":
+ list(,$for) = $child;
+ $start = $this->reduce($for->start, true);
+ $start = $start[1];
+ $end = $this->reduce($for->end, true);
+ $end = $end[1];
+ $d = $start < $end ? 1 : -1;
+
+ while (true) {
+ if ((!$for->until && $start - $d == $end) ||
+ ($for->until && $start == $end))
+ {
+ break;
+ }
+
+ $this->set($for->var, array("number", $start, ""));
+ $start += $d;
+
+ $ret = $this->compileChildren($for->children, $out);
+ if ($ret) return $ret;
+ }
+
+ break;
+ case "nestedprop":
+ list(,$prop) = $child;
+ $prefixed = array();
+ $prefix = $this->compileValue($prop->prefix) . "-";
+ foreach ($prop->children as $child) {
+ if ($child[0] == "assign") {
+ array_unshift($child[1][2], $prefix);
+ }
+ if ($child[0] == "nestedprop") {
+ array_unshift($child[1]->prefix[2], $prefix);
+ }
+ $prefixed[] = $child;
+ }
+ $this->compileChildren($prefixed, $out);
+ break;
+ case "include": // including a mixin
+ list(,$name, $argValues, $content) = $child;
+ $mixin = $this->get(self::$namespaces["mixin"] . $name, false);
+ if (!$mixin) {
+ $this->throwError("Undefined mixin $name");
+ }
+
+ $callingScope = $this->env;
+
+ // push scope, apply args
+ $this->pushEnv();
+ if ($this->env->depth > 0) {
+ $this->env->depth--;
+ }
+
+ if (isset($content)) {
+ $content->scope = $callingScope;
+ $this->setRaw(self::$namespaces["special"] . "content", $content);
+ }
+
+ if (isset($mixin->args)) {
+ $this->applyArguments($mixin->args, $argValues);
+ }
+
+ foreach ($mixin->children as $child) {
+ $this->compileChild($child, $out);
+ }
+
+ $this->popEnv();
+
+ break;
+ case "mixin_content":
+ $content = $this->get(self::$namespaces["special"] . "content");
+ if (!isset($content)) {
+ $this->throwError("Expected @content inside of mixin");
+ }
+
+ $strongTypes = array('include', 'block', 'for', 'while');
+ foreach ($content->children as $child) {
+ $this->storeEnv = (in_array($child[0], $strongTypes))
+ ? null
+ : $content->scope;
+
+ $this->compileChild($child, $out);
+ }
+
+ unset($this->storeEnv);
+ break;
+ case "debug":
+ list(,$value, $pos) = $child;
+ $line = $this->parser->getLineNo($pos);
+ $value = $this->compileValue($this->reduce($value, true));
+ fwrite(STDERR, "Line $line DEBUG: $value\n");
+ break;
+ default:
+ $this->throwError("unknown child type: $child[0]");
+ }
+ }
+
+ protected function expToString($exp) {
+ list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp;
+ $content = array($this->reduce($left));
+ if ($whiteLeft) $content[] = " ";
+ $content[] = $op;
+ if ($whiteRight) $content[] = " ";
+ $content[] = $this->reduce($right);
+ return array("string", "", $content);
+ }
+
+ protected function isTruthy($value) {
+ return $value != self::$false && $value != self::$null;
+ }
+
+ // should $value cause its operand to eval
+ protected function shouldEval($value) {
+ switch ($value[0]) {
+ case "exp":
+ if ($value[1] == "/") {
+ return $this->shouldEval($value[2], $value[3]);
+ }
+ case "var":
+ case "fncall":
+ return true;
+ }
+ return false;
+ }
+
+ protected function reduce($value, $inExp = false) {
+ list($type) = $value;
+ switch ($type) {
+ case "exp":
+ list(, $op, $left, $right, $inParens) = $value;
+ $opName = isset(self::$operatorNames[$op]) ? self::$operatorNames[$op] : $op;
+
+ $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right);
+
+ $left = $this->reduce($left, true);
+ $right = $this->reduce($right, true);
+
+ // only do division in special cases
+ if ($opName == "div" && !$inParens && !$inExp) {
+ if ($left[0] != "color" && $right[0] != "color") {
+ return $this->expToString($value);
+ }
+ }
+
+ $left = $this->coerceForExpression($left);
+ $right = $this->coerceForExpression($right);
+
+ $ltype = $left[0];
+ $rtype = $right[0];
+
+ // this tries:
+ // 1. op_[op name]_[left type]_[right type]
+ // 2. op_[left type]_[right type] (passing the op as first arg
+ // 3. op_[op name]
+ $fn = "op_${opName}_${ltype}_${rtype}";
+ if (is_callable(array($this, $fn)) ||
+ (($fn = "op_${ltype}_${rtype}") &&
+ is_callable(array($this, $fn)) &&
+ $passOp = true) ||
+ (($fn = "op_${opName}") &&
+ is_callable(array($this, $fn)) &&
+ $genOp = true))
+ {
+ $unitChange = false;
+ if (!isset($genOp) &&
+ $left[0] == "number" && $right[0] == "number")
+ {
+ if ($opName == "mod" && $right[2] != "") {
+ $this->throwError("Cannot modulo by a number with units: $right[1]$right[2].");
+ }
+
+ $unitChange = true;
+ $emptyUnit = $left[2] == "" || $right[2] == "";
+ $targetUnit = "" != $left[2] ? $left[2] : $right[2];
+
+ if ($opName != "mul") {
+ $left[2] = "" != $left[2] ? $left[2] : $targetUnit;
+ $right[2] = "" != $right[2] ? $right[2] : $targetUnit;
+ }
+
+ if ($opName != "mod") {
+ $left = $this->normalizeNumber($left);
+ $right = $this->normalizeNumber($right);
+ }
+
+ if ($opName == "div" && !$emptyUnit && $left[2] == $right[2]) {
+ $targetUnit = "";
+ }
+
+ if ($opName == "mul") {
+ $left[2] = "" != $left[2] ? $left[2] : $right[2];
+ $right[2] = "" != $right[2] ? $right[2] : $left[2];
+ } elseif ($opName == "div" && $left[2] == $right[2]) {
+ $left[2] = "";
+ $right[2] = "";
+ }
+ }
+
+ $shouldEval = $inParens || $inExp;
+ if (isset($passOp)) {
+ $out = $this->$fn($op, $left, $right, $shouldEval);
+ } else {
+ $out = $this->$fn($left, $right, $shouldEval);
+ }
+
+ if (isset($out)) {
+ if ($unitChange && $out[0] == "number") {
+ $out = $this->coerceUnit($out, $targetUnit);
+ }
+ return $out;
+ }
+ }
+
+ return $this->expToString($value);
+ case "unary":
+ list(, $op, $exp, $inParens) = $value;
+ $inExp = $inExp || $this->shouldEval($exp);
+
+ $exp = $this->reduce($exp);
+ if ($exp[0] == "number") {
+ switch ($op) {
+ case "+":
+ return $exp;
+ case "-":
+ $exp[1] *= -1;
+ return $exp;
+ }
+ }
+
+ if ($op == "not") {
+ if ($inExp || $inParens) {
+ if ($exp == self::$false) {
+ return self::$true;
+ } else {
+ return self::$false;
+ }
+ } else {
+ $op = $op . " ";
+ }
+ }
+
+ return array("string", "", array($op, $exp));
+ case "var":
+ list(, $name) = $value;
+ return $this->reduce($this->get($name));
+ case "list":
+ foreach ($value[2] as &$item) {
+ $item = $this->reduce($item);
+ }
+ return $value;
+ case "string":
+ foreach ($value[2] as &$item) {
+ if (is_array($item)) {
+ $item = $this->reduce($item);
+ }
+ }
+ return $value;
+ case "interpolate":
+ $value[1] = $this->reduce($value[1]);
+ return $value;
+ case "fncall":
+ list(,$name, $argValues) = $value;
+
+ // user defined function?
+ $func = $this->get(self::$namespaces["function"] . $name, false);
+ if ($func) {
+ $this->pushEnv();
+
+ // set the args
+ if (isset($func->args)) {
+ $this->applyArguments($func->args, $argValues);
+ }
+
+ // throw away lines and children
+ $tmp = (object)array(
+ "lines" => array(),
+ "children" => array()
+ );
+ $ret = $this->compileChildren($func->children, $tmp);
+ $this->popEnv();
+
+ return !isset($ret) ? self::$defaultValue : $ret;
+ }
+
+ // built in function
+ if ($this->callBuiltin($name, $argValues, $returnValue)) {
+ return $returnValue;
+ }
+
+ // need to flatten the arguments into a list
+ $listArgs = array();
+ foreach ((array)$argValues as $arg) {
+ if (empty($arg[0])) {
+ $listArgs[] = $this->reduce($arg[1]);
+ }
+ }
+ return array("function", $name, array("list", ",", $listArgs));
+ default:
+ return $value;
+ }
+ }
+
+ public function normalizeValue($value) {
+ $value = $this->coerceForExpression($this->reduce($value));
+ list($type) = $value;
+
+ switch ($type) {
+ case "list":
+ $value = $this->extractInterpolation($value);
+ if ($value[0] != "list") {
+ return array("keyword", $this->compileValue($value));
+ }
+ foreach ($value[2] as $key => $item) {
+ $value[2][$key] = $this->normalizeValue($item);
+ }
+ return $value;
+ case "number":
+ return $this->normalizeNumber($value);
+ default:
+ return $value;
+ }
+ }
+
+ // just does physical lengths for now
+ protected function normalizeNumber($number) {
+ list(, $value, $unit) = $number;
+ if (isset(self::$unitTable["in"][$unit])) {
+ $conv = self::$unitTable["in"][$unit];
+ return array("number", $value / $conv, "in");
+ }
+ return $number;
+ }
+
+ // $number should be normalized
+ protected function coerceUnit($number, $unit) {
+ list(, $value, $baseUnit) = $number;
+ if (isset(self::$unitTable[$baseUnit][$unit])) {
+ $value = $value * self::$unitTable[$baseUnit][$unit];
+ }
+
+ return array("number", $value, $unit);
+ }
+
+ protected function op_add_number_number($left, $right) {
+ return array("number", $left[1] + $right[1], $left[2]);
+ }
+
+ protected function op_mul_number_number($left, $right) {
+ return array("number", $left[1] * $right[1], $left[2]);
+ }
+
+ protected function op_sub_number_number($left, $right) {
+ return array("number", $left[1] - $right[1], $left[2]);
+ }
+
+ protected function op_div_number_number($left, $right) {
+ return array("number", $left[1] / $right[1], $left[2]);
+ }
+
+ protected function op_mod_number_number($left, $right) {
+ return array("number", $left[1] % $right[1], $left[2]);
+ }
+
+ // adding strings
+ protected function op_add($left, $right) {
+ if ($strLeft = $this->coerceString($left)) {
+ if ($right[0] == "string") {
+ $right[1] = "";
+ }
+ $strLeft[2][] = $right;
+ return $strLeft;
+ }
+
+ if ($strRight = $this->coerceString($right)) {
+ if ($left[0] == "string") {
+ $left[1] = "";
+ }
+ array_unshift($strRight[2], $left);
+ return $strRight;
+ }
+ }
+
+ protected function op_and($left, $right, $shouldEval) {
+ if (!$shouldEval) return;
+ if ($left != self::$false) return $right;
+ return $left;
+ }
+
+ protected function op_or($left, $right, $shouldEval) {
+ if (!$shouldEval) return;
+ if ($left != self::$false) return $left;
+ return $right;
+ }
+
+ protected function op_color_color($op, $left, $right) {
+ $out = array('color');
+ foreach (range(1, 3) as $i) {
+ $lval = isset($left[$i]) ? $left[$i] : 0;
+ $rval = isset($right[$i]) ? $right[$i] : 0;
+ switch ($op) {
+ case '+':
+ $out[] = $lval + $rval;
+ break;
+ case '-':
+ $out[] = $lval - $rval;
+ break;
+ case '*':
+ $out[] = $lval * $rval;
+ break;
+ case '%':
+ $out[] = $lval % $rval;
+ break;
+ case '/':
+ if ($rval == 0) {
+ $this->throwError("color: Can't divide by zero");
+ }
+ $out[] = $lval / $rval;
+ break;
+ case "==":
+ return $this->op_eq($left, $right);
+ case "!=":
+ return $this->op_neq($left, $right);
+ default:
+ $this->throwError("color: unknown op $op");
+ }
+ }
+
+ if (isset($left[4])) $out[4] = $left[4];
+ elseif (isset($right[4])) $out[4] = $right[4];
+
+ return $this->fixColor($out);
+ }
+
+ protected function op_color_number($op, $left, $right) {
+ $value = $right[1];
+ return $this->op_color_color($op, $left,
+ array("color", $value, $value, $value));
+ }
+
+ protected function op_number_color($op, $left, $right) {
+ $value = $left[1];
+ return $this->op_color_color($op,
+ array("color", $value, $value, $value), $right);
+ }
+
+ protected function op_eq($left, $right) {
+ if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
+ $lStr[1] = "";
+ $rStr[1] = "";
+ return $this->toBool($this->compileValue($lStr) == $this->compileValue($rStr));
+ }
+
+ return $this->toBool($left == $right);
+ }
+
+ protected function op_neq($left, $right) {
+ return $this->toBool($left != $right);
+ }
+
+ protected function op_gte_number_number($left, $right) {
+ return $this->toBool($left[1] >= $right[1]);
+ }
+
+ protected function op_gt_number_number($left, $right) {
+ return $this->toBool($left[1] > $right[1]);
+ }
+
+ protected function op_lte_number_number($left, $right) {
+ return $this->toBool($left[1] <= $right[1]);
+ }
+
+ protected function op_lt_number_number($left, $right) {
+ return $this->toBool($left[1] < $right[1]);
+ }
+
+ public function toBool($thing) {
+ return $thing ? self::$true : self::$false;
+ }
+
+ /**
+ * Compiles a primitive value into a CSS property value.
+ *
+ * Values in scssphp are typed by being wrapped in arrays, their format is
+ * typically:
+ *
+ * array(type, contents [, additional_contents]*)
+ *
+ * The input is expected to be reduced. This function will not work on
+ * things like expressions and variables.
+ *
+ * @param array $value
+ */
+ protected function compileValue($value) {
+ $value = $this->reduce($value);
+
+ list($type) = $value;
+ switch ($type) {
+ case "keyword":
+ return $value[1];
+ case "color":
+ // [1] - red component (either number for a %)
+ // [2] - green component
+ // [3] - blue component
+ // [4] - optional alpha component
+ list(, $r, $g, $b) = $value;
+
+ $r = round($r);
+ $g = round($g);
+ $b = round($b);
+
+ if (count($value) == 5 && $value[4] != 1) { // rgba
+ return 'rgba('.$r.', '.$g.', '.$b.', '.$value[4].')';
+ }
+
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
+
+ // Converting hex color to short notation (e.g. #003399 to #039)
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
+ $h = '#' . $h[1] . $h[3] . $h[5];
+ }
+
+ return $h;
+ case "number":
+ return round($value[1], $this->numberPrecision) . $value[2];
+ case "string":
+ return $value[1] . $this->compileStringContent($value) . $value[1];
+ case "function":
+ $args = !empty($value[2]) ? $this->compileValue($value[2]) : "";
+ return "$value[1]($args)";
+ case "list":
+ $value = $this->extractInterpolation($value);
+ if ($value[0] != "list") return $this->compileValue($value);
+
+ list(, $delim, $items) = $value;
+
+ $filtered = array();
+ foreach ($items as $item) {
+ if ($item[0] == "null") continue;
+ $filtered[] = $this->compileValue($item);
+ }
+
+ return implode("$delim ", $filtered);
+ case "interpolated": # node created by extractInterpolation
+ list(, $interpolate, $left, $right) = $value;
+ list(,, $whiteLeft, $whiteRight) = $interpolate;
+
+ $left = count($left[2]) > 0 ?
+ $this->compileValue($left).$whiteLeft : "";
+
+ $right = count($right[2]) > 0 ?
+ $whiteRight.$this->compileValue($right) : "";
+
+ return $left.$this->compileValue($interpolate).$right;
+
+ case "interpolate": # raw parse node
+ list(, $exp) = $value;
+
+ // strip quotes if it's a string
+ $reduced = $this->reduce($exp);
+ switch ($reduced[0]) {
+ case "string":
+ $reduced = array("keyword",
+ $this->compileStringContent($reduced));
+ break;
+ case "null":
+ $reduced = array("keyword", "");
+ }
+
+ return $this->compileValue($reduced);
+ case "null":
+ return "null";
+ default:
+ $this->throwError("unknown value type: $type");
+ }
+ }
+
+ protected function compileStringContent($string) {
+ $parts = array();
+ foreach ($string[2] as $part) {
+ if (is_array($part)) {
+ $parts[] = $this->compileValue($part);
+ } else {
+ $parts[] = $part;
+ }
+ }
+
+ return implode($parts);
+ }
+
+ // doesn't need to be recursive, compileValue will handle that
+ protected function extractInterpolation($list) {
+ $items = $list[2];
+ foreach ($items as $i => $item) {
+ if ($item[0] == "interpolate") {
+ $before = array("list", $list[1], array_slice($items, 0, $i));
+ $after = array("list", $list[1], array_slice($items, $i + 1));
+ return array("interpolated", $item, $before, $after);
+ }
+ }
+ return $list;
+ }
+
+ // find the final set of selectors
+ protected function multiplySelectors($env) {
+ $envs = array();
+ while (null !== $env) {
+ if (!empty($env->selectors)) {
+ $envs[] = $env;
+ }
+ $env = $env->parent;
+ };
+
+ $selectors = array();
+ $parentSelectors = array(array());
+ while ($env = array_pop($envs)) {
+ $selectors = array();
+ foreach ($env->selectors as $selector) {
+ foreach ($parentSelectors as $parent) {
+ $selectors[] = $this->joinSelectors($parent, $selector);
+ }
+ }
+ $parentSelectors = $selectors;
+ }
+
+ return $selectors;
+ }
+
+ // looks for & to replace, or append parent before child
+ protected function joinSelectors($parent, $child) {
+ $setSelf = false;
+ $out = array();
+ foreach ($child as $part) {
+ $newPart = array();
+ foreach ($part as $p) {
+ if ($p == self::$selfSelector) {
+ $setSelf = true;
+ foreach ($parent as $i => $parentPart) {
+ if ($i > 0) {
+ $out[] = $newPart;
+ $newPart = array();
+ }
+
+ foreach ($parentPart as $pp) {
+ $newPart[] = $pp;
+ }
+ }
+ } else {
+ $newPart[] = $p;
+ }
+ }
+
+ $out[] = $newPart;
+ }
+
+ return $setSelf ? $out : array_merge($parent, $child);
+ }
+
+ protected function multiplyMedia($env, $childQueries = null) {
+ if (!isset($env) ||
+ !empty($env->block->type) && $env->block->type != "media")
+ {
+ return $childQueries;
+ }
+
+ // plain old block, skip
+ if (empty($env->block->type)) {
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ $parentQueries = $env->block->queryList;
+ if ($childQueries == null) {
+ $childQueries = $parentQueries;
+ } else {
+ $originalQueries = $childQueries;
+ $childQueries = array();
+
+ foreach ($parentQueries as $parentQuery){
+ foreach ($originalQueries as $childQuery) {
+ $childQueries []= array_merge($parentQuery, $childQuery);
+ }
+ }
+ }
+
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ // convert something to list
+ protected function coerceList($item, $delim = ",") {
+ if (isset($item) && $item[0] == "list") {
+ return $item;
+ }
+
+ return array("list", $delim, !isset($item) ? array(): array($item));
+ }
+
+ protected function applyArguments($argDef, $argValues) {
+ $hasVariable = false;
+ $args = array();
+ foreach ($argDef as $i => $arg) {
+ list($name, $default, $isVariable) = $argDef[$i];
+ $args[$name] = array($i, $name, $default, $isVariable);
+ $hasVariable |= $isVariable;
+ }
+
+ $keywordArgs = array();
+ $deferredKeywordArgs = array();
+ $remaining = array();
+ // assign the keyword args
+ foreach ((array) $argValues as $arg) {
+ if (!empty($arg[0])) {
+ if (!isset($args[$arg[0][1]])) {
+ if ($hasVariable) {
+ $deferredKeywordArgs[$arg[0][1]] = $arg[1];
+ } else {
+ $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
+ }
+ } elseif ($args[$arg[0][1]][0] < count($remaining)) {
+ $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
+ } else {
+ $keywordArgs[$arg[0][1]] = $arg[1];
+ }
+ } elseif (count($keywordArgs)) {
+ $this->throwError('Positional arguments must come before keyword arguments.');
+ } elseif ($arg[2] == true) {
+ $val = $this->reduce($arg[1], true);
+ if ($val[0] == "list") {
+ foreach ($val[2] as $name => $item) {
+ if (!is_numeric($name)) {
+ $keywordArgs[$name] = $item;
+ } else {
+ $remaining[] = $item;
+ }
+ }
+ } else {
+ $remaining[] = $val;
+ }
+ } else {
+ $remaining[] = $arg[1];
+ }
+ }
+
+ foreach ($args as $arg) {
+ list($i, $name, $default, $isVariable) = $arg;
+ if ($isVariable) {
+ $val = array("list", ",", array());
+ for ($count = count($remaining); $i < $count; $i++) {
+ $val[2][] = $remaining[$i];
+ }
+ foreach ($deferredKeywordArgs as $itemName => $item) {
+ $val[2][$itemName] = $item;
+ }
+ } elseif (isset($remaining[$i])) {
+ $val = $remaining[$i];
+ } elseif (isset($keywordArgs[$name])) {
+ $val = $keywordArgs[$name];
+ } elseif (!empty($default)) {
+ $val = $default;
+ } else {
+ $this->throwError("Missing argument $name");
+ }
+
+ $this->set($name, $this->reduce($val, true), true);
+ }
+ }
+
+ protected function pushEnv($block=null) {
+ $env = new stdClass;
+ $env->parent = $this->env;
+ $env->store = array();
+ $env->block = $block;
+ $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
+
+ $this->env = $env;
+ return $env;
+ }
+
+ protected function normalizeName($name) {
+ return str_replace("-", "_", $name);
+ }
+
+ protected function getStoreEnv() {
+ return isset($this->storeEnv) ? $this->storeEnv : $this->env;
+ }
+
+ protected function set($name, $value, $shadow=false) {
+ $name = $this->normalizeName($name);
+
+ if ($shadow) {
+ $this->setRaw($name, $value);
+ } else {
+ $this->setExisting($name, $value);
+ }
+ }
+
+ protected function setExisting($name, $value, $env = null) {
+ if (!isset($env)) $env = $this->getStoreEnv();
+
+ if (isset($env->store[$name]) || !isset($env->parent)) {
+ $env->store[$name] = $value;
+ } else {
+ $this->setExisting($name, $value, $env->parent);
+ }
+ }
+
+ protected function setRaw($name, $value) {
+ $env = $this->getStoreEnv();
+ $env->store[$name] = $value;
+ }
+
+ public function get($name, $defaultValue = null, $env = null) {
+ $name = $this->normalizeName($name);
+
+ if (!isset($env)) $env = $this->getStoreEnv();
+ if (!isset($defaultValue)) $defaultValue = self::$defaultValue;
+
+ if (isset($env->store[$name])) {
+ return $env->store[$name];
+ } elseif (isset($env->parent)) {
+ return $this->get($name, $defaultValue, $env->parent);
+ }
+
+ return $defaultValue; // found nothing
+ }
+
+ protected function injectVariables(array $args)
+ {
+ if (empty($args)) {
+ return;
+ }
+
+ $parser = new scss_parser(__METHOD__, false);
+
+ foreach ($args as $name => $strValue) {
+ if ($name[0] === '$') {
+ $name = substr($name, 1);
+ }
+
+ $parser->env = null;
+ $parser->count = 0;
+ $parser->buffer = (string) $strValue;
+ $parser->inParens = false;
+ $parser->eatWhiteDefault = true;
+ $parser->insertComments = true;
+
+ if ( ! $parser->valueList($value)) {
+ throw new Exception("failed to parse passed in variable $name: $strValue");
+ }
+
+ $this->set($name, $value);
+ }
+ }
+
+ /**
+ * Set variables
+ *
+ * @param array $variables
+ */
+ public function setVariables(array $variables)
+ {
+ $this->registeredVars = array_merge($this->registeredVars, $variables);
+ }
+
+ /**
+ * Unset variable
+ *
+ * @param string $name
+ */
+ public function unsetVariable($name)
+ {
+ unset($this->registeredVars[$name]);
+ }
+
+ protected function popEnv() {
+ $env = $this->env;
+ $this->env = $this->env->parent;
+ return $env;
+ }
+
+ public function getParsedFiles() {
+ return $this->parsedFiles;
+ }
+
+ public function addImportPath($path) {
+ $this->importPaths[] = $path;
+ }
+
+ public function setImportPaths($path) {
+ $this->importPaths = (array)$path;
+ }
+
+ public function setNumberPrecision($numberPrecision) {
+ $this->numberPrecision = $numberPrecision;
+ }
+
+ public function setFormatter($formatterName) {
+ $this->formatter = $formatterName;
+ }
+
+ public function registerFunction($name, $func) {
+ $this->userFunctions[$this->normalizeName($name)] = $func;
+ }
+
+ public function unregisterFunction($name) {
+ unset($this->userFunctions[$this->normalizeName($name)]);
+ }
+
+ protected function importFile($path, $out) {
+ // see if tree is cached
+ $realPath = realpath($path);
+ if (isset($this->importCache[$realPath])) {
+ $tree = $this->importCache[$realPath];
+ } else {
+ $code = file_get_contents($path);
+ $parser = new scss_parser($path, false);
+ $tree = $parser->parse($code);
+ $this->parsedFiles[] = $path;
+
+ $this->importCache[$realPath] = $tree;
+ }
+
+ $pi = pathinfo($path);
+ array_unshift($this->importPaths, $pi['dirname']);
+ $this->compileChildren($tree->children, $out);
+ array_shift($this->importPaths);
+ }
+
+ // results the file path for an import url if it exists
+ public function findImport($url) {
+ $urls = array();
+
+ // for "normal" scss imports (ignore vanilla css and external requests)
+ if (!preg_match('/\.css|^http:\/\/$/', $url)) {
+ // try both normal and the _partial filename
+ $urls = array($url, preg_replace('/[^\/]+$/', '_\0', $url));
+ }
+
+ foreach ($this->importPaths as $dir) {
+ if (is_string($dir)) {
+ // check urls for normal import paths
+ foreach ($urls as $full) {
+ $full = $dir .
+ (!empty($dir) && substr($dir, -1) != '/' ? '/' : '') .
+ $full;
+
+ if ($this->fileExists($file = $full.'.scss') ||
+ $this->fileExists($file = $full))
+ {
+ return $file;
+ }
+ }
+ } else {
+ // check custom callback for import path
+ $file = call_user_func($dir,$url,$this);
+ if ($file !== null) {
+ return $file;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ protected function fileExists($name) {
+ return is_file($name);
+ }
+
+ protected function callBuiltin($name, $args, &$returnValue) {
+ // try a lib function
+ $name = $this->normalizeName($name);
+ $libName = "lib_".$name;
+ $f = array($this, $libName);
+ if (is_callable($f)) {
+ $prototype = isset(self::$$libName) ? self::$$libName : null;
+ $sorted = $this->sortArgs($prototype, $args);
+ foreach ($sorted as &$val) {
+ $val = $this->reduce($val, true);
+ }
+ $returnValue = call_user_func($f, $sorted, $this);
+ } elseif (isset($this->userFunctions[$name])) {
+ // see if we can find a user function
+ $fn = $this->userFunctions[$name];
+
+ foreach ($args as &$val) {
+ $val = $this->reduce($val[1], true);
+ }
+
+ $returnValue = call_user_func($fn, $args, $this);
+ }
+
+ if (isset($returnValue)) {
+ // coerce a php value into a scss one
+ if (is_numeric($returnValue)) {
+ $returnValue = array('number', $returnValue, "");
+ } elseif (is_bool($returnValue)) {
+ $returnValue = $returnValue ? self::$true : self::$false;
+ } elseif (!is_array($returnValue)) {
+ $returnValue = array('keyword', $returnValue);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // sorts any keyword arguments
+ // TODO: merge with apply arguments
+ protected function sortArgs($prototype, $args) {
+ $keyArgs = array();
+ $posArgs = array();
+
+ foreach ($args as $arg) {
+ list($key, $value) = $arg;
+ $key = $key[1];
+ if (empty($key)) {
+ $posArgs[] = $value;
+ } else {
+ $keyArgs[$key] = $value;
+ }
+ }
+
+ if (!isset($prototype)) return $posArgs;
+
+ $finalArgs = array();
+ foreach ($prototype as $i => $names) {
+ if (isset($posArgs[$i])) {
+ $finalArgs[] = $posArgs[$i];
+ continue;
+ }
+
+ $set = false;
+ foreach ((array)$names as $name) {
+ if (isset($keyArgs[$name])) {
+ $finalArgs[] = $keyArgs[$name];
+ $set = true;
+ break;
+ }
+ }
+
+ if (!$set) {
+ $finalArgs[] = null;
+ }
+ }
+
+ return $finalArgs;
+ }
+
+ protected function coerceForExpression($value) {
+ if ($color = $this->coerceColor($value)) {
+ return $color;
+ }
+
+ return $value;
+ }
+
+ protected function coerceColor($value) {
+ switch ($value[0]) {
+ case "color": return $value;
+ case "keyword":
+ $name = $value[1];
+ if (isset(self::$cssColors[$name])) {
+ $rgba = explode(',', self::$cssColors[$name]);
+ return isset($rgba[3])
+ ? array('color', (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3])
+ : array('color', (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]);
+ }
+ return null;
+ }
+
+ return null;
+ }
+
+ protected function coerceString($value) {
+ switch ($value[0]) {
+ case "string":
+ return $value;
+ case "keyword":
+ return array("string", "", array($value[1]));
+ }
+ return null;
+ }
+
+ public function assertList($value) {
+ if ($value[0] != "list")
+ $this->throwError("expecting list");
+ return $value;
+ }
+
+ public function assertColor($value) {
+ if ($color = $this->coerceColor($value)) return $color;
+ $this->throwError("expecting color");
+ }
+
+ public function assertNumber($value) {
+ if ($value[0] != "number")
+ $this->throwError("expecting number");
+ return $value[1];
+ }
+
+ protected function coercePercent($value) {
+ if ($value[0] == "number") {
+ if ($value[2] == "%") {
+ return $value[1] / 100;
+ }
+ return $value[1];
+ }
+ return 0;
+ }
+
+ // make sure a color's components don't go out of bounds
+ protected function fixColor($c) {
+ foreach (range(1, 3) as $i) {
+ if ($c[$i] < 0) $c[$i] = 0;
+ if ($c[$i] > 255) $c[$i] = 255;
+ }
+
+ return $c;
+ }
+
+ public function toHSL($red, $green, $blue) {
+ $min = min($red, $green, $blue);
+ $max = max($red, $green, $blue);
+
+ $l = $min + $max;
+
+ if ($min == $max) {
+ $s = $h = 0;
+ } else {
+ $d = $max - $min;
+
+ if ($l < 255)
+ $s = $d / $l;
+ else
+ $s = $d / (510 - $l);
+
+ if ($red == $max)
+ $h = 60 * ($green - $blue) / $d;
+ elseif ($green == $max)
+ $h = 60 * ($blue - $red) / $d + 120;
+ elseif ($blue == $max)
+ $h = 60 * ($red - $green) / $d + 240;
+ }
+
+ return array('hsl', fmod($h, 360), $s * 100, $l / 5.1);
+ }
+
+ public function hueToRGB($m1, $m2, $h) {
+ if ($h < 0)
+ $h += 1;
+ elseif ($h > 1)
+ $h -= 1;
+
+ if ($h * 6 < 1)
+ return $m1 + ($m2 - $m1) * $h * 6;
+
+ if ($h * 2 < 1)
+ return $m2;
+
+ if ($h * 3 < 2)
+ return $m1 + ($m2 - $m1) * (2/3 - $h) * 6;
+
+ return $m1;
+ }
+
+ // H from 0 to 360, S and L from 0 to 100
+ public function toRGB($hue, $saturation, $lightness) {
+ if ($hue < 0) {
+ $hue += 360;
+ }
+
+ $h = $hue / 360;
+ $s = min(100, max(0, $saturation)) / 100;
+ $l = min(100, max(0, $lightness)) / 100;
+
+ $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s;
+ $m1 = $l * 2 - $m2;
+
+ $r = $this->hueToRGB($m1, $m2, $h + 1/3) * 255;
+ $g = $this->hueToRGB($m1, $m2, $h) * 255;
+ $b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255;
+
+ $out = array('color', $r, $g, $b);
+ return $out;
+ }
+
+ // Built in functions
+
+ protected static $lib_if = array("condition", "if-true", "if-false");
+ protected function lib_if($args) {
+ list($cond,$t, $f) = $args;
+ if (!$this->isTruthy($cond)) return $f;
+ return $t;
+ }
+
+ protected static $lib_index = array("list", "value");
+ protected function lib_index($args) {
+ list($list, $value) = $args;
+ $list = $this->assertList($list);
+
+ $values = array();
+ foreach ($list[2] as $item) {
+ $values[] = $this->normalizeValue($item);
+ }
+ $key = array_search($this->normalizeValue($value), $values);
+
+ return false === $key ? false : $key + 1;
+ }
+
+ protected static $lib_rgb = array("red", "green", "blue");
+ protected function lib_rgb($args) {
+ list($r,$g,$b) = $args;
+ return array("color", $r[1], $g[1], $b[1]);
+ }
+
+ protected static $lib_rgba = array(
+ array("red", "color"),
+ "green", "blue", "alpha");
+ protected function lib_rgba($args) {
+ if ($color = $this->coerceColor($args[0])) {
+ $num = !isset($args[1]) ? $args[3] : $args[1];
+ $alpha = $this->assertNumber($num);
+ $color[4] = $alpha;
+ return $color;
+ }
+
+ list($r,$g,$b, $a) = $args;
+ return array("color", $r[1], $g[1], $b[1], $a[1]);
+ }
+
+ // helper function for adjust_color, change_color, and scale_color
+ protected function alter_color($args, $fn) {
+ $color = $this->assertColor($args[0]);
+
+ foreach (array(1,2,3,7) as $i) {
+ if (isset($args[$i])) {
+ $val = $this->assertNumber($args[$i]);
+ $ii = $i == 7 ? 4 : $i; // alpha
+ $color[$ii] =
+ $this->$fn(isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
+ }
+ }
+
+ if (isset($args[4]) || isset($args[5]) || isset($args[6])) {
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ foreach (array(4,5,6) as $i) {
+ if (isset($args[$i])) {
+ $val = $this->assertNumber($args[$i]);
+ $hsl[$i - 3] = $this->$fn($hsl[$i - 3], $val, $i);
+ }
+ }
+
+ $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
+ if (isset($color[4])) $rgb[4] = $color[4];
+ $color = $rgb;
+ }
+
+ return $color;
+ }
+
+ protected static $lib_adjust_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function adjust_color_helper($base, $alter, $i) {
+ return $base += $alter;
+ }
+ protected function lib_adjust_color($args) {
+ return $this->alter_color($args, "adjust_color_helper");
+ }
+
+ protected static $lib_change_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function change_color_helper($base, $alter, $i) {
+ return $alter;
+ }
+ protected function lib_change_color($args) {
+ return $this->alter_color($args, "change_color_helper");
+ }
+
+ protected static $lib_scale_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function scale_color_helper($base, $scale, $i) {
+ // 1,2,3 - rgb
+ // 4, 5, 6 - hsl
+ // 7 - a
+ switch ($i) {
+ case 1:
+ case 2:
+ case 3:
+ $max = 255; break;
+ case 4:
+ $max = 360; break;
+ case 7:
+ $max = 1; break;
+ default:
+ $max = 100;
+ }
+
+ $scale = $scale / 100;
+ if ($scale < 0) {
+ return $base * $scale + $base;
+ } else {
+ return ($max - $base) * $scale + $base;
+ }
+ }
+ protected function lib_scale_color($args) {
+ return $this->alter_color($args, "scale_color_helper");
+ }
+
+ protected static $lib_ie_hex_str = array("color");
+ protected function lib_ie_hex_str($args) {
+ $color = $this->coerceColor($args[0]);
+ $color[4] = isset($color[4]) ? round(255*$color[4]) : 255;
+
+ return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]);
+ }
+
+ protected static $lib_red = array("color");
+ protected function lib_red($args) {
+ $color = $this->coerceColor($args[0]);
+ return $color[1];
+ }
+
+ protected static $lib_green = array("color");
+ protected function lib_green($args) {
+ $color = $this->coerceColor($args[0]);
+ return $color[2];
+ }
+
+ protected static $lib_blue = array("color");
+ protected function lib_blue($args) {
+ $color = $this->coerceColor($args[0]);
+ return $color[3];
+ }
+
+ protected static $lib_alpha = array("color");
+ protected function lib_alpha($args) {
+ if ($color = $this->coerceColor($args[0])) {
+ return isset($color[4]) ? $color[4] : 1;
+ }
+
+ // this might be the IE function, so return value unchanged
+ return null;
+ }
+
+ protected static $lib_opacity = array("color");
+ protected function lib_opacity($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ return $this->lib_alpha($args);
+ }
+
+ // mix two colors
+ protected static $lib_mix = array("color-1", "color-2", "weight");
+ protected function lib_mix($args) {
+ list($first, $second, $weight) = $args;
+ $first = $this->assertColor($first);
+ $second = $this->assertColor($second);
+
+ if (!isset($weight)) {
+ $weight = 0.5;
+ } else {
+ $weight = $this->coercePercent($weight);
+ }
+
+ $firstAlpha = isset($first[4]) ? $first[4] : 1;
+ $secondAlpha = isset($second[4]) ? $second[4] : 1;
+
+ $w = $weight * 2 - 1;
+ $a = $firstAlpha - $secondAlpha;
+
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
+ $w2 = 1.0 - $w1;
+
+ $new = array('color',
+ $w1 * $first[1] + $w2 * $second[1],
+ $w1 * $first[2] + $w2 * $second[2],
+ $w1 * $first[3] + $w2 * $second[3],
+ );
+
+ if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
+ $new[] = $firstAlpha * $weight + $secondAlpha * ($weight - 1);
+ }
+
+ return $this->fixColor($new);
+ }
+
+ protected static $lib_hsl = array("hue", "saturation", "lightness");
+ protected function lib_hsl($args) {
+ list($h, $s, $l) = $args;
+ return $this->toRGB($h[1], $s[1], $l[1]);
+ }
+
+ protected static $lib_hsla = array("hue", "saturation",
+ "lightness", "alpha");
+ protected function lib_hsla($args) {
+ list($h, $s, $l, $a) = $args;
+ $color = $this->toRGB($h[1], $s[1], $l[1]);
+ $color[4] = $a[1];
+ return $color;
+ }
+
+ protected static $lib_hue = array("color");
+ protected function lib_hue($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[1], "deg");
+ }
+
+ protected static $lib_saturation = array("color");
+ protected function lib_saturation($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[2], "%");
+ }
+
+ protected static $lib_lightness = array("color");
+ protected function lib_lightness($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[3], "%");
+ }
+
+ protected function adjustHsl($color, $idx, $amount) {
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ $hsl[$idx] += $amount;
+ $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
+ if (isset($color[4])) $out[4] = $color[4];
+ return $out;
+ }
+
+ protected static $lib_adjust_hue = array("color", "degrees");
+ protected function lib_adjust_hue($args) {
+ $color = $this->assertColor($args[0]);
+ $degrees = $this->assertNumber($args[1]);
+ return $this->adjustHsl($color, 1, $degrees);
+ }
+
+ protected static $lib_lighten = array("color", "amount");
+ protected function lib_lighten($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 3, $amount);
+ }
+
+ protected static $lib_darken = array("color", "amount");
+ protected function lib_darken($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 3, -$amount);
+ }
+
+ protected static $lib_saturate = array("color", "amount");
+ protected function lib_saturate($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ $color = $this->assertColor($value);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 2, $amount);
+ }
+
+ protected static $lib_desaturate = array("color", "amount");
+ protected function lib_desaturate($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 2, -$amount);
+ }
+
+ protected static $lib_grayscale = array("color");
+ protected function lib_grayscale($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ return $this->adjustHsl($this->assertColor($value), 2, -100);
+ }
+
+ protected static $lib_complement = array("color");
+ protected function lib_complement($args) {
+ return $this->adjustHsl($this->assertColor($args[0]), 1, 180);
+ }
+
+ protected static $lib_invert = array("color");
+ protected function lib_invert($args) {
+ $value = $args[0];
+ if ($value[0] === 'number') return null;
+ $color = $this->assertColor($value);
+ $color[1] = 255 - $color[1];
+ $color[2] = 255 - $color[2];
+ $color[3] = 255 - $color[3];
+ return $color;
+ }
+
+ // increases opacity by amount
+ protected static $lib_opacify = array("color", "amount");
+ protected function lib_opacify($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = $this->coercePercent($args[1]);
+
+ $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount;
+ $color[4] = min(1, max(0, $color[4]));
+ return $color;
+ }
+
+ protected static $lib_fade_in = array("color", "amount");
+ protected function lib_fade_in($args) {
+ return $this->lib_opacify($args);
+ }
+
+ // decreases opacity by amount
+ protected static $lib_transparentize = array("color", "amount");
+ protected function lib_transparentize($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = $this->coercePercent($args[1]);
+
+ $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount;
+ $color[4] = min(1, max(0, $color[4]));
+ return $color;
+ }
+
+ protected static $lib_fade_out = array("color", "amount");
+ protected function lib_fade_out($args) {
+ return $this->lib_transparentize($args);
+ }
+
+ protected static $lib_unquote = array("string");
+ protected function lib_unquote($args) {
+ $str = $args[0];
+ if ($str[0] == "string") $str[1] = "";
+ return $str;
+ }
+
+ protected static $lib_quote = array("string");
+ protected function lib_quote($args) {
+ $value = $args[0];
+ if ($value[0] == "string" && !empty($value[1]))
+ return $value;
+ return array("string", '"', array($value));
+ }
+
+ protected static $lib_percentage = array("value");
+ protected function lib_percentage($args) {
+ return array("number",
+ $this->coercePercent($args[0]) * 100,
+ "%");
+ }
+
+ protected static $lib_round = array("value");
+ protected function lib_round($args) {
+ $num = $args[0];
+ $num[1] = round($num[1]);
+ return $num;
+ }
+
+ protected static $lib_floor = array("value");
+ protected function lib_floor($args) {
+ $num = $args[0];
+ $num[1] = floor($num[1]);
+ return $num;
+ }
+
+ protected static $lib_ceil = array("value");
+ protected function lib_ceil($args) {
+ $num = $args[0];
+ $num[1] = ceil($num[1]);
+ return $num;
+ }
+
+ protected static $lib_abs = array("value");
+ protected function lib_abs($args) {
+ $num = $args[0];
+ $num[1] = abs($num[1]);
+ return $num;
+ }
+
+ protected function lib_min($args) {
+ $numbers = $this->getNormalizedNumbers($args);
+ $min = null;
+ foreach ($numbers as $key => $number) {
+ if (null === $min || $number[1] <= $min[1]) {
+ $min = array($key, $number[1]);
+ }
+ }
+
+ return $args[$min[0]];
+ }
+
+ protected function lib_max($args) {
+ $numbers = $this->getNormalizedNumbers($args);
+ $max = null;
+ foreach ($numbers as $key => $number) {
+ if (null === $max || $number[1] >= $max[1]) {
+ $max = array($key, $number[1]);
+ }
+ }
+
+ return $args[$max[0]];
+ }
+
+ protected function getNormalizedNumbers($args) {
+ $unit = null;
+ $originalUnit = null;
+ $numbers = array();
+ foreach ($args as $key => $item) {
+ if ('number' != $item[0]) {
+ $this->throwError("%s is not a number", $item[0]);
+ }
+ $number = $this->normalizeNumber($item);
+
+ if (null === $unit) {
+ $unit = $number[2];
+ $originalUnit = $item[2];
+ } elseif ($unit !== $number[2]) {
+ $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item[2]);
+ }
+
+ $numbers[$key] = $number;
+ }
+
+ return $numbers;
+ }
+
+ protected static $lib_length = array("list");
+ protected function lib_length($args) {
+ $list = $this->coerceList($args[0]);
+ return count($list[2]);
+ }
+
+ protected static $lib_nth = array("list", "n");
+ protected function lib_nth($args) {
+ $list = $this->coerceList($args[0]);
+ $n = $this->assertNumber($args[1]) - 1;
+ return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
+ }
+
+ protected function listSeparatorForJoin($list1, $sep) {
+ if (!isset($sep)) return $list1[1];
+ switch ($this->compileValue($sep)) {
+ case "comma":
+ return ",";
+ case "space":
+ return "";
+ default:
+ return $list1[1];
+ }
+ }
+
+ protected static $lib_join = array("list1", "list2", "separator");
+ protected function lib_join($args) {
+ list($list1, $list2, $sep) = $args;
+ $list1 = $this->coerceList($list1, " ");
+ $list2 = $this->coerceList($list2, " ");
+ $sep = $this->listSeparatorForJoin($list1, $sep);
+ return array("list", $sep, array_merge($list1[2], $list2[2]));
+ }
+
+ protected static $lib_append = array("list", "val", "separator");
+ protected function lib_append($args) {
+ list($list1, $value, $sep) = $args;
+ $list1 = $this->coerceList($list1, " ");
+ $sep = $this->listSeparatorForJoin($list1, $sep);
+ return array("list", $sep, array_merge($list1[2], array($value)));
+ }
+
+ protected function lib_zip($args) {
+ foreach ($args as $arg) {
+ $this->assertList($arg);
+ }
+
+ $lists = array();
+ $firstList = array_shift($args);
+ foreach ($firstList[2] as $key => $item) {
+ $list = array("list", "", array($item));
+ foreach ($args as $arg) {
+ if (isset($arg[2][$key])) {
+ $list[2][] = $arg[2][$key];
+ } else {
+ break 2;
+ }
+ }
+ $lists[] = $list;
+ }
+
+ return array("list", ",", $lists);
+ }
+
+ protected static $lib_type_of = array("value");
+ protected function lib_type_of($args) {
+ $value = $args[0];
+ switch ($value[0]) {
+ case "keyword":
+ if ($value == self::$true || $value == self::$false) {
+ return "bool";
+ }
+
+ if ($this->coerceColor($value)) {
+ return "color";
+ }
+
+ return "string";
+ default:
+ return $value[0];
+ }
+ }
+
+ protected static $lib_unit = array("number");
+ protected function lib_unit($args) {
+ $num = $args[0];
+ if ($num[0] == "number") {
+ return array("string", '"', array($num[2]));
+ }
+ return "";
+ }
+
+ protected static $lib_unitless = array("number");
+ protected function lib_unitless($args) {
+ $value = $args[0];
+ return $value[0] == "number" && empty($value[2]);
+ }
+
+ protected static $lib_comparable = array("number-1", "number-2");
+ protected function lib_comparable($args) {
+ list($number1, $number2) = $args;
+ if (!isset($number1[0]) || $number1[0] != "number" || !isset($number2[0]) || $number2[0] != "number") {
+ $this->throwError('Invalid argument(s) for "comparable"');
+ }
+
+ $number1 = $this->normalizeNumber($number1);
+ $number2 = $this->normalizeNumber($number2);
+
+ return $number1[2] == $number2[2] || $number1[2] == "" || $number2[2] == "";
+ }
+
+ /**
+ * Workaround IE7's content counter bug.
+ *
+ * @param array $args
+ */
+ protected function lib_counter($args) {
+ $list = array_map(array($this, 'compileValue'), $args);
+ return array('string', '', array('counter(' . implode(',', $list) . ')'));
+ }
+
+ public function throwError($msg = null) {
+ if (func_num_args() > 1) {
+ $msg = call_user_func_array("sprintf", func_get_args());
+ }
+
+ if ($this->sourcePos >= 0 && isset($this->sourceParser)) {
+ $this->sourceParser->throwParseError($msg, $this->sourcePos);
+ }
+
+ throw new Exception($msg);
+ }
+
+ /**
+ * CSS Colors
+ *
+ * @see http://www.w3.org/TR/css3-color
+ */
+ static protected $cssColors = array(
+ 'aliceblue' => '240,248,255',
+ 'antiquewhite' => '250,235,215',
+ 'aqua' => '0,255,255',
+ 'aquamarine' => '127,255,212',
+ 'azure' => '240,255,255',
+ 'beige' => '245,245,220',
+ 'bisque' => '255,228,196',
+ 'black' => '0,0,0',
+ 'blanchedalmond' => '255,235,205',
+ 'blue' => '0,0,255',
+ 'blueviolet' => '138,43,226',
+ 'brown' => '165,42,42',
+ 'burlywood' => '222,184,135',
+ 'cadetblue' => '95,158,160',
+ 'chartreuse' => '127,255,0',
+ 'chocolate' => '210,105,30',
+ 'coral' => '255,127,80',
+ 'cornflowerblue' => '100,149,237',
+ 'cornsilk' => '255,248,220',
+ 'crimson' => '220,20,60',
+ 'cyan' => '0,255,255',
+ 'darkblue' => '0,0,139',
+ 'darkcyan' => '0,139,139',
+ 'darkgoldenrod' => '184,134,11',
+ 'darkgray' => '169,169,169',
+ 'darkgreen' => '0,100,0',
+ 'darkgrey' => '169,169,169',
+ 'darkkhaki' => '189,183,107',
+ 'darkmagenta' => '139,0,139',
+ 'darkolivegreen' => '85,107,47',
+ 'darkorange' => '255,140,0',
+ 'darkorchid' => '153,50,204',
+ 'darkred' => '139,0,0',
+ 'darksalmon' => '233,150,122',
+ 'darkseagreen' => '143,188,143',
+ 'darkslateblue' => '72,61,139',
+ 'darkslategray' => '47,79,79',
+ 'darkslategrey' => '47,79,79',
+ 'darkturquoise' => '0,206,209',
+ 'darkviolet' => '148,0,211',
+ 'deeppink' => '255,20,147',
+ 'deepskyblue' => '0,191,255',
+ 'dimgray' => '105,105,105',
+ 'dimgrey' => '105,105,105',
+ 'dodgerblue' => '30,144,255',
+ 'firebrick' => '178,34,34',
+ 'floralwhite' => '255,250,240',
+ 'forestgreen' => '34,139,34',
+ 'fuchsia' => '255,0,255',
+ 'gainsboro' => '220,220,220',
+ 'ghostwhite' => '248,248,255',
+ 'gold' => '255,215,0',
+ 'goldenrod' => '218,165,32',
+ 'gray' => '128,128,128',
+ 'green' => '0,128,0',
+ 'greenyellow' => '173,255,47',
+ 'grey' => '128,128,128',
+ 'honeydew' => '240,255,240',
+ 'hotpink' => '255,105,180',
+ 'indianred' => '205,92,92',
+ 'indigo' => '75,0,130',
+ 'ivory' => '255,255,240',
+ 'khaki' => '240,230,140',
+ 'lavender' => '230,230,250',
+ 'lavenderblush' => '255,240,245',
+ 'lawngreen' => '124,252,0',
+ 'lemonchiffon' => '255,250,205',
+ 'lightblue' => '173,216,230',
+ 'lightcoral' => '240,128,128',
+ 'lightcyan' => '224,255,255',
+ 'lightgoldenrodyellow' => '250,250,210',
+ 'lightgray' => '211,211,211',
+ 'lightgreen' => '144,238,144',
+ 'lightgrey' => '211,211,211',
+ 'lightpink' => '255,182,193',
+ 'lightsalmon' => '255,160,122',
+ 'lightseagreen' => '32,178,170',
+ 'lightskyblue' => '135,206,250',
+ 'lightslategray' => '119,136,153',
+ 'lightslategrey' => '119,136,153',
+ 'lightsteelblue' => '176,196,222',
+ 'lightyellow' => '255,255,224',
+ 'lime' => '0,255,0',
+ 'limegreen' => '50,205,50',
+ 'linen' => '250,240,230',
+ 'magenta' => '255,0,255',
+ 'maroon' => '128,0,0',
+ 'mediumaquamarine' => '102,205,170',
+ 'mediumblue' => '0,0,205',
+ 'mediumorchid' => '186,85,211',
+ 'mediumpurple' => '147,112,219',
+ 'mediumseagreen' => '60,179,113',
+ 'mediumslateblue' => '123,104,238',
+ 'mediumspringgreen' => '0,250,154',
+ 'mediumturquoise' => '72,209,204',
+ 'mediumvioletred' => '199,21,133',
+ 'midnightblue' => '25,25,112',
+ 'mintcream' => '245,255,250',
+ 'mistyrose' => '255,228,225',
+ 'moccasin' => '255,228,181',
+ 'navajowhite' => '255,222,173',
+ 'navy' => '0,0,128',
+ 'oldlace' => '253,245,230',
+ 'olive' => '128,128,0',
+ 'olivedrab' => '107,142,35',
+ 'orange' => '255,165,0',
+ 'orangered' => '255,69,0',
+ 'orchid' => '218,112,214',
+ 'palegoldenrod' => '238,232,170',
+ 'palegreen' => '152,251,152',
+ 'paleturquoise' => '175,238,238',
+ 'palevioletred' => '219,112,147',
+ 'papayawhip' => '255,239,213',
+ 'peachpuff' => '255,218,185',
+ 'peru' => '205,133,63',
+ 'pink' => '255,192,203',
+ 'plum' => '221,160,221',
+ 'powderblue' => '176,224,230',
+ 'purple' => '128,0,128',
+ 'red' => '255,0,0',
+ 'rosybrown' => '188,143,143',
+ 'royalblue' => '65,105,225',
+ 'saddlebrown' => '139,69,19',
+ 'salmon' => '250,128,114',
+ 'sandybrown' => '244,164,96',
+ 'seagreen' => '46,139,87',
+ 'seashell' => '255,245,238',
+ 'sienna' => '160,82,45',
+ 'silver' => '192,192,192',
+ 'skyblue' => '135,206,235',
+ 'slateblue' => '106,90,205',
+ 'slategray' => '112,128,144',
+ 'slategrey' => '112,128,144',
+ 'snow' => '255,250,250',
+ 'springgreen' => '0,255,127',
+ 'steelblue' => '70,130,180',
+ 'tan' => '210,180,140',
+ 'teal' => '0,128,128',
+ 'thistle' => '216,191,216',
+ 'tomato' => '255,99,71',
+ 'transparent' => '0,0,0,0',
+ 'turquoise' => '64,224,208',
+ 'violet' => '238,130,238',
+ 'wheat' => '245,222,179',
+ 'white' => '255,255,255',
+ 'whitesmoke' => '245,245,245',
+ 'yellow' => '255,255,0',
+ 'yellowgreen' => '154,205,50'
+ );
+}
+
+/**
+ * SCSS parser
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_parser {
+ static protected $precedence = array(
+ "or" => 0,
+ "and" => 1,
+
+ '==' => 2,
+ '!=' => 2,
+ '<=' => 2,
+ '>=' => 2,
+ '=' => 2,
+ '<' => 3,
+ '>' => 2,
+
+ '+' => 3,
+ '-' => 3,
+ '*' => 4,
+ '/' => 4,
+ '%' => 4,
+ );
+
+ static protected $operators = array("+", "-", "*", "/", "%",
+ "==", "!=", "<=", ">=", "<", ">", "and", "or");
+
+ static protected $operatorStr;
+ static protected $whitePattern;
+ static protected $commentMulti;
+
+ static protected $commentSingle = "//";
+ static protected $commentMultiLeft = "/*";
+ static protected $commentMultiRight = "*/";
+
+ /**
+ * Constructor
+ *
+ * @param string $sourceName
+ * @param boolean $rootParser
+ */
+ public function __construct($sourceName = null, $rootParser = true) {
+ $this->sourceName = $sourceName;
+ $this->rootParser = $rootParser;
+
+ if (empty(self::$operatorStr)) {
+ self::$operatorStr = $this->makeOperatorStr(self::$operators);
+
+ $commentSingle = $this->preg_quote(self::$commentSingle);
+ $commentMultiLeft = $this->preg_quote(self::$commentMultiLeft);
+ $commentMultiRight = $this->preg_quote(self::$commentMultiRight);
+ self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
+ self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
+ }
+ }
+
+ static protected function makeOperatorStr($operators) {
+ return '('.implode('|', array_map(array('scss_parser','preg_quote'),
+ $operators)).')';
+ }
+
+ /**
+ * Parser buffer
+ *
+ * @param string $buffer;
+ *
+ * @return \StdClass
+ */
+ public function parse($buffer)
+ {
+ $this->count = 0;
+ $this->env = null;
+ $this->inParens = false;
+ $this->eatWhiteDefault = true;
+ $this->insertComments = true;
+ $this->buffer = $buffer;
+
+ $this->pushBlock(null); // root block
+ $this->whitespace();
+
+ while (false !== $this->parseChunk())
+ ;
+
+ if ($this->count != strlen($this->buffer)) {
+ $this->throwParseError();
+ }
+
+ if (!empty($this->env->parent)) {
+ $this->throwParseError("unclosed block");
+ }
+
+ $this->env->isRoot = true;
+
+ return $this->env;
+ }
+
+ /**
+ * Parse a single chunk off the head of the buffer and append it to the
+ * current parse environment.
+ *
+ * Returns false when the buffer is empty, or when there is an error.
+ *
+ * This function is called repeatedly until the entire document is
+ * parsed.
+ *
+ * This parser is most similar to a recursive descent parser. Single
+ * functions represent discrete grammatical rules for the language, and
+ * they are able to capture the text that represents those rules.
+ *
+ * Consider the function scssc::keyword(). (All parse functions are
+ * structured the same.)
+ *
+ * The function takes a single reference argument. When calling the
+ * function it will attempt to match a keyword on the head of the buffer.
+ * If it is successful, it will place the keyword in the referenced
+ * argument, advance the position in the buffer, and return true. If it
+ * fails then it won't advance the buffer and it will return false.
+ *
+ * All of these parse functions are powered by scssc::match(), which behaves
+ * the same way, but takes a literal regular expression. Sometimes it is
+ * more convenient to use match instead of creating a new function.
+ *
+ * Because of the format of the functions, to parse an entire string of
+ * grammatical rules, you can chain them together using &&.
+ *
+ * But, if some of the rules in the chain succeed before one fails, then
+ * the buffer position will be left at an invalid state. In order to
+ * avoid this, scssc::seek() is used to remember and set buffer positions.
+ *
+ * Before parsing a chain, use $s = $this->seek() to remember the current
+ * position into $s. Then if a chain fails, use $this->seek($s) to
+ * go back where we started.
+ *
+ * @return boolean
+ */
+ protected function parseChunk() {
+ $s = $this->seek();
+
+ // the directives
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
+ if ($this->literal("@media") && $this->mediaQueryList($mediaQueryList) && $this->literal("{")) {
+ $media = $this->pushSpecialBlock("media");
+ $media->queryList = $mediaQueryList[2];
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@mixin") &&
+ $this->keyword($mixinName) &&
+ ($this->argumentDef($args) || true) &&
+ $this->literal("{"))
+ {
+ $mixin = $this->pushSpecialBlock("mixin");
+ $mixin->name = $mixinName;
+ $mixin->args = $args;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@include") &&
+ $this->keyword($mixinName) &&
+ ($this->literal("(") &&
+ ($this->argValues($argValues) || true) &&
+ $this->literal(")") || true) &&
+ ($this->end() ||
+ $this->literal("{") && $hasBlock = true))
+ {
+ $child = array("include",
+ $mixinName, isset($argValues) ? $argValues : null, null);
+
+ if (!empty($hasBlock)) {
+ $include = $this->pushSpecialBlock("include");
+ $include->child = $child;
+ } else {
+ $this->append($child, $s);
+ }
+
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@import") &&
+ $this->valueList($importPath) &&
+ $this->end())
+ {
+ $this->append(array("import", $importPath), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@extend") &&
+ $this->selectors($selector) &&
+ $this->end())
+ {
+ $this->append(array("extend", $selector), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@function") &&
+ $this->keyword($fnName) &&
+ $this->argumentDef($args) &&
+ $this->literal("{"))
+ {
+ $func = $this->pushSpecialBlock("function");
+ $func->name = $fnName;
+ $func->args = $args;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@return") && $this->valueList($retVal) && $this->end()) {
+ $this->append(array("return", $retVal), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@each") &&
+ $this->variable($varName) &&
+ $this->literal("in") &&
+ $this->valueList($list) &&
+ $this->literal("{"))
+ {
+ $each = $this->pushSpecialBlock("each");
+ $each->var = $varName[1];
+ $each->list = $list;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@while") &&
+ $this->expression($cond) &&
+ $this->literal("{"))
+ {
+ $while = $this->pushSpecialBlock("while");
+ $while->cond = $cond;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@for") &&
+ $this->variable($varName) &&
+ $this->literal("from") &&
+ $this->expression($start) &&
+ ($this->literal("through") ||
+ ($forUntil = true && $this->literal("to"))) &&
+ $this->expression($end) &&
+ $this->literal("{"))
+ {
+ $for = $this->pushSpecialBlock("for");
+ $for->var = $varName[1];
+ $for->start = $start;
+ $for->end = $end;
+ $for->until = isset($forUntil);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@if") && $this->valueList($cond) && $this->literal("{")) {
+ $if = $this->pushSpecialBlock("if");
+ $if->cond = $cond;
+ $if->cases = array();
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if (($this->literal("@debug") || $this->literal("@warn")) &&
+ $this->valueList($value) &&
+ $this->end()) {
+ $this->append(array("debug", $value, $s), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@content") && $this->end()) {
+ $this->append(array("mixin_content"), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ $last = $this->last();
+ if (isset($last) && $last[0] == "if") {
+ list(, $if) = $last;
+ if ($this->literal("@else")) {
+ if ($this->literal("{")) {
+ $else = $this->pushSpecialBlock("else");
+ } elseif ($this->literal("if") && $this->valueList($cond) && $this->literal("{")) {
+ $else = $this->pushSpecialBlock("elseif");
+ $else->cond = $cond;
+ }
+
+ if (isset($else)) {
+ $else->dontAppend = true;
+ $if->cases[] = $else;
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ }
+
+ if ($this->literal("@charset") &&
+ $this->valueList($charset) && $this->end())
+ {
+ $this->append(array("charset", $charset), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // doesn't match built in directive, do generic one
+ if ($this->literal("@", false) && $this->keyword($dirName) &&
+ ($this->openString("{", $dirValue) || true) &&
+ $this->literal("{"))
+ {
+ $directive = $this->pushSpecialBlock("directive");
+ $directive->name = $dirName;
+ if (isset($dirValue)) $directive->value = $dirValue;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // property shortcut
+ // captures most properties before having to parse a selector
+ if ($this->keyword($name, false) &&
+ $this->literal(": ") &&
+ $this->valueList($value) &&
+ $this->end())
+ {
+ $name = array("string", "", array($name));
+ $this->append(array("assign", $name, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // variable assigns
+ if ($this->variable($name) &&
+ $this->literal(":") &&
+ $this->valueList($value) && $this->end())
+ {
+ // check for !default
+ $defaultVar = $value[0] == "list" && $this->stripDefault($value);
+ $this->append(array("assign", $name, $value, $defaultVar), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // misc
+ if ($this->literal("-->")) {
+ return true;
+ }
+
+ // opening css block
+ $oldComments = $this->insertComments;
+ $this->insertComments = false;
+ if ($this->selectors($selectors) && $this->literal("{")) {
+ $this->pushBlock($selectors);
+ $this->insertComments = $oldComments;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+ $this->insertComments = $oldComments;
+
+ // property assign, or nested assign
+ if ($this->propertyName($name) && $this->literal(":")) {
+ $foundSomething = false;
+ if ($this->valueList($value)) {
+ $this->append(array("assign", $name, $value), $s);
+ $foundSomething = true;
+ }
+
+ if ($this->literal("{")) {
+ $propBlock = $this->pushSpecialBlock("nestedprop");
+ $propBlock->prefix = $name;
+ $foundSomething = true;
+ } elseif ($foundSomething) {
+ $foundSomething = $this->end();
+ }
+
+ if ($foundSomething) {
+ return true;
+ }
+
+ $this->seek($s);
+ } else {
+ $this->seek($s);
+ }
+
+ // closing a block
+ if ($this->literal("}")) {
+ $block = $this->popBlock();
+ if (isset($block->type) && $block->type == "include") {
+ $include = $block->child;
+ unset($block->child);
+ $include[3] = $block;
+ $this->append($include, $s);
+ } elseif (empty($block->dontAppend)) {
+ $type = isset($block->type) ? $block->type : "block";
+ $this->append(array($type, $block), $s);
+ }
+ return true;
+ }
+
+ // extra stuff
+ if ($this->literal(";") ||
+ $this->literal("<!--"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function stripDefault(&$value) {
+ $def = end($value[2]);
+ if ($def[0] == "keyword" && $def[1] == "!default") {
+ array_pop($value[2]);
+ $value = $this->flattenList($value);
+ return true;
+ }
+
+ if ($def[0] == "list") {
+ return $this->stripDefault($value[2][count($value[2]) - 1]);
+ }
+
+ return false;
+ }
+
+ protected function literal($what, $eatWhitespace = null) {
+ if (!isset($eatWhitespace)) $eatWhitespace = $this->eatWhiteDefault;
+
+ // shortcut on single letter
+ if (!isset($what[1]) && isset($this->buffer[$this->count])) {
+ if ($this->buffer[$this->count] == $what) {
+ if (!$eatWhitespace) {
+ $this->count++;
+ return true;
+ }
+ // goes below...
+ } else {
+ return false;
+ }
+ }
+
+ return $this->match($this->preg_quote($what), $m, $eatWhitespace);
+ }
+
+ // tree builders
+
+ protected function pushBlock($selectors) {
+ $b = new stdClass;
+ $b->parent = $this->env; // not sure if we need this yet
+
+ $b->selectors = $selectors;
+ $b->children = array();
+
+ $this->env = $b;
+ return $b;
+ }
+
+ protected function pushSpecialBlock($type) {
+ $block = $this->pushBlock(null);
+ $block->type = $type;
+ return $block;
+ }
+
+ protected function popBlock() {
+ if (empty($this->env->parent)) {
+ $this->throwParseError("unexpected }");
+ }
+
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ unset($old->parent);
+ return $old;
+ }
+
+ protected function append($statement, $pos=null) {
+ if ($pos !== null) {
+ $statement[-1] = $pos;
+ if (!$this->rootParser) $statement[-2] = $this;
+ }
+ $this->env->children[] = $statement;
+ }
+
+ // last child that was appended
+ protected function last() {
+ $i = count($this->env->children) - 1;
+ if (isset($this->env->children[$i]))
+ return $this->env->children[$i];
+ }
+
+ // high level parsers (they return parts of ast)
+
+ protected function mediaQueryList(&$out) {
+ return $this->genericList($out, "mediaQuery", ",", false);
+ }
+
+ protected function mediaQuery(&$out) {
+ $s = $this->seek();
+
+ $expressions = null;
+ $parts = array();
+
+ if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->mixedKeyword($mediaType)) {
+ $prop = array("mediaType");
+ if (isset($only)) $prop[] = array("keyword", "only");
+ if (isset($not)) $prop[] = array("keyword", "not");
+ $media = array("list", "", array());
+ foreach ((array)$mediaType as $type) {
+ if (is_array($type)) {
+ $media[2][] = $type;
+ } else {
+ $media[2][] = array("keyword", $type);
+ }
+ }
+ $prop[] = $media;
+ $parts[] = $prop;
+ }
+
+ if (empty($parts) || $this->literal("and")) {
+ $this->genericList($expressions, "mediaExpression", "and", false);
+ if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function mediaExpression(&$out) {
+ $s = $this->seek();
+ $value = null;
+ if ($this->literal("(") &&
+ $this->expression($feature) &&
+ ($this->literal(":") && $this->expression($value) || true) &&
+ $this->literal(")"))
+ {
+ $out = array("mediaExp", $feature);
+ if ($value) $out[] = $value;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function argValues(&$out) {
+ if ($this->genericList($list, "argValue", ",", false)) {
+ $out = $list[2];
+ return true;
+ }
+ return false;
+ }
+
+ protected function argValue(&$out) {
+ $s = $this->seek();
+
+ $keyword = null;
+ if (!$this->variable($keyword) || !$this->literal(":")) {
+ $this->seek($s);
+ $keyword = null;
+ }
+
+ if ($this->genericList($value, "expression")) {
+ $out = array($keyword, $value, false);
+ $s = $this->seek();
+ if ($this->literal("...")) {
+ $out[2] = true;
+ } else {
+ $this->seek($s);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse list
+ *
+ * @param string $out
+ *
+ * @return boolean
+ */
+ public function valueList(&$out)
+ {
+ return $this->genericList($out, 'spaceList', ',');
+ }
+
+ protected function spaceList(&$out)
+ {
+ return $this->genericList($out, 'expression');
+ }
+
+ protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
+ $s = $this->seek();
+ $items = array();
+ while ($this->$parseItem($value)) {
+ $items[] = $value;
+ if ($delim) {
+ if (!$this->literal($delim)) break;
+ }
+ }
+
+ if (count($items) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($flatten && count($items) == 1) {
+ $out = $items[0];
+ } else {
+ $out = array("list", $delim, $items);
+ }
+
+ return true;
+ }
+
+ protected function expression(&$out) {
+ $s = $this->seek();
+
+ if ($this->literal("(")) {
+ if ($this->literal(")")) {
+ $out = array("list", "", array());
+ return true;
+ }
+
+ if ($this->valueList($out) && $this->literal(')') && $out[0] == "list") {
+ return true;
+ }
+
+ $this->seek($s);
+ }
+
+ if ($this->value($lhs)) {
+ $out = $this->expHelper($lhs, 0);
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function expHelper($lhs, $minP) {
+ $opstr = self::$operatorStr;
+
+ $ss = $this->seek();
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+ while ($this->match($opstr, $m) && self::$precedence[$m[1]] >= $minP) {
+ $whiteAfter = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ $op = $m[1];
+
+ // don't turn negative numbers into expressions
+ if ($op == "-" && $whiteBefore) {
+ if (!$whiteAfter) break;
+ }
+
+ if (!$this->value($rhs)) break;
+
+ // peek and see if rhs belongs to next operator
+ if ($this->peek($opstr, $next) && self::$precedence[$next[1]] > self::$precedence[$op]) {
+ $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
+ }
+
+ $lhs = array("exp", $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter);
+ $ss = $this->seek();
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+ }
+
+ $this->seek($ss);
+ return $lhs;
+ }
+
+ protected function value(&$out) {
+ $s = $this->seek();
+
+ if ($this->literal("not", false) && $this->whitespace() && $this->value($inner)) {
+ $out = array("unary", "not", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("+") && $this->value($inner)) {
+ $out = array("unary", "+", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // negation
+ if ($this->literal("-", false) &&
+ ($this->variable($inner) ||
+ $this->unit($inner) ||
+ $this->parenValue($inner)))
+ {
+ $out = array("unary", "-", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->parenValue($out)) return true;
+ if ($this->interpolation($out)) return true;
+ if ($this->variable($out)) return true;
+ if ($this->color($out)) return true;
+ if ($this->unit($out)) return true;
+ if ($this->string($out)) return true;
+ if ($this->func($out)) return true;
+ if ($this->progid($out)) return true;
+
+ if ($this->keyword($keyword)) {
+ if ($keyword == "null") {
+ $out = array("null");
+ } else {
+ $out = array("keyword", $keyword);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ // value wrappen in parentheses
+ protected function parenValue(&$out) {
+ $s = $this->seek();
+
+ $inParens = $this->inParens;
+ if ($this->literal("(") &&
+ ($this->inParens = true) && $this->expression($exp) &&
+ $this->literal(")"))
+ {
+ $out = $exp;
+ $this->inParens = $inParens;
+ return true;
+ } else {
+ $this->inParens = $inParens;
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ protected function progid(&$out) {
+ $s = $this->seek();
+ if ($this->literal("progid:", false) &&
+ $this->openString("(", $fn) &&
+ $this->literal("("))
+ {
+ $this->openString(")", $args, "(");
+ if ($this->literal(")")) {
+ $out = array("string", "", array(
+ "progid:", $fn, "(", $args, ")"
+ ));
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function func(&$func) {
+ $s = $this->seek();
+
+ if ($this->keyword($name, false) &&
+ $this->literal("("))
+ {
+ if ($name == "alpha" && $this->argumentList($args)) {
+ $func = array("function", $name, array("string", "", $args));
+ return true;
+ }
+
+ if ($name != "expression" && !preg_match("/^(-[a-z]+-)?calc$/", $name)) {
+ $ss = $this->seek();
+ if ($this->argValues($args) && $this->literal(")")) {
+ $func = array("fncall", $name, $args);
+ return true;
+ }
+ $this->seek($ss);
+ }
+
+ if (($this->openString(")", $str, "(") || true ) &&
+ $this->literal(")"))
+ {
+ $args = array();
+ if (!empty($str)) {
+ $args[] = array(null, array("string", "", array($str)));
+ }
+
+ $func = array("fncall", $name, $args);
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function argumentList(&$out) {
+ $s = $this->seek();
+ $this->literal("(");
+
+ $args = array();
+ while ($this->keyword($var)) {
+ $ss = $this->seek();
+
+ if ($this->literal("=") && $this->expression($exp)) {
+ $args[] = array("string", "", array($var."="));
+ $arg = $exp;
+ } else {
+ break;
+ }
+
+ $args[] = $arg;
+
+ if (!$this->literal(",")) break;
+
+ $args[] = array("string", "", array(", "));
+ }
+
+ if (!$this->literal(")") || !count($args)) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $args;
+ return true;
+ }
+
+ protected function argumentDef(&$out) {
+ $s = $this->seek();
+ $this->literal("(");
+
+ $args = array();
+ while ($this->variable($var)) {
+ $arg = array($var[1], null, false);
+
+ $ss = $this->seek();
+ if ($this->literal(":") && $this->genericList($defaultVal, "expression")) {
+ $arg[1] = $defaultVal;
+ } else {
+ $this->seek($ss);
+ }
+
+ $ss = $this->seek();
+ if ($this->literal("...")) {
+ $sss = $this->seek();
+ if (!$this->literal(")")) {
+ $this->throwParseError("... has to be after the final argument");
+ }
+ $arg[2] = true;
+ $this->seek($sss);
+ } else {
+ $this->seek($ss);
+ }
+
+ $args[] = $arg;
+ if (!$this->literal(",")) break;
+ }
+
+ if (!$this->literal(")")) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $args;
+ return true;
+ }
+
+ protected function color(&$out) {
+ $color = array('color');
+
+ if ($this->match('(#([0-9a-f]{6})|#([0-9a-f]{3}))', $m)) {
+ if (isset($m[3])) {
+ $num = $m[3];
+ $width = 16;
+ } else {
+ $num = $m[2];
+ $width = 256;
+ }
+
+ $num = hexdec($num);
+ foreach (array(3,2,1) as $i) {
+ $t = $num % $width;
+ $num /= $width;
+
+ $color[$i] = $t * (256/$width) + $t * floor(16/$width);
+ }
+
+ $out = $color;
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function unit(&$unit) {
+ if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m)) {
+ $unit = array("number", $m[1], empty($m[3]) ? "" : $m[3]);
+ return true;
+ }
+ return false;
+ }
+
+ protected function string(&$out) {
+ $s = $this->seek();
+ if ($this->literal('"', false)) {
+ $delim = '"';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
+ } else {
+ return false;
+ }
+
+ $content = array();
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while ($this->matchString($m, $delim)) {
+ $content[] = $m[1];
+ if ($m[2] == "#{") {
+ $this->count -= strlen($m[2]);
+ if ($this->interpolation($inter, false)) {
+ $content[] = $inter;
+ } else {
+ $this->count += strlen($m[2]);
+ $content[] = "#{"; // ignore it
+ }
+ } elseif ($m[2] == '\\') {
+ $content[] = $m[2];
+ if ($this->literal($delim, false)) {
+ $content[] = $delim;
+ }
+ } else {
+ $this->count -= strlen($delim);
+ break; // delim
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if ($this->literal($delim)) {
+ $out = array("string", $delim, $content);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function mixedKeyword(&$out) {
+ $s = $this->seek();
+
+ $parts = array();
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->keyword($key)) {
+ $parts[] = $key;
+ continue;
+ }
+
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ continue;
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($parts) == 0) return false;
+
+ if ($this->eatWhiteDefault) {
+ $this->whitespace();
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ // an unbounded string stopped by $end
+ protected function openString($end, &$out, $nestingOpen=null) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $stop = array("'", '"', "#{", $end);
+ $stop = array_map(array($this, "preg_quote"), $stop);
+ $stop[] = self::$commentMulti;
+
+ $patt = '(.*?)('.implode("|", $stop).')';
+
+ $nestingLevel = 0;
+
+ $content = array();
+ while ($this->match($patt, $m, false)) {
+ if (isset($m[1]) && $m[1] !== '') {
+ $content[] = $m[1];
+ if ($nestingOpen) {
+ $nestingLevel += substr_count($m[1], $nestingOpen);
+ }
+ }
+
+ $tok = $m[2];
+
+ $this->count-= strlen($tok);
+ if ($tok == $end) {
+ if ($nestingLevel == 0) {
+ break;
+ } else {
+ $nestingLevel--;
+ }
+ }
+
+ if (($tok == "'" || $tok == '"') && $this->string($str)) {
+ $content[] = $str;
+ continue;
+ }
+
+ if ($tok == "#{" && $this->interpolation($inter)) {
+ $content[] = $inter;
+ continue;
+ }
+
+ $content[] = $tok;
+ $this->count+= strlen($tok);
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($content) == 0) return false;
+
+ // trim the end
+ if (is_string(end($content))) {
+ $content[count($content) - 1] = rtrim(end($content));
+ }
+
+ $out = array("string", "", $content);
+ return true;
+ }
+
+ // $lookWhite: save information about whitespace before and after
+ protected function interpolation(&$out, $lookWhite=true) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = true;
+
+ $s = $this->seek();
+ if ($this->literal("#{") && $this->valueList($value) && $this->literal("}", false)) {
+
+ // TODO: don't error if out of bounds
+
+ if ($lookWhite) {
+ $left = preg_match('/\s/', $this->buffer[$s - 1]) ? " " : "";
+ $right = preg_match('/\s/', $this->buffer[$this->count]) ? " ": "";
+ } else {
+ $left = $right = false;
+ }
+
+ $out = array("interpolate", $value, $left, $right);
+ $this->eatWhiteDefault = $oldWhite;
+ if ($this->eatWhiteDefault) $this->whitespace();
+ return true;
+ }
+
+ $this->seek($s);
+ $this->eatWhiteDefault = $oldWhite;
+ return false;
+ }
+
+ // low level parsers
+
+ // returns an array of parts or a string
+ protected function propertyName(&$out) {
+ $s = $this->seek();
+ $parts = array();
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ } elseif ($this->keyword($text)) {
+ $parts[] = $text;
+ } elseif (count($parts) == 0 && $this->match('[:.#]', $m, false)) {
+ // css hacks
+ $parts[] = $m[0];
+ } else {
+ break;
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ if (count($parts) == 0) return false;
+
+ // match comment hack
+ if (preg_match(self::$whitePattern,
+ $this->buffer, $m, null, $this->count))
+ {
+ if (!empty($m[0])) {
+ $parts[] = $m[0];
+ $this->count += strlen($m[0]);
+ }
+ }
+
+ $this->whitespace(); // get any extra whitespace
+
+ $out = array("string", "", $parts);
+ return true;
+ }
+
+ // comma separated list of selectors
+ protected function selectors(&$out) {
+ $s = $this->seek();
+ $selectors = array();
+ while ($this->selector($sel)) {
+ $selectors[] = $sel;
+ if (!$this->literal(",")) break;
+ while ($this->literal(",")); // ignore extra
+ }
+
+ if (count($selectors) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $selectors;
+ return true;
+ }
+
+ // whitespace separated list of selectorSingle
+ protected function selector(&$out) {
+ $selector = array();
+
+ while (true) {
+ if ($this->match('[>+~]+', $m)) {
+ $selector[] = array($m[0]);
+ } elseif ($this->selectorSingle($part)) {
+ $selector[] = $part;
+ $this->whitespace();
+ } elseif ($this->match('\/[^\/]+\/', $m)) {
+ $selector[] = array($m[0]);
+ } else {
+ break;
+ }
+
+ }
+
+ if (count($selector) == 0) {
+ return false;
+ }
+
+ $out = $selector;
+ return true;
+ }
+
+ // the parts that make up
+ // div[yes=no]#something.hello.world:nth-child(-2n+1)%placeholder
+ protected function selectorSingle(&$out) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $parts = array();
+
+ if ($this->literal("*", false)) {
+ $parts[] = "*";
+ }
+
+ while (true) {
+ // see if we can stop early
+ if ($this->match("\s*[{,]", $m)) {
+ $this->count--;
+ break;
+ }
+
+ $s = $this->seek();
+ // self
+ if ($this->literal("&", false)) {
+ $parts[] = scssc::$selfSelector;
+ continue;
+ }
+
+ if ($this->literal(".", false)) {
+ $parts[] = ".";
+ continue;
+ }
+
+ if ($this->literal("|", false)) {
+ $parts[] = "|";
+ continue;
+ }
+
+ // for keyframes
+ if ($this->unit($unit)) {
+ $parts[] = $unit;
+ continue;
+ }
+
+ if ($this->keyword($name)) {
+ $parts[] = $name;
+ continue;
+ }
+
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ continue;
+ }
+
+ if ($this->literal('%', false) && $this->placeholder($placeholder)) {
+ $parts[] = '%';
+ $parts[] = $placeholder;
+ continue;
+ }
+
+ if ($this->literal("#", false)) {
+ $parts[] = "#";
+ continue;
+ }
+
+ // a pseudo selector
+ if ($this->match("::?", $m) && $this->mixedKeyword($nameParts)) {
+ $parts[] = $m[0];
+ foreach ($nameParts as $sub) {
+ $parts[] = $sub;
+ }
+
+ $ss = $this->seek();
+ if ($this->literal("(") &&
+ ($this->openString(")", $str, "(") || true ) &&
+ $this->literal(")"))
+ {
+ $parts[] = "(";
+ if (!empty($str)) $parts[] = $str;
+ $parts[] = ")";
+ } else {
+ $this->seek($ss);
+ }
+
+ continue;
+ } else {
+ $this->seek($s);
+ }
+
+ // attribute selector
+ // TODO: replace with open string?
+ if ($this->literal("[", false)) {
+ $attrParts = array("[");
+ // keyword, string, operator
+ while (true) {
+ if ($this->literal("]", false)) {
+ $this->count--;
+ break; // get out early
+ }
+
+ if ($this->match('\s+', $m)) {
+ $attrParts[] = " ";
+ continue;
+ }
+ if ($this->string($str)) {
+ $attrParts[] = $str;
+ continue;
+ }
+
+ if ($this->keyword($word)) {
+ $attrParts[] = $word;
+ continue;
+ }
+
+ if ($this->interpolation($inter, false)) {
+ $attrParts[] = $inter;
+ continue;
+ }
+
+ // operator, handles attr namespace too
+ if ($this->match('[|-~\$\*\^=]+', $m)) {
+ $attrParts[] = $m[0];
+ continue;
+ }
+
+ break;
+ }
+
+ if ($this->literal("]", false)) {
+ $attrParts[] = "]";
+ foreach ($attrParts as $part) {
+ $parts[] = $part;
+ }
+ continue;
+ }
+ $this->seek($s);
+ // should just break here?
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($parts) == 0) return false;
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function variable(&$out) {
+ $s = $this->seek();
+ if ($this->literal("$", false) && $this->keyword($name)) {
+ $out = array("var", $name);
+ return true;
+ }
+ $this->seek($s);
+ return false;
+ }
+
+ protected function keyword(&$word, $eatWhitespace = null) {
+ if ($this->match('([\w_\-\*!"\'\\\\][\w\-_"\'\\\\]*)',
+ $m, $eatWhitespace))
+ {
+ $word = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ protected function placeholder(&$placeholder) {
+ if ($this->match('([\w\-_]+)', $m)) {
+ $placeholder = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ // consume an end of statement delimiter
+ protected function end() {
+ if ($this->literal(';')) {
+ return true;
+ } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
+ // if there is end of file or a closing block next then we don't need a ;
+ return true;
+ }
+ return false;
+ }
+
+ // advance counter to next occurrence of $what
+ // $until - don't include $what in advance
+ // $allowNewline, if string, will be used as valid char set
+ protected function to($what, &$out, $until = false, $allowNewline = false) {
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? "." : "[^\n]";
+ }
+ if (!$this->match('('.$validChars.'*?)'.$this->preg_quote($what), $m, !$until)) return false;
+ if ($until) $this->count -= strlen($what); // give back $what
+ $out = $m[1];
+ return true;
+ }
+
+ public function throwParseError($msg = "parse error", $count = null) {
+ $count = !isset($count) ? $this->count : $count;
+
+ $line = $this->getLineNo($count);
+
+ if (!empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new Exception("$msg: failed at `$m[1]` $loc");
+ } else {
+ throw new Exception("$msg: $loc");
+ }
+ }
+
+ public function getLineNo($pos) {
+ return 1 + substr_count(substr($this->buffer, 0, $pos), "\n");
+ }
+
+ /**
+ * Match string looking for either ending delim, escape, or string interpolation
+ *
+ * {@internal This is a workaround for preg_match's 250K string match limit. }}
+ *
+ * @param array $m Matches (passed by reference)
+ * @param string $delim Delimeter
+ *
+ * @return boolean True if match; false otherwise
+ */
+ protected function matchString(&$m, $delim) {
+ $token = null;
+
+ $end = strpos($this->buffer, "\n", $this->count);
+ if ($end === false || $this->buffer[$end - 1] == '\\' || $this->buffer[$end - 2] == '\\' && $this->buffer[$end - 1] == "\r") {
+ $end = strlen($this->buffer);
+ }
+
+ // look for either ending delim, escape, or string interpolation
+ foreach (array('#{', '\\', $delim) as $lookahead) {
+ $pos = strpos($this->buffer, $lookahead, $this->count);
+ if ($pos !== false && $pos < $end) {
+ $end = $pos;
+ $token = $lookahead;
+ }
+ }
+
+ if (!isset($token)) {
+ return false;
+ }
+
+ $match = substr($this->buffer, $this->count, $end - $this->count);
+ $m = array(
+ $match . $token,
+ $match,
+ $token
+ );
+ $this->count = $end + strlen($token);
+
+ return true;
+ }
+
+ // try to match something on head of buffer
+ protected function match($regex, &$out, $eatWhitespace = null) {
+ if (!isset($eatWhitespace)) $eatWhitespace = $this->eatWhiteDefault;
+
+ $r = '/'.$regex.'/Ais';
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+ if ($eatWhitespace) $this->whitespace();
+ return true;
+ }
+ return false;
+ }
+
+ // match some whitespace
+ protected function whitespace() {
+ $gotWhite = false;
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if ($this->insertComments) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->append(array("comment", $m[1]));
+ $this->commentsSeen[$this->count] = true;
+ }
+ }
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
+ }
+ return $gotWhite;
+ }
+
+ protected function peek($regex, &$out, $from=null) {
+ if (!isset($from)) $from = $this->count;
+
+ $r = '/'.$regex.'/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ protected function seek($where = null) {
+ if ($where === null) return $this->count;
+ else $this->count = $where;
+ return true;
+ }
+
+ static function preg_quote($what) {
+ return preg_quote($what, '/');
+ }
+
+ protected function show() {
+ if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
+ return $m[1];
+ }
+ return "";
+ }
+
+ // turn list of length 1 into value type
+ protected function flattenList($value) {
+ if ($value[0] == "list" && count($value[2]) == 1) {
+ return $this->flattenList($value[2][0]);
+ }
+ return $value;
+ }
+}
+
+/**
+ * SCSS base formatter
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_formatter {
+ public $indentChar = " ";
+
+ public $break = "\n";
+ public $open = " {";
+ public $close = "}";
+ public $tagSeparator = ", ";
+ public $assignSeparator = ": ";
+
+ public function __construct() {
+ $this->indentLevel = 0;
+ }
+
+ public function indentStr($n = 0) {
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
+ public function property($name, $value) {
+ return $name . $this->assignSeparator . $value . ";";
+ }
+
+ protected function block($block) {
+ if (empty($block->lines) && empty($block->children)) return;
+
+ $inner = $pre = $this->indentStr();
+
+ if (!empty($block->selectors)) {
+ echo $pre .
+ implode($this->tagSeparator, $block->selectors) .
+ $this->open . $this->break;
+ $this->indentLevel++;
+ $inner = $this->indentStr();
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!empty($block->children)) {
+ echo $this->break;
+ }
+ }
+
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel--;
+ if (empty($block->children)) echo $this->break;
+ echo $pre . $this->close . $this->break;
+ }
+ }
+
+ public function format($block) {
+ ob_start();
+ $this->block($block);
+ $out = ob_get_clean();
+
+ return $out;
+ }
+}
+
+/**
+ * SCSS nested formatter
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_formatter_nested extends scss_formatter {
+ public $close = " }";
+
+ // adjust the depths of all children, depth first
+ public function adjustAllChildren($block) {
+ // flatten empty nested blocks
+ $children = array();
+ foreach ($block->children as $i => $child) {
+ if (empty($child->lines) && empty($child->children)) {
+ if (isset($block->children[$i + 1])) {
+ $block->children[$i + 1]->depth = $child->depth;
+ }
+ continue;
+ }
+ $children[] = $child;
+ }
+
+ $count = count($children);
+ for ($i = 0; $i < $count; $i++) {
+ $depth = $children[$i]->depth;
+ $j = $i + 1;
+ if (isset($children[$j]) && $depth < $children[$j]->depth) {
+ $childDepth = $children[$j]->depth;
+ for (; $j < $count; $j++) {
+ if ($depth < $children[$j]->depth && $childDepth >= $children[$j]->depth) {
+ $children[$j]->depth = $depth + 1;
+ }
+ }
+ }
+ }
+
+ $block->children = $children;
+
+ // make relative to parent
+ foreach ($block->children as $child) {
+ $this->adjustAllChildren($child);
+ $child->depth = $child->depth - $block->depth;
+ }
+ }
+
+ protected function block($block) {
+ if ($block->type == "root") {
+ $this->adjustAllChildren($block);
+ }
+
+ $inner = $pre = $this->indentStr($block->depth - 1);
+ if (!empty($block->selectors)) {
+ echo $pre .
+ implode($this->tagSeparator, $block->selectors) .
+ $this->open . $this->break;
+ $this->indentLevel++;
+ $inner = $this->indentStr($block->depth - 1);
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!empty($block->children)) echo $this->break;
+ }
+
+ foreach ($block->children as $i => $child) {
+ // echo "*** block: ".$block->depth." child: ".$child->depth."\n";
+ $this->block($child);
+ if ($i < count($block->children) - 1) {
+ echo $this->break;
+
+ if (isset($block->children[$i + 1])) {
+ $next = $block->children[$i + 1];
+ if ($next->depth == max($block->depth, 1) && $child->depth >= $next->depth) {
+ echo $this->break;
+ }
+ }
+ }
+ }
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel--;
+ echo $this->close;
+ }
+
+ if ($block->type == "root") {
+ echo $this->break;
+ }
+ }
+}
+
+/**
+ * SCSS compressed formatter
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_formatter_compressed extends scss_formatter {
+ public $open = "{";
+ public $tagSeparator = ",";
+ public $assignSeparator = ":";
+ public $break = "";
+
+ public function indentStr($n = 0) {
+ return "";
+ }
+}
+
+/**
+ * SCSS server
+ *
+ * @author Leaf Corcoran <leafot@gmail.com>
+ */
+class scss_server {
+ /**
+ * Join path components
+ *
+ * @param string $left Path component, left of the directory separator
+ * @param string $right Path component, right of the directory separator
+ *
+ * @return string
+ */
+ protected function join($left, $right) {
+ return rtrim($left, '/\\') . DIRECTORY_SEPARATOR . ltrim($right, '/\\');
+ }
+
+ /**
+ * Get name of requested .scss file
+ *
+ * @return string|null
+ */
+ protected function inputName() {
+ switch (true) {
+ case isset($_GET['p']):
+ return $_GET['p'];
+ case isset($_SERVER['PATH_INFO']):
+ return $_SERVER['PATH_INFO'];
+ case isset($_SERVER['DOCUMENT_URI']):
+ return substr($_SERVER['DOCUMENT_URI'], strlen($_SERVER['SCRIPT_NAME']));
+ }
+ }
+
+ /**
+ * Get path to requested .scss file
+ *
+ * @return string
+ */
+ protected function findInput() {
+ if (($input = $this->inputName())
+ && strpos($input, '..') === false
+ && substr($input, -5) === '.scss'
+ ) {
+ $name = $this->join($this->dir, $input);
+
+ if (is_file($name) && is_readable($name)) {
+ return $name;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get path to cached .css file
+ *
+ * @return string
+ */
+ protected function cacheName($fname) {
+ return $this->join($this->cacheDir, md5($fname) . '.css');
+ }
+
+ /**
+ * Get path to cached imports
+ *
+ * @return string
+ */
+ protected function importsCacheName($out) {
+ return $out . '.imports';
+ }
+
+ /**
+ * Determine whether .scss file needs to be re-compiled.
+ *
+ * @param string $in Input path
+ * @param string $out Output path
+ *
+ * @return boolean True if compile required.
+ */
+ protected function needsCompile($in, $out) {
+ if (!is_file($out)) return true;
+
+ $mtime = filemtime($out);
+ if (filemtime($in) > $mtime) return true;
+
+ // look for modified imports
+ $icache = $this->importsCacheName($out);
+ if (is_readable($icache)) {
+ $imports = unserialize(file_get_contents($icache));
+ foreach ($imports as $import) {
+ if (filemtime($import) > $mtime) return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get If-Modified-Since header from client request
+ *
+ * @return string
+ */
+ protected function getModifiedSinceHeader()
+ {
+ $modifiedSince = '';
+
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
+ $modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+
+ if (false !== ($semicolonPos = strpos($modifiedSince, ';'))) {
+ $modifiedSince = substr($modifiedSince, 0, $semicolonPos);
+ }
+ }
+
+ return $modifiedSince;
+ }
+
+ /**
+ * Compile .scss file
+ *
+ * @param string $in Input path (.scss)
+ * @param string $out Output path (.css)
+ *
+ * @return string
+ */
+ protected function compile($in, $out) {
+ $start = microtime(true);
+ $css = $this->scss->compile(file_get_contents($in), $in);
+ $elapsed = round((microtime(true) - $start), 4);
+
+ $v = scssc::$VERSION;
+ $t = @date('r');
+ $css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css;
+
+ file_put_contents($out, $css);
+ file_put_contents($this->importsCacheName($out),
+ serialize($this->scss->getParsedFiles()));
+ return $css;
+ }
+
+ /**
+ * Compile requested scss and serve css. Outputs HTTP response.
+ *
+ * @param string $salt Prefix a string to the filename for creating the cache name hash
+ */
+ public function serve($salt = '') {
+ $protocol = isset($_SERVER['SERVER_PROTOCOL'])
+ ? $_SERVER['SERVER_PROTOCOL']
+ : 'HTTP/1.0';
+
+ if ($input = $this->findInput()) {
+ $output = $this->cacheName($salt . $input);
+
+ if ($this->needsCompile($input, $output)) {
+ try {
+ $css = $this->compile($input, $output);
+
+ $lastModified = gmdate('D, d M Y H:i:s', filemtime($output)) . ' GMT';
+
+ header('Last-Modified: ' . $lastModified);
+ header('Content-type: text/css');
+
+ echo $css;
+
+ return;
+ } catch (Exception $e) {
+ header($protocol . ' 500 Internal Server Error');
+ header('Content-type: text/plain');
+
+ echo 'Parse error: ' . $e->getMessage() . "\n";
+ }
+ }
+
+ header('X-SCSS-Cache: true');
+ header('Content-type: text/css');
+
+ $modifiedSince = $this->getModifiedSinceHeader();
+ $mtime = filemtime($output);
+
+ if (@strtotime($modifiedSince) === $mtime) {
+ header($protocol . ' 304 Not Modified');
+
+ return;
+ }
+
+ $lastModified = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
+ header('Last-Modified: ' . $lastModified);
+
+ echo file_get_contents($output);
+
+ return;
+ }
+
+ header($protocol . ' 404 Not Found');
+ header('Content-type: text/plain');
+
+ $v = scssc::$VERSION;
+ echo "/* INPUT NOT FOUND scss $v */\n";
+ }
+
+ /**
+ * Constructor
+ *
+ * @param string $dir Root directory to .scss files
+ * @param string $cacheDir Cache directory
+ * @param \scssc|null $scss SCSS compiler instance
+ */
+ public function __construct($dir, $cacheDir=null, $scss=null) {
+ $this->dir = $dir;
+
+ if (!isset($cacheDir)) {
+ $cacheDir = $this->join($dir, 'scss_cache');
+ }
+
+ $this->cacheDir = $cacheDir;
+ if (!is_dir($this->cacheDir)) mkdir($this->cacheDir, 0755, true);
+
+ if (!isset($scss)) {
+ $scss = new scssc();
+ $scss->setImportPaths($this->dir);
+ }
+ $this->scss = $scss;
+ }
+
+ /**
+ * Helper method to serve compiled scss
+ *
+ * @param string $path Root path
+ */
+ static public function serveFrom($path) {
+ $server = new self($path);
+ $server->serve();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/polyfill-ctype/Ctype.php b/public/system/storage/vendor/symfony/polyfill-ctype/Ctype.php
new file mode 100644
index 0000000..58414dc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-ctype/Ctype.php
@@ -0,0 +1,227 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Ctype;
+
+/**
+ * Ctype implementation through regex.
+ *
+ * @internal
+ *
+ * @author Gert de Pagter <BackEndTea@gmail.com>
+ */
+final class Ctype
+{
+ /**
+ * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
+ *
+ * @see https://php.net/ctype-alnum
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_alnum($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is a letter, FALSE otherwise.
+ *
+ * @see https://php.net/ctype-alpha
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_alpha($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
+ *
+ * @see https://php.net/ctype-cntrl
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_cntrl($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
+ *
+ * @see https://php.net/ctype-digit
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_digit($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
+ *
+ * @see https://php.net/ctype-graph
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_graph($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is a lowercase letter.
+ *
+ * @see https://php.net/ctype-lower
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_lower($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
+ *
+ * @see https://php.net/ctype-print
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_print($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
+ *
+ * @see https://php.net/ctype-punct
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_punct($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
+ *
+ * @see https://php.net/ctype-space
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_space($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is an uppercase letter.
+ *
+ * @see https://php.net/ctype-upper
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_upper($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
+ }
+
+ /**
+ * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
+ *
+ * @see https://php.net/ctype-xdigit
+ *
+ * @param string|int $text
+ *
+ * @return bool
+ */
+ public static function ctype_xdigit($text)
+ {
+ $text = self::convert_int_to_char_for_ctype($text);
+
+ return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
+ }
+
+ /**
+ * Converts integers to their char versions according to normal ctype behaviour, if needed.
+ *
+ * If an integer between -128 and 255 inclusive is provided,
+ * it is interpreted as the ASCII value of a single character
+ * (negative values have 256 added in order to allow characters in the Extended ASCII range).
+ * Any other integer is interpreted as a string containing the decimal digits of the integer.
+ *
+ * @param string|int $int
+ *
+ * @return mixed
+ */
+ private static function convert_int_to_char_for_ctype($int)
+ {
+ if (!\is_int($int)) {
+ return $int;
+ }
+
+ if ($int < -128 || $int > 255) {
+ return (string) $int;
+ }
+
+ if ($int < 0) {
+ $int += 256;
+ }
+
+ return \chr($int);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/polyfill-ctype/LICENSE b/public/system/storage/vendor/symfony/polyfill-ctype/LICENSE
new file mode 100644
index 0000000..3f853aa
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-ctype/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2019 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/symfony/polyfill-ctype/README.md b/public/system/storage/vendor/symfony/polyfill-ctype/README.md
new file mode 100644
index 0000000..8add1ab
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-ctype/README.md
@@ -0,0 +1,12 @@
+Symfony Polyfill / Ctype
+========================
+
+This component provides `ctype_*` functions to users who run php versions without the ctype extension.
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/public/system/storage/vendor/symfony/polyfill-ctype/bootstrap.php b/public/system/storage/vendor/symfony/polyfill-ctype/bootstrap.php
new file mode 100644
index 0000000..14d1d0f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-ctype/bootstrap.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Ctype as p;
+
+if (!function_exists('ctype_alnum')) {
+ function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
+ function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
+ function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
+ function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
+ function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
+ function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
+ function ctype_print($text) { return p\Ctype::ctype_print($text); }
+ function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
+ function ctype_space($text) { return p\Ctype::ctype_space($text); }
+ function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
+ function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
+}
diff --git a/public/system/storage/vendor/symfony/polyfill-ctype/composer.json b/public/system/storage/vendor/symfony/polyfill-ctype/composer.json
new file mode 100644
index 0000000..c24e20c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-ctype/composer.json
@@ -0,0 +1,34 @@
+{
+ "name": "symfony/polyfill-ctype",
+ "type": "library",
+ "description": "Symfony polyfill for ctype functions",
+ "keywords": ["polyfill", "compatibility", "portable", "ctype"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
+ "files": [ "bootstrap.php" ]
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.11-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/LICENSE b/public/system/storage/vendor/symfony/polyfill-mbstring/LICENSE
new file mode 100644
index 0000000..4cd8bdd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2019 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/Mbstring.php b/public/system/storage/vendor/symfony/polyfill-mbstring/Mbstring.php
new file mode 100644
index 0000000..a5e4a8f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/Mbstring.php
@@ -0,0 +1,800 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Mbstring;
+
+/**
+ * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
+ *
+ * Implemented:
+ * - mb_chr - Returns a specific character from its Unicode code point
+ * - mb_convert_encoding - Convert character encoding
+ * - mb_convert_variables - Convert character code in variable(s)
+ * - mb_decode_mimeheader - Decode string in MIME header field
+ * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
+ * - mb_decode_numericentity - Decode HTML numeric string reference to character
+ * - mb_encode_numericentity - Encode character to HTML numeric string reference
+ * - mb_convert_case - Perform case folding on a string
+ * - mb_detect_encoding - Detect character encoding
+ * - mb_get_info - Get internal settings of mbstring
+ * - mb_http_input - Detect HTTP input character encoding
+ * - mb_http_output - Set/Get HTTP output character encoding
+ * - mb_internal_encoding - Set/Get internal character encoding
+ * - mb_list_encodings - Returns an array of all supported encodings
+ * - mb_ord - Returns the Unicode code point of a character
+ * - mb_output_handler - Callback function converts character encoding in output buffer
+ * - mb_scrub - Replaces ill-formed byte sequences with substitute characters
+ * - mb_strlen - Get string length
+ * - mb_strpos - Find position of first occurrence of string in a string
+ * - mb_strrpos - Find position of last occurrence of a string in a string
+ * - mb_strtolower - Make a string lowercase
+ * - mb_strtoupper - Make a string uppercase
+ * - mb_substitute_character - Set/Get substitution character
+ * - mb_substr - Get part of string
+ * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
+ * - mb_stristr - Finds first occurrence of a string within another, case insensitive
+ * - mb_strrchr - Finds the last occurrence of a character in a string within another
+ * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
+ * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
+ * - mb_strstr - Finds first occurrence of a string within another
+ * - mb_strwidth - Return width of string
+ * - mb_substr_count - Count the number of substring occurrences
+ *
+ * Not implemented:
+ * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
+ * - mb_ereg_* - Regular expression with multibyte support
+ * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
+ * - mb_preferred_mime_name - Get MIME charset string
+ * - mb_regex_encoding - Returns current encoding for multibyte regex as string
+ * - mb_regex_set_options - Set/Get the default options for mbregex functions
+ * - mb_send_mail - Send encoded mail
+ * - mb_split - Split multibyte string using regular expression
+ * - mb_strcut - Get part of string
+ * - mb_strimwidth - Get truncated string with specified width
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @internal
+ */
+final class Mbstring
+{
+ const MB_CASE_FOLD = PHP_INT_MAX;
+
+ private static $encodingList = array('ASCII', 'UTF-8');
+ private static $language = 'neutral';
+ private static $internalEncoding = 'UTF-8';
+ private static $caseFold = array(
+ array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"),
+ array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'),
+ );
+
+ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
+ {
+ if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
+ $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
+ } else {
+ $fromEncoding = self::getEncoding($fromEncoding);
+ }
+
+ $toEncoding = self::getEncoding($toEncoding);
+
+ if ('BASE64' === $fromEncoding) {
+ $s = base64_decode($s);
+ $fromEncoding = $toEncoding;
+ }
+
+ if ('BASE64' === $toEncoding) {
+ return base64_encode($s);
+ }
+
+ if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
+ if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
+ $fromEncoding = 'Windows-1252';
+ }
+ if ('UTF-8' !== $fromEncoding) {
+ $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
+ }
+
+ return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
+ }
+
+ if ('HTML-ENTITIES' === $fromEncoding) {
+ $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
+ $fromEncoding = 'UTF-8';
+ }
+
+ return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
+ }
+
+ public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
+ {
+ $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
+
+ $ok = true;
+ array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
+ if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
+ $ok = false;
+ }
+ });
+
+ return $ok ? $fromEncoding : false;
+ }
+
+ public static function mb_decode_mimeheader($s)
+ {
+ return iconv_mime_decode($s, 2, self::$internalEncoding);
+ }
+
+ public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
+ {
+ trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
+ }
+
+ public static function mb_decode_numericentity($s, $convmap, $encoding = null)
+ {
+ if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
+ trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
+
+ return null;
+ }
+
+ if (!\is_array($convmap) || !$convmap) {
+ return false;
+ }
+
+ if (null !== $encoding && !\is_scalar($encoding)) {
+ trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
+
+ return ''; // Instead of null (cf. mb_encode_numericentity).
+ }
+
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ $cnt = floor(\count($convmap) / 4) * 4;
+
+ for ($i = 0; $i < $cnt; $i += 4) {
+ // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
+ $convmap[$i] += $convmap[$i + 2];
+ $convmap[$i + 1] += $convmap[$i + 2];
+ }
+
+ $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
+ $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
+ for ($i = 0; $i < $cnt; $i += 4) {
+ if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
+ return Mbstring::mb_chr($c - $convmap[$i + 2]);
+ }
+ }
+
+ return $m[0];
+ }, $s);
+
+ if (null === $encoding) {
+ return $s;
+ }
+
+ return iconv('UTF-8', $encoding.'//IGNORE', $s);
+ }
+
+ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
+ {
+ if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
+ trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
+
+ return null;
+ }
+
+ if (!\is_array($convmap) || !$convmap) {
+ return false;
+ }
+
+ if (null !== $encoding && !\is_scalar($encoding)) {
+ trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
+
+ return null; // Instead of '' (cf. mb_decode_numericentity).
+ }
+
+ if (null !== $is_hex && !\is_scalar($is_hex)) {
+ trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING);
+
+ return null;
+ }
+
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
+
+ $cnt = floor(\count($convmap) / 4) * 4;
+ $i = 0;
+ $len = \strlen($s);
+ $result = '';
+
+ while ($i < $len) {
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
+ $uchr = substr($s, $i, $ulen);
+ $i += $ulen;
+ $c = self::mb_ord($uchr);
+
+ for ($j = 0; $j < $cnt; $j += 4) {
+ if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
+ $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
+ $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
+ continue 2;
+ }
+ }
+ $result .= $uchr;
+ }
+
+ if (null === $encoding) {
+ return $result;
+ }
+
+ return iconv('UTF-8', $encoding.'//IGNORE', $result);
+ }
+
+ public static function mb_convert_case($s, $mode, $encoding = null)
+ {
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ if (MB_CASE_TITLE == $mode) {
+ static $titleRegexp = null;
+ if (null === $titleRegexp) {
+ $titleRegexp = self::getData('titleCaseRegexp');
+ }
+ $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s);
+ } else {
+ if (MB_CASE_UPPER == $mode) {
+ static $upper = null;
+ if (null === $upper) {
+ $upper = self::getData('upperCase');
+ }
+ $map = $upper;
+ } else {
+ if (self::MB_CASE_FOLD === $mode) {
+ $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
+ }
+
+ static $lower = null;
+ if (null === $lower) {
+ $lower = self::getData('lowerCase');
+ }
+ $map = $lower;
+ }
+
+ static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
+
+ $i = 0;
+ $len = \strlen($s);
+
+ while ($i < $len) {
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
+ $uchr = substr($s, $i, $ulen);
+ $i += $ulen;
+
+ if (isset($map[$uchr])) {
+ $uchr = $map[$uchr];
+ $nlen = \strlen($uchr);
+
+ if ($nlen == $ulen) {
+ $nlen = $i;
+ do {
+ $s[--$nlen] = $uchr[--$ulen];
+ } while ($ulen);
+ } else {
+ $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
+ $len += $nlen - $ulen;
+ $i += $nlen - $ulen;
+ }
+ }
+ }
+ }
+
+ if (null === $encoding) {
+ return $s;
+ }
+
+ return iconv('UTF-8', $encoding.'//IGNORE', $s);
+ }
+
+ public static function mb_internal_encoding($encoding = null)
+ {
+ if (null === $encoding) {
+ return self::$internalEncoding;
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
+ self::$internalEncoding = $encoding;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public static function mb_language($lang = null)
+ {
+ if (null === $lang) {
+ return self::$language;
+ }
+
+ switch ($lang = strtolower($lang)) {
+ case 'uni':
+ case 'neutral':
+ self::$language = $lang;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public static function mb_list_encodings()
+ {
+ return array('UTF-8');
+ }
+
+ public static function mb_encoding_aliases($encoding)
+ {
+ switch (strtoupper($encoding)) {
+ case 'UTF8':
+ case 'UTF-8':
+ return array('utf8');
+ }
+
+ return false;
+ }
+
+ public static function mb_check_encoding($var = null, $encoding = null)
+ {
+ if (null === $encoding) {
+ if (null === $var) {
+ return false;
+ }
+ $encoding = self::$internalEncoding;
+ }
+
+ return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
+ }
+
+ public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
+ {
+ if (null === $encodingList) {
+ $encodingList = self::$encodingList;
+ } else {
+ if (!\is_array($encodingList)) {
+ $encodingList = array_map('trim', explode(',', $encodingList));
+ }
+ $encodingList = array_map('strtoupper', $encodingList);
+ }
+
+ foreach ($encodingList as $enc) {
+ switch ($enc) {
+ case 'ASCII':
+ if (!preg_match('/[\x80-\xFF]/', $str)) {
+ return $enc;
+ }
+ break;
+
+ case 'UTF8':
+ case 'UTF-8':
+ if (preg_match('//u', $str)) {
+ return 'UTF-8';
+ }
+ break;
+
+ default:
+ if (0 === strncmp($enc, 'ISO-8859-', 9)) {
+ return $enc;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static function mb_detect_order($encodingList = null)
+ {
+ if (null === $encodingList) {
+ return self::$encodingList;
+ }
+
+ if (!\is_array($encodingList)) {
+ $encodingList = array_map('trim', explode(',', $encodingList));
+ }
+ $encodingList = array_map('strtoupper', $encodingList);
+
+ foreach ($encodingList as $enc) {
+ switch ($enc) {
+ default:
+ if (strncmp($enc, 'ISO-8859-', 9)) {
+ return false;
+ }
+ // no break
+ case 'ASCII':
+ case 'UTF8':
+ case 'UTF-8':
+ }
+ }
+
+ self::$encodingList = $encodingList;
+
+ return true;
+ }
+
+ public static function mb_strlen($s, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return \strlen($s);
+ }
+
+ return @iconv_strlen($s, $encoding);
+ }
+
+ public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return strpos($haystack, $needle, $offset);
+ }
+
+ $needle = (string) $needle;
+ if ('' === $needle) {
+ trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
+
+ return false;
+ }
+
+ return iconv_strpos($haystack, $needle, $offset, $encoding);
+ }
+
+ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return strrpos($haystack, $needle, $offset);
+ }
+
+ if ($offset != (int) $offset) {
+ $offset = 0;
+ } elseif ($offset = (int) $offset) {
+ if ($offset < 0) {
+ $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
+ $offset = 0;
+ } else {
+ $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
+ }
+ }
+
+ $pos = iconv_strrpos($haystack, $needle, $encoding);
+
+ return false !== $pos ? $offset + $pos : false;
+ }
+
+ public static function mb_strtolower($s, $encoding = null)
+ {
+ return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
+ }
+
+ public static function mb_strtoupper($s, $encoding = null)
+ {
+ return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
+ }
+
+ public static function mb_substitute_character($c = null)
+ {
+ if (0 === strcasecmp($c, 'none')) {
+ return true;
+ }
+
+ return null !== $c ? false : 'none';
+ }
+
+ public static function mb_substr($s, $start, $length = null, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return substr($s, $start, null === $length ? 2147483647 : $length);
+ }
+
+ if ($start < 0) {
+ $start = iconv_strlen($s, $encoding) + $start;
+ if ($start < 0) {
+ $start = 0;
+ }
+ }
+
+ if (null === $length) {
+ $length = 2147483647;
+ } elseif ($length < 0) {
+ $length = iconv_strlen($s, $encoding) + $length - $start;
+ if ($length < 0) {
+ return '';
+ }
+ }
+
+ return (string) iconv_substr($s, $start, $length, $encoding);
+ }
+
+ public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
+ $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
+
+ return self::mb_strpos($haystack, $needle, $offset, $encoding);
+ }
+
+ public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
+
+ return self::getSubpart($pos, $part, $haystack, $encoding);
+ }
+
+ public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return strrchr($haystack, $needle, $part);
+ }
+ $needle = self::mb_substr($needle, 0, 1, $encoding);
+ $pos = iconv_strrpos($haystack, $needle, $encoding);
+
+ return self::getSubpart($pos, $part, $haystack, $encoding);
+ }
+
+ public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $needle = self::mb_substr($needle, 0, 1, $encoding);
+ $pos = self::mb_strripos($haystack, $needle, $encoding);
+
+ return self::getSubpart($pos, $part, $haystack, $encoding);
+ }
+
+ public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
+ $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
+
+ return self::mb_strrpos($haystack, $needle, $offset, $encoding);
+ }
+
+ public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $pos = strpos($haystack, $needle);
+ if (false === $pos) {
+ return false;
+ }
+ if ($part) {
+ return substr($haystack, 0, $pos);
+ }
+
+ return substr($haystack, $pos);
+ }
+
+ public static function mb_get_info($type = 'all')
+ {
+ $info = array(
+ 'internal_encoding' => self::$internalEncoding,
+ 'http_output' => 'pass',
+ 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
+ 'func_overload' => 0,
+ 'func_overload_list' => 'no overload',
+ 'mail_charset' => 'UTF-8',
+ 'mail_header_encoding' => 'BASE64',
+ 'mail_body_encoding' => 'BASE64',
+ 'illegal_chars' => 0,
+ 'encoding_translation' => 'Off',
+ 'language' => self::$language,
+ 'detect_order' => self::$encodingList,
+ 'substitute_character' => 'none',
+ 'strict_detection' => 'Off',
+ );
+
+ if ('all' === $type) {
+ return $info;
+ }
+ if (isset($info[$type])) {
+ return $info[$type];
+ }
+
+ return false;
+ }
+
+ public static function mb_http_input($type = '')
+ {
+ return false;
+ }
+
+ public static function mb_http_output($encoding = null)
+ {
+ return null !== $encoding ? 'pass' === $encoding : 'pass';
+ }
+
+ public static function mb_strwidth($s, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' !== $encoding) {
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
+
+ return ($wide << 1) + iconv_strlen($s, 'UTF-8');
+ }
+
+ public static function mb_substr_count($haystack, $needle, $encoding = null)
+ {
+ return substr_count($haystack, $needle);
+ }
+
+ public static function mb_output_handler($contents, $status)
+ {
+ return $contents;
+ }
+
+ public static function mb_chr($code, $encoding = null)
+ {
+ if (0x80 > $code %= 0x200000) {
+ $s = \chr($code);
+ } elseif (0x800 > $code) {
+ $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
+ } elseif (0x10000 > $code) {
+ $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
+ } else {
+ $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
+ }
+
+ if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
+ $s = mb_convert_encoding($s, $encoding, 'UTF-8');
+ }
+
+ return $s;
+ }
+
+ public static function mb_ord($s, $encoding = null)
+ {
+ if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
+ $s = mb_convert_encoding($s, 'UTF-8', $encoding);
+ }
+
+ if (1 === \strlen($s)) {
+ return \ord($s);
+ }
+
+ $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
+ if (0xF0 <= $code) {
+ return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
+ }
+ if (0xE0 <= $code) {
+ return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
+ }
+ if (0xC0 <= $code) {
+ return (($code - 0xC0) << 6) + $s[2] - 0x80;
+ }
+
+ return $code;
+ }
+
+ private static function getSubpart($pos, $part, $haystack, $encoding)
+ {
+ if (false === $pos) {
+ return false;
+ }
+ if ($part) {
+ return self::mb_substr($haystack, 0, $pos, $encoding);
+ }
+
+ return self::mb_substr($haystack, $pos, null, $encoding);
+ }
+
+ private static function html_encoding_callback(array $m)
+ {
+ $i = 1;
+ $entities = '';
+ $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
+
+ while (isset($m[$i])) {
+ if (0x80 > $m[$i]) {
+ $entities .= \chr($m[$i++]);
+ continue;
+ }
+ if (0xF0 <= $m[$i]) {
+ $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
+ } elseif (0xE0 <= $m[$i]) {
+ $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
+ } else {
+ $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
+ }
+
+ $entities .= '&#'.$c.';';
+ }
+
+ return $entities;
+ }
+
+ private static function title_case(array $s)
+ {
+ return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
+ }
+
+ private static function getData($file)
+ {
+ if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
+ return require $file;
+ }
+
+ return false;
+ }
+
+ private static function getEncoding($encoding)
+ {
+ if (null === $encoding) {
+ return self::$internalEncoding;
+ }
+
+ $encoding = strtoupper($encoding);
+
+ if ('8BIT' === $encoding || 'BINARY' === $encoding) {
+ return 'CP850';
+ }
+ if ('UTF8' === $encoding) {
+ return 'UTF-8';
+ }
+
+ return $encoding;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/README.md b/public/system/storage/vendor/symfony/polyfill-mbstring/README.md
new file mode 100644
index 0000000..342e828
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/README.md
@@ -0,0 +1,13 @@
+Symfony Polyfill / Mbstring
+===========================
+
+This component provides a partial, native PHP implementation for the
+[Mbstring](http://php.net/mbstring) extension.
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
new file mode 100644
index 0000000..e6fbfa6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
@@ -0,0 +1,1096 @@
+<?php
+
+return array(
+ 'A' => 'a',
+ 'B' => 'b',
+ 'C' => 'c',
+ 'D' => 'd',
+ 'E' => 'e',
+ 'F' => 'f',
+ 'G' => 'g',
+ 'H' => 'h',
+ 'I' => 'i',
+ 'J' => 'j',
+ 'K' => 'k',
+ 'L' => 'l',
+ 'M' => 'm',
+ 'N' => 'n',
+ 'O' => 'o',
+ 'P' => 'p',
+ 'Q' => 'q',
+ 'R' => 'r',
+ 'S' => 's',
+ 'T' => 't',
+ 'U' => 'u',
+ 'V' => 'v',
+ 'W' => 'w',
+ 'X' => 'x',
+ 'Y' => 'y',
+ 'Z' => 'z',
+ 'À' => 'à',
+ 'Á' => 'á',
+ 'Â' => 'â',
+ 'Ã' => 'ã',
+ 'Ä' => 'ä',
+ 'Å' => 'å',
+ 'Æ' => 'æ',
+ 'Ç' => 'ç',
+ 'È' => 'è',
+ 'É' => 'é',
+ 'Ê' => 'ê',
+ 'Ë' => 'ë',
+ 'Ì' => 'ì',
+ 'Í' => 'í',
+ 'Î' => 'î',
+ 'Ï' => 'ï',
+ 'Ð' => 'ð',
+ 'Ñ' => 'ñ',
+ 'Ò' => 'ò',
+ 'Ó' => 'ó',
+ 'Ô' => 'ô',
+ 'Õ' => 'õ',
+ 'Ö' => 'ö',
+ 'Ø' => 'ø',
+ 'Ù' => 'ù',
+ 'Ú' => 'ú',
+ 'Û' => 'û',
+ 'Ü' => 'ü',
+ 'Ý' => 'ý',
+ 'Þ' => 'þ',
+ 'Ā' => 'ā',
+ 'Ă' => 'ă',
+ 'Ą' => 'ą',
+ 'Ć' => 'ć',
+ 'Ĉ' => 'ĉ',
+ 'Ċ' => 'ċ',
+ 'Č' => 'č',
+ 'Ď' => 'ď',
+ 'Đ' => 'đ',
+ 'Ē' => 'ē',
+ 'Ĕ' => 'ĕ',
+ 'Ė' => 'ė',
+ 'Ę' => 'ę',
+ 'Ě' => 'ě',
+ 'Ĝ' => 'ĝ',
+ 'Ğ' => 'ğ',
+ 'Ġ' => 'ġ',
+ 'Ģ' => 'ģ',
+ 'Ĥ' => 'ĥ',
+ 'Ħ' => 'ħ',
+ 'Ĩ' => 'ĩ',
+ 'Ī' => 'ī',
+ 'Ĭ' => 'ĭ',
+ 'Į' => 'į',
+ 'İ' => 'i',
+ 'IJ' => 'ij',
+ 'Ĵ' => 'ĵ',
+ 'Ķ' => 'ķ',
+ 'Ĺ' => 'ĺ',
+ 'Ļ' => 'ļ',
+ 'Ľ' => 'ľ',
+ 'Ŀ' => 'ŀ',
+ 'Ł' => 'ł',
+ 'Ń' => 'ń',
+ 'Ņ' => 'ņ',
+ 'Ň' => 'ň',
+ 'Ŋ' => 'ŋ',
+ 'Ō' => 'ō',
+ 'Ŏ' => 'ŏ',
+ 'Ő' => 'ő',
+ 'Œ' => 'œ',
+ 'Ŕ' => 'ŕ',
+ 'Ŗ' => 'ŗ',
+ 'Ř' => 'ř',
+ 'Ś' => 'ś',
+ 'Ŝ' => 'ŝ',
+ 'Ş' => 'ş',
+ 'Š' => 'š',
+ 'Ţ' => 'ţ',
+ 'Ť' => 'ť',
+ 'Ŧ' => 'ŧ',
+ 'Ũ' => 'ũ',
+ 'Ū' => 'ū',
+ 'Ŭ' => 'ŭ',
+ 'Ů' => 'ů',
+ 'Ű' => 'ű',
+ 'Ų' => 'ų',
+ 'Ŵ' => 'ŵ',
+ 'Ŷ' => 'ŷ',
+ 'Ÿ' => 'ÿ',
+ 'Ź' => 'ź',
+ 'Ż' => 'ż',
+ 'Ž' => 'ž',
+ 'Ɓ' => 'ɓ',
+ 'Ƃ' => 'ƃ',
+ 'Ƅ' => 'ƅ',
+ 'Ɔ' => 'ɔ',
+ 'Ƈ' => 'ƈ',
+ 'Ɖ' => 'ɖ',
+ 'Ɗ' => 'ɗ',
+ 'Ƌ' => 'ƌ',
+ 'Ǝ' => 'ǝ',
+ 'Ə' => 'ə',
+ 'Ɛ' => 'ɛ',
+ 'Ƒ' => 'ƒ',
+ 'Ɠ' => 'ɠ',
+ 'Ɣ' => 'ɣ',
+ 'Ɩ' => 'ɩ',
+ 'Ɨ' => 'ɨ',
+ 'Ƙ' => 'ƙ',
+ 'Ɯ' => 'ɯ',
+ 'Ɲ' => 'ɲ',
+ 'Ɵ' => 'ɵ',
+ 'Ơ' => 'ơ',
+ 'Ƣ' => 'ƣ',
+ 'Ƥ' => 'ƥ',
+ 'Ʀ' => 'ʀ',
+ 'Ƨ' => 'ƨ',
+ 'Ʃ' => 'ʃ',
+ 'Ƭ' => 'ƭ',
+ 'Ʈ' => 'ʈ',
+ 'Ư' => 'ư',
+ 'Ʊ' => 'ʊ',
+ 'Ʋ' => 'ʋ',
+ 'Ƴ' => 'ƴ',
+ 'Ƶ' => 'ƶ',
+ 'Ʒ' => 'ʒ',
+ 'Ƹ' => 'ƹ',
+ 'Ƽ' => 'ƽ',
+ 'DŽ' => 'dž',
+ 'Dž' => 'dž',
+ 'LJ' => 'lj',
+ 'Lj' => 'lj',
+ 'NJ' => 'nj',
+ 'Nj' => 'nj',
+ 'Ǎ' => 'ǎ',
+ 'Ǐ' => 'ǐ',
+ 'Ǒ' => 'ǒ',
+ 'Ǔ' => 'ǔ',
+ 'Ǖ' => 'ǖ',
+ 'Ǘ' => 'ǘ',
+ 'Ǚ' => 'ǚ',
+ 'Ǜ' => 'ǜ',
+ 'Ǟ' => 'ǟ',
+ 'Ǡ' => 'ǡ',
+ 'Ǣ' => 'ǣ',
+ 'Ǥ' => 'ǥ',
+ 'Ǧ' => 'ǧ',
+ 'Ǩ' => 'ǩ',
+ 'Ǫ' => 'ǫ',
+ 'Ǭ' => 'ǭ',
+ 'Ǯ' => 'ǯ',
+ 'DZ' => 'dz',
+ 'Dz' => 'dz',
+ 'Ǵ' => 'ǵ',
+ 'Ƕ' => 'ƕ',
+ 'Ƿ' => 'ƿ',
+ 'Ǹ' => 'ǹ',
+ 'Ǻ' => 'ǻ',
+ 'Ǽ' => 'ǽ',
+ 'Ǿ' => 'ǿ',
+ 'Ȁ' => 'ȁ',
+ 'Ȃ' => 'ȃ',
+ 'Ȅ' => 'ȅ',
+ 'Ȇ' => 'ȇ',
+ 'Ȉ' => 'ȉ',
+ 'Ȋ' => 'ȋ',
+ 'Ȍ' => 'ȍ',
+ 'Ȏ' => 'ȏ',
+ 'Ȑ' => 'ȑ',
+ 'Ȓ' => 'ȓ',
+ 'Ȕ' => 'ȕ',
+ 'Ȗ' => 'ȗ',
+ 'Ș' => 'ș',
+ 'Ț' => 'ț',
+ 'Ȝ' => 'ȝ',
+ 'Ȟ' => 'ȟ',
+ 'Ƞ' => 'ƞ',
+ 'Ȣ' => 'ȣ',
+ 'Ȥ' => 'ȥ',
+ 'Ȧ' => 'ȧ',
+ 'Ȩ' => 'ȩ',
+ 'Ȫ' => 'ȫ',
+ 'Ȭ' => 'ȭ',
+ 'Ȯ' => 'ȯ',
+ 'Ȱ' => 'ȱ',
+ 'Ȳ' => 'ȳ',
+ 'Ⱥ' => 'ⱥ',
+ 'Ȼ' => 'ȼ',
+ 'Ƚ' => 'ƚ',
+ 'Ⱦ' => 'ⱦ',
+ 'Ɂ' => 'ɂ',
+ 'Ƀ' => 'ƀ',
+ 'Ʉ' => 'ʉ',
+ 'Ʌ' => 'ʌ',
+ 'Ɇ' => 'ɇ',
+ 'Ɉ' => 'ɉ',
+ 'Ɋ' => 'ɋ',
+ 'Ɍ' => 'ɍ',
+ 'Ɏ' => 'ɏ',
+ 'Ͱ' => 'ͱ',
+ 'Ͳ' => 'ͳ',
+ 'Ͷ' => 'ͷ',
+ 'Ϳ' => 'ϳ',
+ 'Ά' => 'ά',
+ 'Έ' => 'έ',
+ 'Ή' => 'ή',
+ 'Ί' => 'ί',
+ 'Ό' => 'ό',
+ 'Ύ' => 'ύ',
+ 'Ώ' => 'ώ',
+ 'Α' => 'α',
+ 'Β' => 'β',
+ 'Γ' => 'γ',
+ 'Δ' => 'δ',
+ 'Ε' => 'ε',
+ 'Ζ' => 'ζ',
+ 'Η' => 'η',
+ 'Θ' => 'θ',
+ 'Ι' => 'ι',
+ 'Κ' => 'κ',
+ 'Λ' => 'λ',
+ 'Μ' => 'μ',
+ 'Ν' => 'ν',
+ 'Ξ' => 'ξ',
+ 'Ο' => 'ο',
+ 'Π' => 'π',
+ 'Ρ' => 'ρ',
+ 'Σ' => 'σ',
+ 'Τ' => 'τ',
+ 'Υ' => 'υ',
+ 'Φ' => 'φ',
+ 'Χ' => 'χ',
+ 'Ψ' => 'ψ',
+ 'Ω' => 'ω',
+ 'Ϊ' => 'ϊ',
+ 'Ϋ' => 'ϋ',
+ 'Ϗ' => 'ϗ',
+ 'Ϙ' => 'ϙ',
+ 'Ϛ' => 'ϛ',
+ 'Ϝ' => 'ϝ',
+ 'Ϟ' => 'ϟ',
+ 'Ϡ' => 'ϡ',
+ 'Ϣ' => 'ϣ',
+ 'Ϥ' => 'ϥ',
+ 'Ϧ' => 'ϧ',
+ 'Ϩ' => 'ϩ',
+ 'Ϫ' => 'ϫ',
+ 'Ϭ' => 'ϭ',
+ 'Ϯ' => 'ϯ',
+ 'ϴ' => 'θ',
+ 'Ϸ' => 'ϸ',
+ 'Ϲ' => 'ϲ',
+ 'Ϻ' => 'ϻ',
+ 'Ͻ' => 'ͻ',
+ 'Ͼ' => 'ͼ',
+ 'Ͽ' => 'ͽ',
+ 'Ѐ' => 'ѐ',
+ 'Ё' => 'ё',
+ 'Ђ' => 'ђ',
+ 'Ѓ' => 'ѓ',
+ 'Є' => 'є',
+ 'Ѕ' => 'ѕ',
+ 'І' => 'і',
+ 'Ї' => 'ї',
+ 'Ј' => 'ј',
+ 'Љ' => 'љ',
+ 'Њ' => 'њ',
+ 'Ћ' => 'ћ',
+ 'Ќ' => 'ќ',
+ 'Ѝ' => 'ѝ',
+ 'Ў' => 'ў',
+ 'Џ' => 'џ',
+ 'А' => 'а',
+ 'Б' => 'б',
+ 'В' => 'в',
+ 'Г' => 'г',
+ 'Д' => 'д',
+ 'Е' => 'е',
+ 'Ж' => 'ж',
+ 'З' => 'з',
+ 'И' => 'и',
+ 'Й' => 'й',
+ 'К' => 'к',
+ 'Л' => 'л',
+ 'М' => 'м',
+ 'Н' => 'н',
+ 'О' => 'о',
+ 'П' => 'п',
+ 'Р' => 'р',
+ 'С' => 'с',
+ 'Т' => 'т',
+ 'У' => 'у',
+ 'Ф' => 'ф',
+ 'Х' => 'х',
+ 'Ц' => 'ц',
+ 'Ч' => 'ч',
+ 'Ш' => 'ш',
+ 'Щ' => 'щ',
+ 'Ъ' => 'ъ',
+ 'Ы' => 'ы',
+ 'Ь' => 'ь',
+ 'Э' => 'э',
+ 'Ю' => 'ю',
+ 'Я' => 'я',
+ 'Ѡ' => 'ѡ',
+ 'Ѣ' => 'ѣ',
+ 'Ѥ' => 'ѥ',
+ 'Ѧ' => 'ѧ',
+ 'Ѩ' => 'ѩ',
+ 'Ѫ' => 'ѫ',
+ 'Ѭ' => 'ѭ',
+ 'Ѯ' => 'ѯ',
+ 'Ѱ' => 'ѱ',
+ 'Ѳ' => 'ѳ',
+ 'Ѵ' => 'ѵ',
+ 'Ѷ' => 'ѷ',
+ 'Ѹ' => 'ѹ',
+ 'Ѻ' => 'ѻ',
+ 'Ѽ' => 'ѽ',
+ 'Ѿ' => 'ѿ',
+ 'Ҁ' => 'ҁ',
+ 'Ҋ' => 'ҋ',
+ 'Ҍ' => 'ҍ',
+ 'Ҏ' => 'ҏ',
+ 'Ґ' => 'ґ',
+ 'Ғ' => 'ғ',
+ 'Ҕ' => 'ҕ',
+ 'Җ' => 'җ',
+ 'Ҙ' => 'ҙ',
+ 'Қ' => 'қ',
+ 'Ҝ' => 'ҝ',
+ 'Ҟ' => 'ҟ',
+ 'Ҡ' => 'ҡ',
+ 'Ң' => 'ң',
+ 'Ҥ' => 'ҥ',
+ 'Ҧ' => 'ҧ',
+ 'Ҩ' => 'ҩ',
+ 'Ҫ' => 'ҫ',
+ 'Ҭ' => 'ҭ',
+ 'Ү' => 'ү',
+ 'Ұ' => 'ұ',
+ 'Ҳ' => 'ҳ',
+ 'Ҵ' => 'ҵ',
+ 'Ҷ' => 'ҷ',
+ 'Ҹ' => 'ҹ',
+ 'Һ' => 'һ',
+ 'Ҽ' => 'ҽ',
+ 'Ҿ' => 'ҿ',
+ 'Ӏ' => 'ӏ',
+ 'Ӂ' => 'ӂ',
+ 'Ӄ' => 'ӄ',
+ 'Ӆ' => 'ӆ',
+ 'Ӈ' => 'ӈ',
+ 'Ӊ' => 'ӊ',
+ 'Ӌ' => 'ӌ',
+ 'Ӎ' => 'ӎ',
+ 'Ӑ' => 'ӑ',
+ 'Ӓ' => 'ӓ',
+ 'Ӕ' => 'ӕ',
+ 'Ӗ' => 'ӗ',
+ 'Ә' => 'ә',
+ 'Ӛ' => 'ӛ',
+ 'Ӝ' => 'ӝ',
+ 'Ӟ' => 'ӟ',
+ 'Ӡ' => 'ӡ',
+ 'Ӣ' => 'ӣ',
+ 'Ӥ' => 'ӥ',
+ 'Ӧ' => 'ӧ',
+ 'Ө' => 'ө',
+ 'Ӫ' => 'ӫ',
+ 'Ӭ' => 'ӭ',
+ 'Ӯ' => 'ӯ',
+ 'Ӱ' => 'ӱ',
+ 'Ӳ' => 'ӳ',
+ 'Ӵ' => 'ӵ',
+ 'Ӷ' => 'ӷ',
+ 'Ӹ' => 'ӹ',
+ 'Ӻ' => 'ӻ',
+ 'Ӽ' => 'ӽ',
+ 'Ӿ' => 'ӿ',
+ 'Ԁ' => 'ԁ',
+ 'Ԃ' => 'ԃ',
+ 'Ԅ' => 'ԅ',
+ 'Ԇ' => 'ԇ',
+ 'Ԉ' => 'ԉ',
+ 'Ԋ' => 'ԋ',
+ 'Ԍ' => 'ԍ',
+ 'Ԏ' => 'ԏ',
+ 'Ԑ' => 'ԑ',
+ 'Ԓ' => 'ԓ',
+ 'Ԕ' => 'ԕ',
+ 'Ԗ' => 'ԗ',
+ 'Ԙ' => 'ԙ',
+ 'Ԛ' => 'ԛ',
+ 'Ԝ' => 'ԝ',
+ 'Ԟ' => 'ԟ',
+ 'Ԡ' => 'ԡ',
+ 'Ԣ' => 'ԣ',
+ 'Ԥ' => 'ԥ',
+ 'Ԧ' => 'ԧ',
+ 'Ԩ' => 'ԩ',
+ 'Ԫ' => 'ԫ',
+ 'Ԭ' => 'ԭ',
+ 'Ԯ' => 'ԯ',
+ 'Ա' => 'ա',
+ 'Բ' => 'բ',
+ 'Գ' => 'գ',
+ 'Դ' => 'դ',
+ 'Ե' => 'ե',
+ 'Զ' => 'զ',
+ 'Է' => 'է',
+ 'Ը' => 'ը',
+ 'Թ' => 'թ',
+ 'Ժ' => 'ժ',
+ 'Ի' => 'ի',
+ 'Լ' => 'լ',
+ 'Խ' => 'խ',
+ 'Ծ' => 'ծ',
+ 'Կ' => 'կ',
+ 'Հ' => 'հ',
+ 'Ձ' => 'ձ',
+ 'Ղ' => 'ղ',
+ 'Ճ' => 'ճ',
+ 'Մ' => 'մ',
+ 'Յ' => 'յ',
+ 'Ն' => 'ն',
+ 'Շ' => 'շ',
+ 'Ո' => 'ո',
+ 'Չ' => 'չ',
+ 'Պ' => 'պ',
+ 'Ջ' => 'ջ',
+ 'Ռ' => 'ռ',
+ 'Ս' => 'ս',
+ 'Վ' => 'վ',
+ 'Տ' => 'տ',
+ 'Ր' => 'ր',
+ 'Ց' => 'ց',
+ 'Ւ' => 'ւ',
+ 'Փ' => 'փ',
+ 'Ք' => 'ք',
+ 'Օ' => 'օ',
+ 'Ֆ' => 'ֆ',
+ 'Ⴀ' => 'ⴀ',
+ 'Ⴁ' => 'ⴁ',
+ 'Ⴂ' => 'ⴂ',
+ 'Ⴃ' => 'ⴃ',
+ 'Ⴄ' => 'ⴄ',
+ 'Ⴅ' => 'ⴅ',
+ 'Ⴆ' => 'ⴆ',
+ 'Ⴇ' => 'ⴇ',
+ 'Ⴈ' => 'ⴈ',
+ 'Ⴉ' => 'ⴉ',
+ 'Ⴊ' => 'ⴊ',
+ 'Ⴋ' => 'ⴋ',
+ 'Ⴌ' => 'ⴌ',
+ 'Ⴍ' => 'ⴍ',
+ 'Ⴎ' => 'ⴎ',
+ 'Ⴏ' => 'ⴏ',
+ 'Ⴐ' => 'ⴐ',
+ 'Ⴑ' => 'ⴑ',
+ 'Ⴒ' => 'ⴒ',
+ 'Ⴓ' => 'ⴓ',
+ 'Ⴔ' => 'ⴔ',
+ 'Ⴕ' => 'ⴕ',
+ 'Ⴖ' => 'ⴖ',
+ 'Ⴗ' => 'ⴗ',
+ 'Ⴘ' => 'ⴘ',
+ 'Ⴙ' => 'ⴙ',
+ 'Ⴚ' => 'ⴚ',
+ 'Ⴛ' => 'ⴛ',
+ 'Ⴜ' => 'ⴜ',
+ 'Ⴝ' => 'ⴝ',
+ 'Ⴞ' => 'ⴞ',
+ 'Ⴟ' => 'ⴟ',
+ 'Ⴠ' => 'ⴠ',
+ 'Ⴡ' => 'ⴡ',
+ 'Ⴢ' => 'ⴢ',
+ 'Ⴣ' => 'ⴣ',
+ 'Ⴤ' => 'ⴤ',
+ 'Ⴥ' => 'ⴥ',
+ 'Ⴧ' => 'ⴧ',
+ 'Ⴭ' => 'ⴭ',
+ 'Ḁ' => 'ḁ',
+ 'Ḃ' => 'ḃ',
+ 'Ḅ' => 'ḅ',
+ 'Ḇ' => 'ḇ',
+ 'Ḉ' => 'ḉ',
+ 'Ḋ' => 'ḋ',
+ 'Ḍ' => 'ḍ',
+ 'Ḏ' => 'ḏ',
+ 'Ḑ' => 'ḑ',
+ 'Ḓ' => 'ḓ',
+ 'Ḕ' => 'ḕ',
+ 'Ḗ' => 'ḗ',
+ 'Ḙ' => 'ḙ',
+ 'Ḛ' => 'ḛ',
+ 'Ḝ' => 'ḝ',
+ 'Ḟ' => 'ḟ',
+ 'Ḡ' => 'ḡ',
+ 'Ḣ' => 'ḣ',
+ 'Ḥ' => 'ḥ',
+ 'Ḧ' => 'ḧ',
+ 'Ḩ' => 'ḩ',
+ 'Ḫ' => 'ḫ',
+ 'Ḭ' => 'ḭ',
+ 'Ḯ' => 'ḯ',
+ 'Ḱ' => 'ḱ',
+ 'Ḳ' => 'ḳ',
+ 'Ḵ' => 'ḵ',
+ 'Ḷ' => 'ḷ',
+ 'Ḹ' => 'ḹ',
+ 'Ḻ' => 'ḻ',
+ 'Ḽ' => 'ḽ',
+ 'Ḿ' => 'ḿ',
+ 'Ṁ' => 'ṁ',
+ 'Ṃ' => 'ṃ',
+ 'Ṅ' => 'ṅ',
+ 'Ṇ' => 'ṇ',
+ 'Ṉ' => 'ṉ',
+ 'Ṋ' => 'ṋ',
+ 'Ṍ' => 'ṍ',
+ 'Ṏ' => 'ṏ',
+ 'Ṑ' => 'ṑ',
+ 'Ṓ' => 'ṓ',
+ 'Ṕ' => 'ṕ',
+ 'Ṗ' => 'ṗ',
+ 'Ṙ' => 'ṙ',
+ 'Ṛ' => 'ṛ',
+ 'Ṝ' => 'ṝ',
+ 'Ṟ' => 'ṟ',
+ 'Ṡ' => 'ṡ',
+ 'Ṣ' => 'ṣ',
+ 'Ṥ' => 'ṥ',
+ 'Ṧ' => 'ṧ',
+ 'Ṩ' => 'ṩ',
+ 'Ṫ' => 'ṫ',
+ 'Ṭ' => 'ṭ',
+ 'Ṯ' => 'ṯ',
+ 'Ṱ' => 'ṱ',
+ 'Ṳ' => 'ṳ',
+ 'Ṵ' => 'ṵ',
+ 'Ṷ' => 'ṷ',
+ 'Ṹ' => 'ṹ',
+ 'Ṻ' => 'ṻ',
+ 'Ṽ' => 'ṽ',
+ 'Ṿ' => 'ṿ',
+ 'Ẁ' => 'ẁ',
+ 'Ẃ' => 'ẃ',
+ 'Ẅ' => 'ẅ',
+ 'Ẇ' => 'ẇ',
+ 'Ẉ' => 'ẉ',
+ 'Ẋ' => 'ẋ',
+ 'Ẍ' => 'ẍ',
+ 'Ẏ' => 'ẏ',
+ 'Ẑ' => 'ẑ',
+ 'Ẓ' => 'ẓ',
+ 'Ẕ' => 'ẕ',
+ 'ẞ' => 'ß',
+ 'Ạ' => 'ạ',
+ 'Ả' => 'ả',
+ 'Ấ' => 'ấ',
+ 'Ầ' => 'ầ',
+ 'Ẩ' => 'ẩ',
+ 'Ẫ' => 'ẫ',
+ 'Ậ' => 'ậ',
+ 'Ắ' => 'ắ',
+ 'Ằ' => 'ằ',
+ 'Ẳ' => 'ẳ',
+ 'Ẵ' => 'ẵ',
+ 'Ặ' => 'ặ',
+ 'Ẹ' => 'ẹ',
+ 'Ẻ' => 'ẻ',
+ 'Ẽ' => 'ẽ',
+ 'Ế' => 'ế',
+ 'Ề' => 'ề',
+ 'Ể' => 'ể',
+ 'Ễ' => 'ễ',
+ 'Ệ' => 'ệ',
+ 'Ỉ' => 'ỉ',
+ 'Ị' => 'ị',
+ 'Ọ' => 'ọ',
+ 'Ỏ' => 'ỏ',
+ 'Ố' => 'ố',
+ 'Ồ' => 'ồ',
+ 'Ổ' => 'ổ',
+ 'Ỗ' => 'ỗ',
+ 'Ộ' => 'ộ',
+ 'Ớ' => 'ớ',
+ 'Ờ' => 'ờ',
+ 'Ở' => 'ở',
+ 'Ỡ' => 'ỡ',
+ 'Ợ' => 'ợ',
+ 'Ụ' => 'ụ',
+ 'Ủ' => 'ủ',
+ 'Ứ' => 'ứ',
+ 'Ừ' => 'ừ',
+ 'Ử' => 'ử',
+ 'Ữ' => 'ữ',
+ 'Ự' => 'ự',
+ 'Ỳ' => 'ỳ',
+ 'Ỵ' => 'ỵ',
+ 'Ỷ' => 'ỷ',
+ 'Ỹ' => 'ỹ',
+ 'Ỻ' => 'ỻ',
+ 'Ỽ' => 'ỽ',
+ 'Ỿ' => 'ỿ',
+ 'Ἀ' => 'ἀ',
+ 'Ἁ' => 'ἁ',
+ 'Ἂ' => 'ἂ',
+ 'Ἃ' => 'ἃ',
+ 'Ἄ' => 'ἄ',
+ 'Ἅ' => 'ἅ',
+ 'Ἆ' => 'ἆ',
+ 'Ἇ' => 'ἇ',
+ 'Ἐ' => 'ἐ',
+ 'Ἑ' => 'ἑ',
+ 'Ἒ' => 'ἒ',
+ 'Ἓ' => 'ἓ',
+ 'Ἔ' => 'ἔ',
+ 'Ἕ' => 'ἕ',
+ 'Ἠ' => 'ἠ',
+ 'Ἡ' => 'ἡ',
+ 'Ἢ' => 'ἢ',
+ 'Ἣ' => 'ἣ',
+ 'Ἤ' => 'ἤ',
+ 'Ἥ' => 'ἥ',
+ 'Ἦ' => 'ἦ',
+ 'Ἧ' => 'ἧ',
+ 'Ἰ' => 'ἰ',
+ 'Ἱ' => 'ἱ',
+ 'Ἲ' => 'ἲ',
+ 'Ἳ' => 'ἳ',
+ 'Ἴ' => 'ἴ',
+ 'Ἵ' => 'ἵ',
+ 'Ἶ' => 'ἶ',
+ 'Ἷ' => 'ἷ',
+ 'Ὀ' => 'ὀ',
+ 'Ὁ' => 'ὁ',
+ 'Ὂ' => 'ὂ',
+ 'Ὃ' => 'ὃ',
+ 'Ὄ' => 'ὄ',
+ 'Ὅ' => 'ὅ',
+ 'Ὑ' => 'ὑ',
+ 'Ὓ' => 'ὓ',
+ 'Ὕ' => 'ὕ',
+ 'Ὗ' => 'ὗ',
+ 'Ὠ' => 'ὠ',
+ 'Ὡ' => 'ὡ',
+ 'Ὢ' => 'ὢ',
+ 'Ὣ' => 'ὣ',
+ 'Ὤ' => 'ὤ',
+ 'Ὥ' => 'ὥ',
+ 'Ὦ' => 'ὦ',
+ 'Ὧ' => 'ὧ',
+ 'ᾈ' => 'ᾀ',
+ 'ᾉ' => 'ᾁ',
+ 'ᾊ' => 'ᾂ',
+ 'ᾋ' => 'ᾃ',
+ 'ᾌ' => 'ᾄ',
+ 'ᾍ' => 'ᾅ',
+ 'ᾎ' => 'ᾆ',
+ 'ᾏ' => 'ᾇ',
+ 'ᾘ' => 'ᾐ',
+ 'ᾙ' => 'ᾑ',
+ 'ᾚ' => 'ᾒ',
+ 'ᾛ' => 'ᾓ',
+ 'ᾜ' => 'ᾔ',
+ 'ᾝ' => 'ᾕ',
+ 'ᾞ' => 'ᾖ',
+ 'ᾟ' => 'ᾗ',
+ 'ᾨ' => 'ᾠ',
+ 'ᾩ' => 'ᾡ',
+ 'ᾪ' => 'ᾢ',
+ 'ᾫ' => 'ᾣ',
+ 'ᾬ' => 'ᾤ',
+ 'ᾭ' => 'ᾥ',
+ 'ᾮ' => 'ᾦ',
+ 'ᾯ' => 'ᾧ',
+ 'Ᾰ' => 'ᾰ',
+ 'Ᾱ' => 'ᾱ',
+ 'Ὰ' => 'ὰ',
+ 'Ά' => 'ά',
+ 'ᾼ' => 'ᾳ',
+ 'Ὲ' => 'ὲ',
+ 'Έ' => 'έ',
+ 'Ὴ' => 'ὴ',
+ 'Ή' => 'ή',
+ 'ῌ' => 'ῃ',
+ 'Ῐ' => 'ῐ',
+ 'Ῑ' => 'ῑ',
+ 'Ὶ' => 'ὶ',
+ 'Ί' => 'ί',
+ 'Ῠ' => 'ῠ',
+ 'Ῡ' => 'ῡ',
+ 'Ὺ' => 'ὺ',
+ 'Ύ' => 'ύ',
+ 'Ῥ' => 'ῥ',
+ 'Ὸ' => 'ὸ',
+ 'Ό' => 'ό',
+ 'Ὼ' => 'ὼ',
+ 'Ώ' => 'ώ',
+ 'ῼ' => 'ῳ',
+ 'Ω' => 'ω',
+ 'K' => 'k',
+ 'Å' => 'å',
+ 'Ⅎ' => 'ⅎ',
+ 'Ⅰ' => 'ⅰ',
+ 'Ⅱ' => 'ⅱ',
+ 'Ⅲ' => 'ⅲ',
+ 'Ⅳ' => 'ⅳ',
+ 'Ⅴ' => 'ⅴ',
+ 'Ⅵ' => 'ⅵ',
+ 'Ⅶ' => 'ⅶ',
+ 'Ⅷ' => 'ⅷ',
+ 'Ⅸ' => 'ⅸ',
+ 'Ⅹ' => 'ⅹ',
+ 'Ⅺ' => 'ⅺ',
+ 'Ⅻ' => 'ⅻ',
+ 'Ⅼ' => 'ⅼ',
+ 'Ⅽ' => 'ⅽ',
+ 'Ⅾ' => 'ⅾ',
+ 'Ⅿ' => 'ⅿ',
+ 'Ↄ' => 'ↄ',
+ 'Ⓐ' => 'ⓐ',
+ 'Ⓑ' => 'ⓑ',
+ 'Ⓒ' => 'ⓒ',
+ 'Ⓓ' => 'ⓓ',
+ 'Ⓔ' => 'ⓔ',
+ 'Ⓕ' => 'ⓕ',
+ 'Ⓖ' => 'ⓖ',
+ 'Ⓗ' => 'ⓗ',
+ 'Ⓘ' => 'ⓘ',
+ 'Ⓙ' => 'ⓙ',
+ 'Ⓚ' => 'ⓚ',
+ 'Ⓛ' => 'ⓛ',
+ 'Ⓜ' => 'ⓜ',
+ 'Ⓝ' => 'ⓝ',
+ 'Ⓞ' => 'ⓞ',
+ 'Ⓟ' => 'ⓟ',
+ 'Ⓠ' => 'ⓠ',
+ 'Ⓡ' => 'ⓡ',
+ 'Ⓢ' => 'ⓢ',
+ 'Ⓣ' => 'ⓣ',
+ 'Ⓤ' => 'ⓤ',
+ 'Ⓥ' => 'ⓥ',
+ 'Ⓦ' => 'ⓦ',
+ 'Ⓧ' => 'ⓧ',
+ 'Ⓨ' => 'ⓨ',
+ 'Ⓩ' => 'ⓩ',
+ 'Ⰰ' => 'ⰰ',
+ 'Ⰱ' => 'ⰱ',
+ 'Ⰲ' => 'ⰲ',
+ 'Ⰳ' => 'ⰳ',
+ 'Ⰴ' => 'ⰴ',
+ 'Ⰵ' => 'ⰵ',
+ 'Ⰶ' => 'ⰶ',
+ 'Ⰷ' => 'ⰷ',
+ 'Ⰸ' => 'ⰸ',
+ 'Ⰹ' => 'ⰹ',
+ 'Ⰺ' => 'ⰺ',
+ 'Ⰻ' => 'ⰻ',
+ 'Ⰼ' => 'ⰼ',
+ 'Ⰽ' => 'ⰽ',
+ 'Ⰾ' => 'ⰾ',
+ 'Ⰿ' => 'ⰿ',
+ 'Ⱀ' => 'ⱀ',
+ 'Ⱁ' => 'ⱁ',
+ 'Ⱂ' => 'ⱂ',
+ 'Ⱃ' => 'ⱃ',
+ 'Ⱄ' => 'ⱄ',
+ 'Ⱅ' => 'ⱅ',
+ 'Ⱆ' => 'ⱆ',
+ 'Ⱇ' => 'ⱇ',
+ 'Ⱈ' => 'ⱈ',
+ 'Ⱉ' => 'ⱉ',
+ 'Ⱊ' => 'ⱊ',
+ 'Ⱋ' => 'ⱋ',
+ 'Ⱌ' => 'ⱌ',
+ 'Ⱍ' => 'ⱍ',
+ 'Ⱎ' => 'ⱎ',
+ 'Ⱏ' => 'ⱏ',
+ 'Ⱐ' => 'ⱐ',
+ 'Ⱑ' => 'ⱑ',
+ 'Ⱒ' => 'ⱒ',
+ 'Ⱓ' => 'ⱓ',
+ 'Ⱔ' => 'ⱔ',
+ 'Ⱕ' => 'ⱕ',
+ 'Ⱖ' => 'ⱖ',
+ 'Ⱗ' => 'ⱗ',
+ 'Ⱘ' => 'ⱘ',
+ 'Ⱙ' => 'ⱙ',
+ 'Ⱚ' => 'ⱚ',
+ 'Ⱛ' => 'ⱛ',
+ 'Ⱜ' => 'ⱜ',
+ 'Ⱝ' => 'ⱝ',
+ 'Ⱞ' => 'ⱞ',
+ 'Ⱡ' => 'ⱡ',
+ 'Ɫ' => 'ɫ',
+ 'Ᵽ' => 'ᵽ',
+ 'Ɽ' => 'ɽ',
+ 'Ⱨ' => 'ⱨ',
+ 'Ⱪ' => 'ⱪ',
+ 'Ⱬ' => 'ⱬ',
+ 'Ɑ' => 'ɑ',
+ 'Ɱ' => 'ɱ',
+ 'Ɐ' => 'ɐ',
+ 'Ɒ' => 'ɒ',
+ 'Ⱳ' => 'ⱳ',
+ 'Ⱶ' => 'ⱶ',
+ 'Ȿ' => 'ȿ',
+ 'Ɀ' => 'ɀ',
+ 'Ⲁ' => 'ⲁ',
+ 'Ⲃ' => 'ⲃ',
+ 'Ⲅ' => 'ⲅ',
+ 'Ⲇ' => 'ⲇ',
+ 'Ⲉ' => 'ⲉ',
+ 'Ⲋ' => 'ⲋ',
+ 'Ⲍ' => 'ⲍ',
+ 'Ⲏ' => 'ⲏ',
+ 'Ⲑ' => 'ⲑ',
+ 'Ⲓ' => 'ⲓ',
+ 'Ⲕ' => 'ⲕ',
+ 'Ⲗ' => 'ⲗ',
+ 'Ⲙ' => 'ⲙ',
+ 'Ⲛ' => 'ⲛ',
+ 'Ⲝ' => 'ⲝ',
+ 'Ⲟ' => 'ⲟ',
+ 'Ⲡ' => 'ⲡ',
+ 'Ⲣ' => 'ⲣ',
+ 'Ⲥ' => 'ⲥ',
+ 'Ⲧ' => 'ⲧ',
+ 'Ⲩ' => 'ⲩ',
+ 'Ⲫ' => 'ⲫ',
+ 'Ⲭ' => 'ⲭ',
+ 'Ⲯ' => 'ⲯ',
+ 'Ⲱ' => 'ⲱ',
+ 'Ⲳ' => 'ⲳ',
+ 'Ⲵ' => 'ⲵ',
+ 'Ⲷ' => 'ⲷ',
+ 'Ⲹ' => 'ⲹ',
+ 'Ⲻ' => 'ⲻ',
+ 'Ⲽ' => 'ⲽ',
+ 'Ⲿ' => 'ⲿ',
+ 'Ⳁ' => 'ⳁ',
+ 'Ⳃ' => 'ⳃ',
+ 'Ⳅ' => 'ⳅ',
+ 'Ⳇ' => 'ⳇ',
+ 'Ⳉ' => 'ⳉ',
+ 'Ⳋ' => 'ⳋ',
+ 'Ⳍ' => 'ⳍ',
+ 'Ⳏ' => 'ⳏ',
+ 'Ⳑ' => 'ⳑ',
+ 'Ⳓ' => 'ⳓ',
+ 'Ⳕ' => 'ⳕ',
+ 'Ⳗ' => 'ⳗ',
+ 'Ⳙ' => 'ⳙ',
+ 'Ⳛ' => 'ⳛ',
+ 'Ⳝ' => 'ⳝ',
+ 'Ⳟ' => 'ⳟ',
+ 'Ⳡ' => 'ⳡ',
+ 'Ⳣ' => 'ⳣ',
+ 'Ⳬ' => 'ⳬ',
+ 'Ⳮ' => 'ⳮ',
+ 'Ⳳ' => 'ⳳ',
+ 'Ꙁ' => 'ꙁ',
+ 'Ꙃ' => 'ꙃ',
+ 'Ꙅ' => 'ꙅ',
+ 'Ꙇ' => 'ꙇ',
+ 'Ꙉ' => 'ꙉ',
+ 'Ꙋ' => 'ꙋ',
+ 'Ꙍ' => 'ꙍ',
+ 'Ꙏ' => 'ꙏ',
+ 'Ꙑ' => 'ꙑ',
+ 'Ꙓ' => 'ꙓ',
+ 'Ꙕ' => 'ꙕ',
+ 'Ꙗ' => 'ꙗ',
+ 'Ꙙ' => 'ꙙ',
+ 'Ꙛ' => 'ꙛ',
+ 'Ꙝ' => 'ꙝ',
+ 'Ꙟ' => 'ꙟ',
+ 'Ꙡ' => 'ꙡ',
+ 'Ꙣ' => 'ꙣ',
+ 'Ꙥ' => 'ꙥ',
+ 'Ꙧ' => 'ꙧ',
+ 'Ꙩ' => 'ꙩ',
+ 'Ꙫ' => 'ꙫ',
+ 'Ꙭ' => 'ꙭ',
+ 'Ꚁ' => 'ꚁ',
+ 'Ꚃ' => 'ꚃ',
+ 'Ꚅ' => 'ꚅ',
+ 'Ꚇ' => 'ꚇ',
+ 'Ꚉ' => 'ꚉ',
+ 'Ꚋ' => 'ꚋ',
+ 'Ꚍ' => 'ꚍ',
+ 'Ꚏ' => 'ꚏ',
+ 'Ꚑ' => 'ꚑ',
+ 'Ꚓ' => 'ꚓ',
+ 'Ꚕ' => 'ꚕ',
+ 'Ꚗ' => 'ꚗ',
+ 'Ꚙ' => 'ꚙ',
+ 'Ꚛ' => 'ꚛ',
+ 'Ꜣ' => 'ꜣ',
+ 'Ꜥ' => 'ꜥ',
+ 'Ꜧ' => 'ꜧ',
+ 'Ꜩ' => 'ꜩ',
+ 'Ꜫ' => 'ꜫ',
+ 'Ꜭ' => 'ꜭ',
+ 'Ꜯ' => 'ꜯ',
+ 'Ꜳ' => 'ꜳ',
+ 'Ꜵ' => 'ꜵ',
+ 'Ꜷ' => 'ꜷ',
+ 'Ꜹ' => 'ꜹ',
+ 'Ꜻ' => 'ꜻ',
+ 'Ꜽ' => 'ꜽ',
+ 'Ꜿ' => 'ꜿ',
+ 'Ꝁ' => 'ꝁ',
+ 'Ꝃ' => 'ꝃ',
+ 'Ꝅ' => 'ꝅ',
+ 'Ꝇ' => 'ꝇ',
+ 'Ꝉ' => 'ꝉ',
+ 'Ꝋ' => 'ꝋ',
+ 'Ꝍ' => 'ꝍ',
+ 'Ꝏ' => 'ꝏ',
+ 'Ꝑ' => 'ꝑ',
+ 'Ꝓ' => 'ꝓ',
+ 'Ꝕ' => 'ꝕ',
+ 'Ꝗ' => 'ꝗ',
+ 'Ꝙ' => 'ꝙ',
+ 'Ꝛ' => 'ꝛ',
+ 'Ꝝ' => 'ꝝ',
+ 'Ꝟ' => 'ꝟ',
+ 'Ꝡ' => 'ꝡ',
+ 'Ꝣ' => 'ꝣ',
+ 'Ꝥ' => 'ꝥ',
+ 'Ꝧ' => 'ꝧ',
+ 'Ꝩ' => 'ꝩ',
+ 'Ꝫ' => 'ꝫ',
+ 'Ꝭ' => 'ꝭ',
+ 'Ꝯ' => 'ꝯ',
+ 'Ꝺ' => 'ꝺ',
+ 'Ꝼ' => 'ꝼ',
+ 'Ᵹ' => 'ᵹ',
+ 'Ꝿ' => 'ꝿ',
+ 'Ꞁ' => 'ꞁ',
+ 'Ꞃ' => 'ꞃ',
+ 'Ꞅ' => 'ꞅ',
+ 'Ꞇ' => 'ꞇ',
+ 'Ꞌ' => 'ꞌ',
+ 'Ɥ' => 'ɥ',
+ 'Ꞑ' => 'ꞑ',
+ 'Ꞓ' => 'ꞓ',
+ 'Ꞗ' => 'ꞗ',
+ 'Ꞙ' => 'ꞙ',
+ 'Ꞛ' => 'ꞛ',
+ 'Ꞝ' => 'ꞝ',
+ 'Ꞟ' => 'ꞟ',
+ 'Ꞡ' => 'ꞡ',
+ 'Ꞣ' => 'ꞣ',
+ 'Ꞥ' => 'ꞥ',
+ 'Ꞧ' => 'ꞧ',
+ 'Ꞩ' => 'ꞩ',
+ 'Ɦ' => 'ɦ',
+ 'Ɜ' => 'ɜ',
+ 'Ɡ' => 'ɡ',
+ 'Ɬ' => 'ɬ',
+ 'Ʞ' => 'ʞ',
+ 'Ʇ' => 'ʇ',
+ 'A' => 'a',
+ 'B' => 'b',
+ 'C' => 'c',
+ 'D' => 'd',
+ 'E' => 'e',
+ 'F' => 'f',
+ 'G' => 'g',
+ 'H' => 'h',
+ 'I' => 'i',
+ 'J' => 'j',
+ 'K' => 'k',
+ 'L' => 'l',
+ 'M' => 'm',
+ 'N' => 'n',
+ 'O' => 'o',
+ 'P' => 'p',
+ 'Q' => 'q',
+ 'R' => 'r',
+ 'S' => 's',
+ 'T' => 't',
+ 'U' => 'u',
+ 'V' => 'v',
+ 'W' => 'w',
+ 'X' => 'x',
+ 'Y' => 'y',
+ 'Z' => 'z',
+ '𐐀' => '𐐨',
+ '𐐁' => '𐐩',
+ '𐐂' => '𐐪',
+ '𐐃' => '𐐫',
+ '𐐄' => '𐐬',
+ '𐐅' => '𐐭',
+ '𐐆' => '𐐮',
+ '𐐇' => '𐐯',
+ '𐐈' => '𐐰',
+ '𐐉' => '𐐱',
+ '𐐊' => '𐐲',
+ '𐐋' => '𐐳',
+ '𐐌' => '𐐴',
+ '𐐍' => '𐐵',
+ '𐐎' => '𐐶',
+ '𐐏' => '𐐷',
+ '𐐐' => '𐐸',
+ '𐐑' => '𐐹',
+ '𐐒' => '𐐺',
+ '𐐓' => '𐐻',
+ '𐐔' => '𐐼',
+ '𐐕' => '𐐽',
+ '𐐖' => '𐐾',
+ '𐐗' => '𐐿',
+ '𐐘' => '𐑀',
+ '𐐙' => '𐑁',
+ '𐐚' => '𐑂',
+ '𐐛' => '𐑃',
+ '𐐜' => '𐑄',
+ '𐐝' => '𐑅',
+ '𐐞' => '𐑆',
+ '𐐟' => '𐑇',
+ '𐐠' => '𐑈',
+ '𐐡' => '𐑉',
+ '𐐢' => '𐑊',
+ '𐐣' => '𐑋',
+ '𐐤' => '𐑌',
+ '𐐥' => '𐑍',
+ '𐐦' => '𐑎',
+ '𐐧' => '𐑏',
+ '𑢠' => '𑣀',
+ '𑢡' => '𑣁',
+ '𑢢' => '𑣂',
+ '𑢣' => '𑣃',
+ '𑢤' => '𑣄',
+ '𑢥' => '𑣅',
+ '𑢦' => '𑣆',
+ '𑢧' => '𑣇',
+ '𑢨' => '𑣈',
+ '𑢩' => '𑣉',
+ '𑢪' => '𑣊',
+ '𑢫' => '𑣋',
+ '𑢬' => '𑣌',
+ '𑢭' => '𑣍',
+ '𑢮' => '𑣎',
+ '𑢯' => '𑣏',
+ '𑢰' => '𑣐',
+ '𑢱' => '𑣑',
+ '𑢲' => '𑣒',
+ '𑢳' => '𑣓',
+ '𑢴' => '𑣔',
+ '𑢵' => '𑣕',
+ '𑢶' => '𑣖',
+ '𑢷' => '𑣗',
+ '𑢸' => '𑣘',
+ '𑢹' => '𑣙',
+ '𑢺' => '𑣚',
+ '𑢻' => '𑣛',
+ '𑢼' => '𑣜',
+ '𑢽' => '𑣝',
+ '𑢾' => '𑣞',
+ '𑢿' => '𑣟',
+);
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
new file mode 100644
index 0000000..2a8f6e7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
@@ -0,0 +1,5 @@
+<?php
+
+// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
+
+return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php b/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
new file mode 100644
index 0000000..b8103b2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
@@ -0,0 +1,1104 @@
+<?php
+
+return array(
+ 'a' => 'A',
+ 'b' => 'B',
+ 'c' => 'C',
+ 'd' => 'D',
+ 'e' => 'E',
+ 'f' => 'F',
+ 'g' => 'G',
+ 'h' => 'H',
+ 'i' => 'I',
+ 'j' => 'J',
+ 'k' => 'K',
+ 'l' => 'L',
+ 'm' => 'M',
+ 'n' => 'N',
+ 'o' => 'O',
+ 'p' => 'P',
+ 'q' => 'Q',
+ 'r' => 'R',
+ 's' => 'S',
+ 't' => 'T',
+ 'u' => 'U',
+ 'v' => 'V',
+ 'w' => 'W',
+ 'x' => 'X',
+ 'y' => 'Y',
+ 'z' => 'Z',
+ 'µ' => 'Μ',
+ 'à' => 'À',
+ 'á' => 'Á',
+ 'â' => 'Â',
+ 'ã' => 'Ã',
+ 'ä' => 'Ä',
+ 'å' => 'Å',
+ 'æ' => 'Æ',
+ 'ç' => 'Ç',
+ 'è' => 'È',
+ 'é' => 'É',
+ 'ê' => 'Ê',
+ 'ë' => 'Ë',
+ 'ì' => 'Ì',
+ 'í' => 'Í',
+ 'î' => 'Î',
+ 'ï' => 'Ï',
+ 'ð' => 'Ð',
+ 'ñ' => 'Ñ',
+ 'ò' => 'Ò',
+ 'ó' => 'Ó',
+ 'ô' => 'Ô',
+ 'õ' => 'Õ',
+ 'ö' => 'Ö',
+ 'ø' => 'Ø',
+ 'ù' => 'Ù',
+ 'ú' => 'Ú',
+ 'û' => 'Û',
+ 'ü' => 'Ü',
+ 'ý' => 'Ý',
+ 'þ' => 'Þ',
+ 'ÿ' => 'Ÿ',
+ 'ā' => 'Ā',
+ 'ă' => 'Ă',
+ 'ą' => 'Ą',
+ 'ć' => 'Ć',
+ 'ĉ' => 'Ĉ',
+ 'ċ' => 'Ċ',
+ 'č' => 'Č',
+ 'ď' => 'Ď',
+ 'đ' => 'Đ',
+ 'ē' => 'Ē',
+ 'ĕ' => 'Ĕ',
+ 'ė' => 'Ė',
+ 'ę' => 'Ę',
+ 'ě' => 'Ě',
+ 'ĝ' => 'Ĝ',
+ 'ğ' => 'Ğ',
+ 'ġ' => 'Ġ',
+ 'ģ' => 'Ģ',
+ 'ĥ' => 'Ĥ',
+ 'ħ' => 'Ħ',
+ 'ĩ' => 'Ĩ',
+ 'ī' => 'Ī',
+ 'ĭ' => 'Ĭ',
+ 'į' => 'Į',
+ 'ı' => 'I',
+ 'ij' => 'IJ',
+ 'ĵ' => 'Ĵ',
+ 'ķ' => 'Ķ',
+ 'ĺ' => 'Ĺ',
+ 'ļ' => 'Ļ',
+ 'ľ' => 'Ľ',
+ 'ŀ' => 'Ŀ',
+ 'ł' => 'Ł',
+ 'ń' => 'Ń',
+ 'ņ' => 'Ņ',
+ 'ň' => 'Ň',
+ 'ŋ' => 'Ŋ',
+ 'ō' => 'Ō',
+ 'ŏ' => 'Ŏ',
+ 'ő' => 'Ő',
+ 'œ' => 'Œ',
+ 'ŕ' => 'Ŕ',
+ 'ŗ' => 'Ŗ',
+ 'ř' => 'Ř',
+ 'ś' => 'Ś',
+ 'ŝ' => 'Ŝ',
+ 'ş' => 'Ş',
+ 'š' => 'Š',
+ 'ţ' => 'Ţ',
+ 'ť' => 'Ť',
+ 'ŧ' => 'Ŧ',
+ 'ũ' => 'Ũ',
+ 'ū' => 'Ū',
+ 'ŭ' => 'Ŭ',
+ 'ů' => 'Ů',
+ 'ű' => 'Ű',
+ 'ų' => 'Ų',
+ 'ŵ' => 'Ŵ',
+ 'ŷ' => 'Ŷ',
+ 'ź' => 'Ź',
+ 'ż' => 'Ż',
+ 'ž' => 'Ž',
+ 'ſ' => 'S',
+ 'ƀ' => 'Ƀ',
+ 'ƃ' => 'Ƃ',
+ 'ƅ' => 'Ƅ',
+ 'ƈ' => 'Ƈ',
+ 'ƌ' => 'Ƌ',
+ 'ƒ' => 'Ƒ',
+ 'ƕ' => 'Ƕ',
+ 'ƙ' => 'Ƙ',
+ 'ƚ' => 'Ƚ',
+ 'ƞ' => 'Ƞ',
+ 'ơ' => 'Ơ',
+ 'ƣ' => 'Ƣ',
+ 'ƥ' => 'Ƥ',
+ 'ƨ' => 'Ƨ',
+ 'ƭ' => 'Ƭ',
+ 'ư' => 'Ư',
+ 'ƴ' => 'Ƴ',
+ 'ƶ' => 'Ƶ',
+ 'ƹ' => 'Ƹ',
+ 'ƽ' => 'Ƽ',
+ 'ƿ' => 'Ƿ',
+ 'Dž' => 'DŽ',
+ 'dž' => 'DŽ',
+ 'Lj' => 'LJ',
+ 'lj' => 'LJ',
+ 'Nj' => 'NJ',
+ 'nj' => 'NJ',
+ 'ǎ' => 'Ǎ',
+ 'ǐ' => 'Ǐ',
+ 'ǒ' => 'Ǒ',
+ 'ǔ' => 'Ǔ',
+ 'ǖ' => 'Ǖ',
+ 'ǘ' => 'Ǘ',
+ 'ǚ' => 'Ǚ',
+ 'ǜ' => 'Ǜ',
+ 'ǝ' => 'Ǝ',
+ 'ǟ' => 'Ǟ',
+ 'ǡ' => 'Ǡ',
+ 'ǣ' => 'Ǣ',
+ 'ǥ' => 'Ǥ',
+ 'ǧ' => 'Ǧ',
+ 'ǩ' => 'Ǩ',
+ 'ǫ' => 'Ǫ',
+ 'ǭ' => 'Ǭ',
+ 'ǯ' => 'Ǯ',
+ 'Dz' => 'DZ',
+ 'dz' => 'DZ',
+ 'ǵ' => 'Ǵ',
+ 'ǹ' => 'Ǹ',
+ 'ǻ' => 'Ǻ',
+ 'ǽ' => 'Ǽ',
+ 'ǿ' => 'Ǿ',
+ 'ȁ' => 'Ȁ',
+ 'ȃ' => 'Ȃ',
+ 'ȅ' => 'Ȅ',
+ 'ȇ' => 'Ȇ',
+ 'ȉ' => 'Ȉ',
+ 'ȋ' => 'Ȋ',
+ 'ȍ' => 'Ȍ',
+ 'ȏ' => 'Ȏ',
+ 'ȑ' => 'Ȑ',
+ 'ȓ' => 'Ȓ',
+ 'ȕ' => 'Ȕ',
+ 'ȗ' => 'Ȗ',
+ 'ș' => 'Ș',
+ 'ț' => 'Ț',
+ 'ȝ' => 'Ȝ',
+ 'ȟ' => 'Ȟ',
+ 'ȣ' => 'Ȣ',
+ 'ȥ' => 'Ȥ',
+ 'ȧ' => 'Ȧ',
+ 'ȩ' => 'Ȩ',
+ 'ȫ' => 'Ȫ',
+ 'ȭ' => 'Ȭ',
+ 'ȯ' => 'Ȯ',
+ 'ȱ' => 'Ȱ',
+ 'ȳ' => 'Ȳ',
+ 'ȼ' => 'Ȼ',
+ 'ȿ' => 'Ȿ',
+ 'ɀ' => 'Ɀ',
+ 'ɂ' => 'Ɂ',
+ 'ɇ' => 'Ɇ',
+ 'ɉ' => 'Ɉ',
+ 'ɋ' => 'Ɋ',
+ 'ɍ' => 'Ɍ',
+ 'ɏ' => 'Ɏ',
+ 'ɐ' => 'Ɐ',
+ 'ɑ' => 'Ɑ',
+ 'ɒ' => 'Ɒ',
+ 'ɓ' => 'Ɓ',
+ 'ɔ' => 'Ɔ',
+ 'ɖ' => 'Ɖ',
+ 'ɗ' => 'Ɗ',
+ 'ə' => 'Ə',
+ 'ɛ' => 'Ɛ',
+ 'ɜ' => 'Ɜ',
+ 'ɠ' => 'Ɠ',
+ 'ɡ' => 'Ɡ',
+ 'ɣ' => 'Ɣ',
+ 'ɥ' => 'Ɥ',
+ 'ɦ' => 'Ɦ',
+ 'ɨ' => 'Ɨ',
+ 'ɩ' => 'Ɩ',
+ 'ɫ' => 'Ɫ',
+ 'ɬ' => 'Ɬ',
+ 'ɯ' => 'Ɯ',
+ 'ɱ' => 'Ɱ',
+ 'ɲ' => 'Ɲ',
+ 'ɵ' => 'Ɵ',
+ 'ɽ' => 'Ɽ',
+ 'ʀ' => 'Ʀ',
+ 'ʃ' => 'Ʃ',
+ 'ʇ' => 'Ʇ',
+ 'ʈ' => 'Ʈ',
+ 'ʉ' => 'Ʉ',
+ 'ʊ' => 'Ʊ',
+ 'ʋ' => 'Ʋ',
+ 'ʌ' => 'Ʌ',
+ 'ʒ' => 'Ʒ',
+ 'ʞ' => 'Ʞ',
+ 'ͅ' => 'Ι',
+ 'ͱ' => 'Ͱ',
+ 'ͳ' => 'Ͳ',
+ 'ͷ' => 'Ͷ',
+ 'ͻ' => 'Ͻ',
+ 'ͼ' => 'Ͼ',
+ 'ͽ' => 'Ͽ',
+ 'ά' => 'Ά',
+ 'έ' => 'Έ',
+ 'ή' => 'Ή',
+ 'ί' => 'Ί',
+ 'α' => 'Α',
+ 'β' => 'Β',
+ 'γ' => 'Γ',
+ 'δ' => 'Δ',
+ 'ε' => 'Ε',
+ 'ζ' => 'Ζ',
+ 'η' => 'Η',
+ 'θ' => 'Θ',
+ 'ι' => 'Ι',
+ 'κ' => 'Κ',
+ 'λ' => 'Λ',
+ 'μ' => 'Μ',
+ 'ν' => 'Ν',
+ 'ξ' => 'Ξ',
+ 'ο' => 'Ο',
+ 'π' => 'Π',
+ 'ρ' => 'Ρ',
+ 'ς' => 'Σ',
+ 'σ' => 'Σ',
+ 'τ' => 'Τ',
+ 'υ' => 'Υ',
+ 'φ' => 'Φ',
+ 'χ' => 'Χ',
+ 'ψ' => 'Ψ',
+ 'ω' => 'Ω',
+ 'ϊ' => 'Ϊ',
+ 'ϋ' => 'Ϋ',
+ 'ό' => 'Ό',
+ 'ύ' => 'Ύ',
+ 'ώ' => 'Ώ',
+ 'ϐ' => 'Β',
+ 'ϑ' => 'Θ',
+ 'ϕ' => 'Φ',
+ 'ϖ' => 'Π',
+ 'ϗ' => 'Ϗ',
+ 'ϙ' => 'Ϙ',
+ 'ϛ' => 'Ϛ',
+ 'ϝ' => 'Ϝ',
+ 'ϟ' => 'Ϟ',
+ 'ϡ' => 'Ϡ',
+ 'ϣ' => 'Ϣ',
+ 'ϥ' => 'Ϥ',
+ 'ϧ' => 'Ϧ',
+ 'ϩ' => 'Ϩ',
+ 'ϫ' => 'Ϫ',
+ 'ϭ' => 'Ϭ',
+ 'ϯ' => 'Ϯ',
+ 'ϰ' => 'Κ',
+ 'ϱ' => 'Ρ',
+ 'ϲ' => 'Ϲ',
+ 'ϳ' => 'Ϳ',
+ 'ϵ' => 'Ε',
+ 'ϸ' => 'Ϸ',
+ 'ϻ' => 'Ϻ',
+ 'а' => 'А',
+ 'б' => 'Б',
+ 'в' => 'В',
+ 'г' => 'Г',
+ 'д' => 'Д',
+ 'е' => 'Е',
+ 'ж' => 'Ж',
+ 'з' => 'З',
+ 'и' => 'И',
+ 'й' => 'Й',
+ 'к' => 'К',
+ 'л' => 'Л',
+ 'м' => 'М',
+ 'н' => 'Н',
+ 'о' => 'О',
+ 'п' => 'П',
+ 'р' => 'Р',
+ 'с' => 'С',
+ 'т' => 'Т',
+ 'у' => 'У',
+ 'ф' => 'Ф',
+ 'х' => 'Х',
+ 'ц' => 'Ц',
+ 'ч' => 'Ч',
+ 'ш' => 'Ш',
+ 'щ' => 'Щ',
+ 'ъ' => 'Ъ',
+ 'ы' => 'Ы',
+ 'ь' => 'Ь',
+ 'э' => 'Э',
+ 'ю' => 'Ю',
+ 'я' => 'Я',
+ 'ѐ' => 'Ѐ',
+ 'ё' => 'Ё',
+ 'ђ' => 'Ђ',
+ 'ѓ' => 'Ѓ',
+ 'є' => 'Є',
+ 'ѕ' => 'Ѕ',
+ 'і' => 'І',
+ 'ї' => 'Ї',
+ 'ј' => 'Ј',
+ 'љ' => 'Љ',
+ 'њ' => 'Њ',
+ 'ћ' => 'Ћ',
+ 'ќ' => 'Ќ',
+ 'ѝ' => 'Ѝ',
+ 'ў' => 'Ў',
+ 'џ' => 'Џ',
+ 'ѡ' => 'Ѡ',
+ 'ѣ' => 'Ѣ',
+ 'ѥ' => 'Ѥ',
+ 'ѧ' => 'Ѧ',
+ 'ѩ' => 'Ѩ',
+ 'ѫ' => 'Ѫ',
+ 'ѭ' => 'Ѭ',
+ 'ѯ' => 'Ѯ',
+ 'ѱ' => 'Ѱ',
+ 'ѳ' => 'Ѳ',
+ 'ѵ' => 'Ѵ',
+ 'ѷ' => 'Ѷ',
+ 'ѹ' => 'Ѹ',
+ 'ѻ' => 'Ѻ',
+ 'ѽ' => 'Ѽ',
+ 'ѿ' => 'Ѿ',
+ 'ҁ' => 'Ҁ',
+ 'ҋ' => 'Ҋ',
+ 'ҍ' => 'Ҍ',
+ 'ҏ' => 'Ҏ',
+ 'ґ' => 'Ґ',
+ 'ғ' => 'Ғ',
+ 'ҕ' => 'Ҕ',
+ 'җ' => 'Җ',
+ 'ҙ' => 'Ҙ',
+ 'қ' => 'Қ',
+ 'ҝ' => 'Ҝ',
+ 'ҟ' => 'Ҟ',
+ 'ҡ' => 'Ҡ',
+ 'ң' => 'Ң',
+ 'ҥ' => 'Ҥ',
+ 'ҧ' => 'Ҧ',
+ 'ҩ' => 'Ҩ',
+ 'ҫ' => 'Ҫ',
+ 'ҭ' => 'Ҭ',
+ 'ү' => 'Ү',
+ 'ұ' => 'Ұ',
+ 'ҳ' => 'Ҳ',
+ 'ҵ' => 'Ҵ',
+ 'ҷ' => 'Ҷ',
+ 'ҹ' => 'Ҹ',
+ 'һ' => 'Һ',
+ 'ҽ' => 'Ҽ',
+ 'ҿ' => 'Ҿ',
+ 'ӂ' => 'Ӂ',
+ 'ӄ' => 'Ӄ',
+ 'ӆ' => 'Ӆ',
+ 'ӈ' => 'Ӈ',
+ 'ӊ' => 'Ӊ',
+ 'ӌ' => 'Ӌ',
+ 'ӎ' => 'Ӎ',
+ 'ӏ' => 'Ӏ',
+ 'ӑ' => 'Ӑ',
+ 'ӓ' => 'Ӓ',
+ 'ӕ' => 'Ӕ',
+ 'ӗ' => 'Ӗ',
+ 'ә' => 'Ә',
+ 'ӛ' => 'Ӛ',
+ 'ӝ' => 'Ӝ',
+ 'ӟ' => 'Ӟ',
+ 'ӡ' => 'Ӡ',
+ 'ӣ' => 'Ӣ',
+ 'ӥ' => 'Ӥ',
+ 'ӧ' => 'Ӧ',
+ 'ө' => 'Ө',
+ 'ӫ' => 'Ӫ',
+ 'ӭ' => 'Ӭ',
+ 'ӯ' => 'Ӯ',
+ 'ӱ' => 'Ӱ',
+ 'ӳ' => 'Ӳ',
+ 'ӵ' => 'Ӵ',
+ 'ӷ' => 'Ӷ',
+ 'ӹ' => 'Ӹ',
+ 'ӻ' => 'Ӻ',
+ 'ӽ' => 'Ӽ',
+ 'ӿ' => 'Ӿ',
+ 'ԁ' => 'Ԁ',
+ 'ԃ' => 'Ԃ',
+ 'ԅ' => 'Ԅ',
+ 'ԇ' => 'Ԇ',
+ 'ԉ' => 'Ԉ',
+ 'ԋ' => 'Ԋ',
+ 'ԍ' => 'Ԍ',
+ 'ԏ' => 'Ԏ',
+ 'ԑ' => 'Ԑ',
+ 'ԓ' => 'Ԓ',
+ 'ԕ' => 'Ԕ',
+ 'ԗ' => 'Ԗ',
+ 'ԙ' => 'Ԙ',
+ 'ԛ' => 'Ԛ',
+ 'ԝ' => 'Ԝ',
+ 'ԟ' => 'Ԟ',
+ 'ԡ' => 'Ԡ',
+ 'ԣ' => 'Ԣ',
+ 'ԥ' => 'Ԥ',
+ 'ԧ' => 'Ԧ',
+ 'ԩ' => 'Ԩ',
+ 'ԫ' => 'Ԫ',
+ 'ԭ' => 'Ԭ',
+ 'ԯ' => 'Ԯ',
+ 'ա' => 'Ա',
+ 'բ' => 'Բ',
+ 'գ' => 'Գ',
+ 'դ' => 'Դ',
+ 'ե' => 'Ե',
+ 'զ' => 'Զ',
+ 'է' => 'Է',
+ 'ը' => 'Ը',
+ 'թ' => 'Թ',
+ 'ժ' => 'Ժ',
+ 'ի' => 'Ի',
+ 'լ' => 'Լ',
+ 'խ' => 'Խ',
+ 'ծ' => 'Ծ',
+ 'կ' => 'Կ',
+ 'հ' => 'Հ',
+ 'ձ' => 'Ձ',
+ 'ղ' => 'Ղ',
+ 'ճ' => 'Ճ',
+ 'մ' => 'Մ',
+ 'յ' => 'Յ',
+ 'ն' => 'Ն',
+ 'շ' => 'Շ',
+ 'ո' => 'Ո',
+ 'չ' => 'Չ',
+ 'պ' => 'Պ',
+ 'ջ' => 'Ջ',
+ 'ռ' => 'Ռ',
+ 'ս' => 'Ս',
+ 'վ' => 'Վ',
+ 'տ' => 'Տ',
+ 'ր' => 'Ր',
+ 'ց' => 'Ց',
+ 'ւ' => 'Ւ',
+ 'փ' => 'Փ',
+ 'ք' => 'Ք',
+ 'օ' => 'Օ',
+ 'ֆ' => 'Ֆ',
+ 'ᵹ' => 'Ᵹ',
+ 'ᵽ' => 'Ᵽ',
+ 'ḁ' => 'Ḁ',
+ 'ḃ' => 'Ḃ',
+ 'ḅ' => 'Ḅ',
+ 'ḇ' => 'Ḇ',
+ 'ḉ' => 'Ḉ',
+ 'ḋ' => 'Ḋ',
+ 'ḍ' => 'Ḍ',
+ 'ḏ' => 'Ḏ',
+ 'ḑ' => 'Ḑ',
+ 'ḓ' => 'Ḓ',
+ 'ḕ' => 'Ḕ',
+ 'ḗ' => 'Ḗ',
+ 'ḙ' => 'Ḙ',
+ 'ḛ' => 'Ḛ',
+ 'ḝ' => 'Ḝ',
+ 'ḟ' => 'Ḟ',
+ 'ḡ' => 'Ḡ',
+ 'ḣ' => 'Ḣ',
+ 'ḥ' => 'Ḥ',
+ 'ḧ' => 'Ḧ',
+ 'ḩ' => 'Ḩ',
+ 'ḫ' => 'Ḫ',
+ 'ḭ' => 'Ḭ',
+ 'ḯ' => 'Ḯ',
+ 'ḱ' => 'Ḱ',
+ 'ḳ' => 'Ḳ',
+ 'ḵ' => 'Ḵ',
+ 'ḷ' => 'Ḷ',
+ 'ḹ' => 'Ḹ',
+ 'ḻ' => 'Ḻ',
+ 'ḽ' => 'Ḽ',
+ 'ḿ' => 'Ḿ',
+ 'ṁ' => 'Ṁ',
+ 'ṃ' => 'Ṃ',
+ 'ṅ' => 'Ṅ',
+ 'ṇ' => 'Ṇ',
+ 'ṉ' => 'Ṉ',
+ 'ṋ' => 'Ṋ',
+ 'ṍ' => 'Ṍ',
+ 'ṏ' => 'Ṏ',
+ 'ṑ' => 'Ṑ',
+ 'ṓ' => 'Ṓ',
+ 'ṕ' => 'Ṕ',
+ 'ṗ' => 'Ṗ',
+ 'ṙ' => 'Ṙ',
+ 'ṛ' => 'Ṛ',
+ 'ṝ' => 'Ṝ',
+ 'ṟ' => 'Ṟ',
+ 'ṡ' => 'Ṡ',
+ 'ṣ' => 'Ṣ',
+ 'ṥ' => 'Ṥ',
+ 'ṧ' => 'Ṧ',
+ 'ṩ' => 'Ṩ',
+ 'ṫ' => 'Ṫ',
+ 'ṭ' => 'Ṭ',
+ 'ṯ' => 'Ṯ',
+ 'ṱ' => 'Ṱ',
+ 'ṳ' => 'Ṳ',
+ 'ṵ' => 'Ṵ',
+ 'ṷ' => 'Ṷ',
+ 'ṹ' => 'Ṹ',
+ 'ṻ' => 'Ṻ',
+ 'ṽ' => 'Ṽ',
+ 'ṿ' => 'Ṿ',
+ 'ẁ' => 'Ẁ',
+ 'ẃ' => 'Ẃ',
+ 'ẅ' => 'Ẅ',
+ 'ẇ' => 'Ẇ',
+ 'ẉ' => 'Ẉ',
+ 'ẋ' => 'Ẋ',
+ 'ẍ' => 'Ẍ',
+ 'ẏ' => 'Ẏ',
+ 'ẑ' => 'Ẑ',
+ 'ẓ' => 'Ẓ',
+ 'ẕ' => 'Ẕ',
+ 'ẛ' => 'Ṡ',
+ 'ạ' => 'Ạ',
+ 'ả' => 'Ả',
+ 'ấ' => 'Ấ',
+ 'ầ' => 'Ầ',
+ 'ẩ' => 'Ẩ',
+ 'ẫ' => 'Ẫ',
+ 'ậ' => 'Ậ',
+ 'ắ' => 'Ắ',
+ 'ằ' => 'Ằ',
+ 'ẳ' => 'Ẳ',
+ 'ẵ' => 'Ẵ',
+ 'ặ' => 'Ặ',
+ 'ẹ' => 'Ẹ',
+ 'ẻ' => 'Ẻ',
+ 'ẽ' => 'Ẽ',
+ 'ế' => 'Ế',
+ 'ề' => 'Ề',
+ 'ể' => 'Ể',
+ 'ễ' => 'Ễ',
+ 'ệ' => 'Ệ',
+ 'ỉ' => 'Ỉ',
+ 'ị' => 'Ị',
+ 'ọ' => 'Ọ',
+ 'ỏ' => 'Ỏ',
+ 'ố' => 'Ố',
+ 'ồ' => 'Ồ',
+ 'ổ' => 'Ổ',
+ 'ỗ' => 'Ỗ',
+ 'ộ' => 'Ộ',
+ 'ớ' => 'Ớ',
+ 'ờ' => 'Ờ',
+ 'ở' => 'Ở',
+ 'ỡ' => 'Ỡ',
+ 'ợ' => 'Ợ',
+ 'ụ' => 'Ụ',
+ 'ủ' => 'Ủ',
+ 'ứ' => 'Ứ',
+ 'ừ' => 'Ừ',
+ 'ử' => 'Ử',
+ 'ữ' => 'Ữ',
+ 'ự' => 'Ự',
+ 'ỳ' => 'Ỳ',
+ 'ỵ' => 'Ỵ',
+ 'ỷ' => 'Ỷ',
+ 'ỹ' => 'Ỹ',
+ 'ỻ' => 'Ỻ',
+ 'ỽ' => 'Ỽ',
+ 'ỿ' => 'Ỿ',
+ 'ἀ' => 'Ἀ',
+ 'ἁ' => 'Ἁ',
+ 'ἂ' => 'Ἂ',
+ 'ἃ' => 'Ἃ',
+ 'ἄ' => 'Ἄ',
+ 'ἅ' => 'Ἅ',
+ 'ἆ' => 'Ἆ',
+ 'ἇ' => 'Ἇ',
+ 'ἐ' => 'Ἐ',
+ 'ἑ' => 'Ἑ',
+ 'ἒ' => 'Ἒ',
+ 'ἓ' => 'Ἓ',
+ 'ἔ' => 'Ἔ',
+ 'ἕ' => 'Ἕ',
+ 'ἠ' => 'Ἠ',
+ 'ἡ' => 'Ἡ',
+ 'ἢ' => 'Ἢ',
+ 'ἣ' => 'Ἣ',
+ 'ἤ' => 'Ἤ',
+ 'ἥ' => 'Ἥ',
+ 'ἦ' => 'Ἦ',
+ 'ἧ' => 'Ἧ',
+ 'ἰ' => 'Ἰ',
+ 'ἱ' => 'Ἱ',
+ 'ἲ' => 'Ἲ',
+ 'ἳ' => 'Ἳ',
+ 'ἴ' => 'Ἴ',
+ 'ἵ' => 'Ἵ',
+ 'ἶ' => 'Ἶ',
+ 'ἷ' => 'Ἷ',
+ 'ὀ' => 'Ὀ',
+ 'ὁ' => 'Ὁ',
+ 'ὂ' => 'Ὂ',
+ 'ὃ' => 'Ὃ',
+ 'ὄ' => 'Ὄ',
+ 'ὅ' => 'Ὅ',
+ 'ὑ' => 'Ὑ',
+ 'ὓ' => 'Ὓ',
+ 'ὕ' => 'Ὕ',
+ 'ὗ' => 'Ὗ',
+ 'ὠ' => 'Ὠ',
+ 'ὡ' => 'Ὡ',
+ 'ὢ' => 'Ὢ',
+ 'ὣ' => 'Ὣ',
+ 'ὤ' => 'Ὤ',
+ 'ὥ' => 'Ὥ',
+ 'ὦ' => 'Ὦ',
+ 'ὧ' => 'Ὧ',
+ 'ὰ' => 'Ὰ',
+ 'ά' => 'Ά',
+ 'ὲ' => 'Ὲ',
+ 'έ' => 'Έ',
+ 'ὴ' => 'Ὴ',
+ 'ή' => 'Ή',
+ 'ὶ' => 'Ὶ',
+ 'ί' => 'Ί',
+ 'ὸ' => 'Ὸ',
+ 'ό' => 'Ό',
+ 'ὺ' => 'Ὺ',
+ 'ύ' => 'Ύ',
+ 'ὼ' => 'Ὼ',
+ 'ώ' => 'Ώ',
+ 'ᾀ' => 'ᾈ',
+ 'ᾁ' => 'ᾉ',
+ 'ᾂ' => 'ᾊ',
+ 'ᾃ' => 'ᾋ',
+ 'ᾄ' => 'ᾌ',
+ 'ᾅ' => 'ᾍ',
+ 'ᾆ' => 'ᾎ',
+ 'ᾇ' => 'ᾏ',
+ 'ᾐ' => 'ᾘ',
+ 'ᾑ' => 'ᾙ',
+ 'ᾒ' => 'ᾚ',
+ 'ᾓ' => 'ᾛ',
+ 'ᾔ' => 'ᾜ',
+ 'ᾕ' => 'ᾝ',
+ 'ᾖ' => 'ᾞ',
+ 'ᾗ' => 'ᾟ',
+ 'ᾠ' => 'ᾨ',
+ 'ᾡ' => 'ᾩ',
+ 'ᾢ' => 'ᾪ',
+ 'ᾣ' => 'ᾫ',
+ 'ᾤ' => 'ᾬ',
+ 'ᾥ' => 'ᾭ',
+ 'ᾦ' => 'ᾮ',
+ 'ᾧ' => 'ᾯ',
+ 'ᾰ' => 'Ᾰ',
+ 'ᾱ' => 'Ᾱ',
+ 'ᾳ' => 'ᾼ',
+ 'ι' => 'Ι',
+ 'ῃ' => 'ῌ',
+ 'ῐ' => 'Ῐ',
+ 'ῑ' => 'Ῑ',
+ 'ῠ' => 'Ῠ',
+ 'ῡ' => 'Ῡ',
+ 'ῥ' => 'Ῥ',
+ 'ῳ' => 'ῼ',
+ 'ⅎ' => 'Ⅎ',
+ 'ⅰ' => 'Ⅰ',
+ 'ⅱ' => 'Ⅱ',
+ 'ⅲ' => 'Ⅲ',
+ 'ⅳ' => 'Ⅳ',
+ 'ⅴ' => 'Ⅴ',
+ 'ⅵ' => 'Ⅵ',
+ 'ⅶ' => 'Ⅶ',
+ 'ⅷ' => 'Ⅷ',
+ 'ⅸ' => 'Ⅸ',
+ 'ⅹ' => 'Ⅹ',
+ 'ⅺ' => 'Ⅺ',
+ 'ⅻ' => 'Ⅻ',
+ 'ⅼ' => 'Ⅼ',
+ 'ⅽ' => 'Ⅽ',
+ 'ⅾ' => 'Ⅾ',
+ 'ⅿ' => 'Ⅿ',
+ 'ↄ' => 'Ↄ',
+ 'ⓐ' => 'Ⓐ',
+ 'ⓑ' => 'Ⓑ',
+ 'ⓒ' => 'Ⓒ',
+ 'ⓓ' => 'Ⓓ',
+ 'ⓔ' => 'Ⓔ',
+ 'ⓕ' => 'Ⓕ',
+ 'ⓖ' => 'Ⓖ',
+ 'ⓗ' => 'Ⓗ',
+ 'ⓘ' => 'Ⓘ',
+ 'ⓙ' => 'Ⓙ',
+ 'ⓚ' => 'Ⓚ',
+ 'ⓛ' => 'Ⓛ',
+ 'ⓜ' => 'Ⓜ',
+ 'ⓝ' => 'Ⓝ',
+ 'ⓞ' => 'Ⓞ',
+ 'ⓟ' => 'Ⓟ',
+ 'ⓠ' => 'Ⓠ',
+ 'ⓡ' => 'Ⓡ',
+ 'ⓢ' => 'Ⓢ',
+ 'ⓣ' => 'Ⓣ',
+ 'ⓤ' => 'Ⓤ',
+ 'ⓥ' => 'Ⓥ',
+ 'ⓦ' => 'Ⓦ',
+ 'ⓧ' => 'Ⓧ',
+ 'ⓨ' => 'Ⓨ',
+ 'ⓩ' => 'Ⓩ',
+ 'ⰰ' => 'Ⰰ',
+ 'ⰱ' => 'Ⰱ',
+ 'ⰲ' => 'Ⰲ',
+ 'ⰳ' => 'Ⰳ',
+ 'ⰴ' => 'Ⰴ',
+ 'ⰵ' => 'Ⰵ',
+ 'ⰶ' => 'Ⰶ',
+ 'ⰷ' => 'Ⰷ',
+ 'ⰸ' => 'Ⰸ',
+ 'ⰹ' => 'Ⰹ',
+ 'ⰺ' => 'Ⰺ',
+ 'ⰻ' => 'Ⰻ',
+ 'ⰼ' => 'Ⰼ',
+ 'ⰽ' => 'Ⰽ',
+ 'ⰾ' => 'Ⰾ',
+ 'ⰿ' => 'Ⰿ',
+ 'ⱀ' => 'Ⱀ',
+ 'ⱁ' => 'Ⱁ',
+ 'ⱂ' => 'Ⱂ',
+ 'ⱃ' => 'Ⱃ',
+ 'ⱄ' => 'Ⱄ',
+ 'ⱅ' => 'Ⱅ',
+ 'ⱆ' => 'Ⱆ',
+ 'ⱇ' => 'Ⱇ',
+ 'ⱈ' => 'Ⱈ',
+ 'ⱉ' => 'Ⱉ',
+ 'ⱊ' => 'Ⱊ',
+ 'ⱋ' => 'Ⱋ',
+ 'ⱌ' => 'Ⱌ',
+ 'ⱍ' => 'Ⱍ',
+ 'ⱎ' => 'Ⱎ',
+ 'ⱏ' => 'Ⱏ',
+ 'ⱐ' => 'Ⱐ',
+ 'ⱑ' => 'Ⱑ',
+ 'ⱒ' => 'Ⱒ',
+ 'ⱓ' => 'Ⱓ',
+ 'ⱔ' => 'Ⱔ',
+ 'ⱕ' => 'Ⱕ',
+ 'ⱖ' => 'Ⱖ',
+ 'ⱗ' => 'Ⱗ',
+ 'ⱘ' => 'Ⱘ',
+ 'ⱙ' => 'Ⱙ',
+ 'ⱚ' => 'Ⱚ',
+ 'ⱛ' => 'Ⱛ',
+ 'ⱜ' => 'Ⱜ',
+ 'ⱝ' => 'Ⱝ',
+ 'ⱞ' => 'Ⱞ',
+ 'ⱡ' => 'Ⱡ',
+ 'ⱥ' => 'Ⱥ',
+ 'ⱦ' => 'Ⱦ',
+ 'ⱨ' => 'Ⱨ',
+ 'ⱪ' => 'Ⱪ',
+ 'ⱬ' => 'Ⱬ',
+ 'ⱳ' => 'Ⱳ',
+ 'ⱶ' => 'Ⱶ',
+ 'ⲁ' => 'Ⲁ',
+ 'ⲃ' => 'Ⲃ',
+ 'ⲅ' => 'Ⲅ',
+ 'ⲇ' => 'Ⲇ',
+ 'ⲉ' => 'Ⲉ',
+ 'ⲋ' => 'Ⲋ',
+ 'ⲍ' => 'Ⲍ',
+ 'ⲏ' => 'Ⲏ',
+ 'ⲑ' => 'Ⲑ',
+ 'ⲓ' => 'Ⲓ',
+ 'ⲕ' => 'Ⲕ',
+ 'ⲗ' => 'Ⲗ',
+ 'ⲙ' => 'Ⲙ',
+ 'ⲛ' => 'Ⲛ',
+ 'ⲝ' => 'Ⲝ',
+ 'ⲟ' => 'Ⲟ',
+ 'ⲡ' => 'Ⲡ',
+ 'ⲣ' => 'Ⲣ',
+ 'ⲥ' => 'Ⲥ',
+ 'ⲧ' => 'Ⲧ',
+ 'ⲩ' => 'Ⲩ',
+ 'ⲫ' => 'Ⲫ',
+ 'ⲭ' => 'Ⲭ',
+ 'ⲯ' => 'Ⲯ',
+ 'ⲱ' => 'Ⲱ',
+ 'ⲳ' => 'Ⲳ',
+ 'ⲵ' => 'Ⲵ',
+ 'ⲷ' => 'Ⲷ',
+ 'ⲹ' => 'Ⲹ',
+ 'ⲻ' => 'Ⲻ',
+ 'ⲽ' => 'Ⲽ',
+ 'ⲿ' => 'Ⲿ',
+ 'ⳁ' => 'Ⳁ',
+ 'ⳃ' => 'Ⳃ',
+ 'ⳅ' => 'Ⳅ',
+ 'ⳇ' => 'Ⳇ',
+ 'ⳉ' => 'Ⳉ',
+ 'ⳋ' => 'Ⳋ',
+ 'ⳍ' => 'Ⳍ',
+ 'ⳏ' => 'Ⳏ',
+ 'ⳑ' => 'Ⳑ',
+ 'ⳓ' => 'Ⳓ',
+ 'ⳕ' => 'Ⳕ',
+ 'ⳗ' => 'Ⳗ',
+ 'ⳙ' => 'Ⳙ',
+ 'ⳛ' => 'Ⳛ',
+ 'ⳝ' => 'Ⳝ',
+ 'ⳟ' => 'Ⳟ',
+ 'ⳡ' => 'Ⳡ',
+ 'ⳣ' => 'Ⳣ',
+ 'ⳬ' => 'Ⳬ',
+ 'ⳮ' => 'Ⳮ',
+ 'ⳳ' => 'Ⳳ',
+ 'ⴀ' => 'Ⴀ',
+ 'ⴁ' => 'Ⴁ',
+ 'ⴂ' => 'Ⴂ',
+ 'ⴃ' => 'Ⴃ',
+ 'ⴄ' => 'Ⴄ',
+ 'ⴅ' => 'Ⴅ',
+ 'ⴆ' => 'Ⴆ',
+ 'ⴇ' => 'Ⴇ',
+ 'ⴈ' => 'Ⴈ',
+ 'ⴉ' => 'Ⴉ',
+ 'ⴊ' => 'Ⴊ',
+ 'ⴋ' => 'Ⴋ',
+ 'ⴌ' => 'Ⴌ',
+ 'ⴍ' => 'Ⴍ',
+ 'ⴎ' => 'Ⴎ',
+ 'ⴏ' => 'Ⴏ',
+ 'ⴐ' => 'Ⴐ',
+ 'ⴑ' => 'Ⴑ',
+ 'ⴒ' => 'Ⴒ',
+ 'ⴓ' => 'Ⴓ',
+ 'ⴔ' => 'Ⴔ',
+ 'ⴕ' => 'Ⴕ',
+ 'ⴖ' => 'Ⴖ',
+ 'ⴗ' => 'Ⴗ',
+ 'ⴘ' => 'Ⴘ',
+ 'ⴙ' => 'Ⴙ',
+ 'ⴚ' => 'Ⴚ',
+ 'ⴛ' => 'Ⴛ',
+ 'ⴜ' => 'Ⴜ',
+ 'ⴝ' => 'Ⴝ',
+ 'ⴞ' => 'Ⴞ',
+ 'ⴟ' => 'Ⴟ',
+ 'ⴠ' => 'Ⴠ',
+ 'ⴡ' => 'Ⴡ',
+ 'ⴢ' => 'Ⴢ',
+ 'ⴣ' => 'Ⴣ',
+ 'ⴤ' => 'Ⴤ',
+ 'ⴥ' => 'Ⴥ',
+ 'ⴧ' => 'Ⴧ',
+ 'ⴭ' => 'Ⴭ',
+ 'ꙁ' => 'Ꙁ',
+ 'ꙃ' => 'Ꙃ',
+ 'ꙅ' => 'Ꙅ',
+ 'ꙇ' => 'Ꙇ',
+ 'ꙉ' => 'Ꙉ',
+ 'ꙋ' => 'Ꙋ',
+ 'ꙍ' => 'Ꙍ',
+ 'ꙏ' => 'Ꙏ',
+ 'ꙑ' => 'Ꙑ',
+ 'ꙓ' => 'Ꙓ',
+ 'ꙕ' => 'Ꙕ',
+ 'ꙗ' => 'Ꙗ',
+ 'ꙙ' => 'Ꙙ',
+ 'ꙛ' => 'Ꙛ',
+ 'ꙝ' => 'Ꙝ',
+ 'ꙟ' => 'Ꙟ',
+ 'ꙡ' => 'Ꙡ',
+ 'ꙣ' => 'Ꙣ',
+ 'ꙥ' => 'Ꙥ',
+ 'ꙧ' => 'Ꙧ',
+ 'ꙩ' => 'Ꙩ',
+ 'ꙫ' => 'Ꙫ',
+ 'ꙭ' => 'Ꙭ',
+ 'ꚁ' => 'Ꚁ',
+ 'ꚃ' => 'Ꚃ',
+ 'ꚅ' => 'Ꚅ',
+ 'ꚇ' => 'Ꚇ',
+ 'ꚉ' => 'Ꚉ',
+ 'ꚋ' => 'Ꚋ',
+ 'ꚍ' => 'Ꚍ',
+ 'ꚏ' => 'Ꚏ',
+ 'ꚑ' => 'Ꚑ',
+ 'ꚓ' => 'Ꚓ',
+ 'ꚕ' => 'Ꚕ',
+ 'ꚗ' => 'Ꚗ',
+ 'ꚙ' => 'Ꚙ',
+ 'ꚛ' => 'Ꚛ',
+ 'ꜣ' => 'Ꜣ',
+ 'ꜥ' => 'Ꜥ',
+ 'ꜧ' => 'Ꜧ',
+ 'ꜩ' => 'Ꜩ',
+ 'ꜫ' => 'Ꜫ',
+ 'ꜭ' => 'Ꜭ',
+ 'ꜯ' => 'Ꜯ',
+ 'ꜳ' => 'Ꜳ',
+ 'ꜵ' => 'Ꜵ',
+ 'ꜷ' => 'Ꜷ',
+ 'ꜹ' => 'Ꜹ',
+ 'ꜻ' => 'Ꜻ',
+ 'ꜽ' => 'Ꜽ',
+ 'ꜿ' => 'Ꜿ',
+ 'ꝁ' => 'Ꝁ',
+ 'ꝃ' => 'Ꝃ',
+ 'ꝅ' => 'Ꝅ',
+ 'ꝇ' => 'Ꝇ',
+ 'ꝉ' => 'Ꝉ',
+ 'ꝋ' => 'Ꝋ',
+ 'ꝍ' => 'Ꝍ',
+ 'ꝏ' => 'Ꝏ',
+ 'ꝑ' => 'Ꝑ',
+ 'ꝓ' => 'Ꝓ',
+ 'ꝕ' => 'Ꝕ',
+ 'ꝗ' => 'Ꝗ',
+ 'ꝙ' => 'Ꝙ',
+ 'ꝛ' => 'Ꝛ',
+ 'ꝝ' => 'Ꝝ',
+ 'ꝟ' => 'Ꝟ',
+ 'ꝡ' => 'Ꝡ',
+ 'ꝣ' => 'Ꝣ',
+ 'ꝥ' => 'Ꝥ',
+ 'ꝧ' => 'Ꝧ',
+ 'ꝩ' => 'Ꝩ',
+ 'ꝫ' => 'Ꝫ',
+ 'ꝭ' => 'Ꝭ',
+ 'ꝯ' => 'Ꝯ',
+ 'ꝺ' => 'Ꝺ',
+ 'ꝼ' => 'Ꝼ',
+ 'ꝿ' => 'Ꝿ',
+ 'ꞁ' => 'Ꞁ',
+ 'ꞃ' => 'Ꞃ',
+ 'ꞅ' => 'Ꞅ',
+ 'ꞇ' => 'Ꞇ',
+ 'ꞌ' => 'Ꞌ',
+ 'ꞑ' => 'Ꞑ',
+ 'ꞓ' => 'Ꞓ',
+ 'ꞗ' => 'Ꞗ',
+ 'ꞙ' => 'Ꞙ',
+ 'ꞛ' => 'Ꞛ',
+ 'ꞝ' => 'Ꞝ',
+ 'ꞟ' => 'Ꞟ',
+ 'ꞡ' => 'Ꞡ',
+ 'ꞣ' => 'Ꞣ',
+ 'ꞥ' => 'Ꞥ',
+ 'ꞧ' => 'Ꞧ',
+ 'ꞩ' => 'Ꞩ',
+ 'a' => 'A',
+ 'b' => 'B',
+ 'c' => 'C',
+ 'd' => 'D',
+ 'e' => 'E',
+ 'f' => 'F',
+ 'g' => 'G',
+ 'h' => 'H',
+ 'i' => 'I',
+ 'j' => 'J',
+ 'k' => 'K',
+ 'l' => 'L',
+ 'm' => 'M',
+ 'n' => 'N',
+ 'o' => 'O',
+ 'p' => 'P',
+ 'q' => 'Q',
+ 'r' => 'R',
+ 's' => 'S',
+ 't' => 'T',
+ 'u' => 'U',
+ 'v' => 'V',
+ 'w' => 'W',
+ 'x' => 'X',
+ 'y' => 'Y',
+ 'z' => 'Z',
+ '𐐨' => '𐐀',
+ '𐐩' => '𐐁',
+ '𐐪' => '𐐂',
+ '𐐫' => '𐐃',
+ '𐐬' => '𐐄',
+ '𐐭' => '𐐅',
+ '𐐮' => '𐐆',
+ '𐐯' => '𐐇',
+ '𐐰' => '𐐈',
+ '𐐱' => '𐐉',
+ '𐐲' => '𐐊',
+ '𐐳' => '𐐋',
+ '𐐴' => '𐐌',
+ '𐐵' => '𐐍',
+ '𐐶' => '𐐎',
+ '𐐷' => '𐐏',
+ '𐐸' => '𐐐',
+ '𐐹' => '𐐑',
+ '𐐺' => '𐐒',
+ '𐐻' => '𐐓',
+ '𐐼' => '𐐔',
+ '𐐽' => '𐐕',
+ '𐐾' => '𐐖',
+ '𐐿' => '𐐗',
+ '𐑀' => '𐐘',
+ '𐑁' => '𐐙',
+ '𐑂' => '𐐚',
+ '𐑃' => '𐐛',
+ '𐑄' => '𐐜',
+ '𐑅' => '𐐝',
+ '𐑆' => '𐐞',
+ '𐑇' => '𐐟',
+ '𐑈' => '𐐠',
+ '𐑉' => '𐐡',
+ '𐑊' => '𐐢',
+ '𐑋' => '𐐣',
+ '𐑌' => '𐐤',
+ '𐑍' => '𐐥',
+ '𐑎' => '𐐦',
+ '𐑏' => '𐐧',
+ '𑣀' => '𑢠',
+ '𑣁' => '𑢡',
+ '𑣂' => '𑢢',
+ '𑣃' => '𑢣',
+ '𑣄' => '𑢤',
+ '𑣅' => '𑢥',
+ '𑣆' => '𑢦',
+ '𑣇' => '𑢧',
+ '𑣈' => '𑢨',
+ '𑣉' => '𑢩',
+ '𑣊' => '𑢪',
+ '𑣋' => '𑢫',
+ '𑣌' => '𑢬',
+ '𑣍' => '𑢭',
+ '𑣎' => '𑢮',
+ '𑣏' => '𑢯',
+ '𑣐' => '𑢰',
+ '𑣑' => '𑢱',
+ '𑣒' => '𑢲',
+ '𑣓' => '𑢳',
+ '𑣔' => '𑢴',
+ '𑣕' => '𑢵',
+ '𑣖' => '𑢶',
+ '𑣗' => '𑢷',
+ '𑣘' => '𑢸',
+ '𑣙' => '𑢹',
+ '𑣚' => '𑢺',
+ '𑣛' => '𑢻',
+ '𑣜' => '𑢼',
+ '𑣝' => '𑢽',
+ '𑣞' => '𑢾',
+ '𑣟' => '𑢿',
+);
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/bootstrap.php b/public/system/storage/vendor/symfony/polyfill-mbstring/bootstrap.php
new file mode 100644
index 0000000..2fdcc5a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/bootstrap.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Mbstring as p;
+
+if (!function_exists('mb_strlen')) {
+ define('MB_CASE_UPPER', 0);
+ define('MB_CASE_LOWER', 1);
+ define('MB_CASE_TITLE', 2);
+
+ function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
+ function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
+ function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
+ function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
+ function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
+ function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
+ function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
+ function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
+ function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
+ function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
+ function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
+ function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
+ function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
+ function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
+ function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
+ function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
+ function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
+ function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
+ function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
+ function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
+ function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
+ function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
+ function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
+ function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
+ function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
+ function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
+ function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
+ function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
+ function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
+ function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
+ function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
+ function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
+ function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
+ function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); }
+}
+if (!function_exists('mb_chr')) {
+ function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
+ function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
+ function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
+}
diff --git a/public/system/storage/vendor/symfony/polyfill-mbstring/composer.json b/public/system/storage/vendor/symfony/polyfill-mbstring/composer.json
new file mode 100644
index 0000000..0bce087
--- /dev/null
+++ b/public/system/storage/vendor/symfony/polyfill-mbstring/composer.json
@@ -0,0 +1,34 @@
+{
+ "name": "symfony/polyfill-mbstring",
+ "type": "library",
+ "description": "Symfony polyfill for the Mbstring extension",
+ "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
+ "files": [ "bootstrap.php" ]
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.11-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/.gitignore b/public/system/storage/vendor/symfony/translation/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/public/system/storage/vendor/symfony/translation/CHANGELOG.md b/public/system/storage/vendor/symfony/translation/CHANGELOG.md
new file mode 100644
index 0000000..b011f9e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/CHANGELOG.md
@@ -0,0 +1,69 @@
+CHANGELOG
+=========
+
+3.0.0
+-----
+
+ * removed `FileDumper::format()` method.
+ * Changed the visibility of the locale property in `Translator` from protected to private.
+
+2.8.0
+-----
+
+ * deprecated FileDumper::format(), overwrite FileDumper::formatCatalogue() instead.
+ * deprecated Translator::getMessages(), rely on TranslatorBagInterface::getCatalogue() instead.
+ * added `FileDumper::formatCatalogue` which allows format the catalogue without dumping it into file.
+ * added option `json_encoding` to JsonFileDumper
+ * added options `as_tree`, `inline` to YamlFileDumper
+ * added support for XLIFF 2.0.
+ * added support for XLIFF target and tool attributes.
+ * added message parameters to DataCollectorTranslator.
+ * [DEPRECATION] The `DiffOperation` class has been deprecated and
+ will be removed in Symfony 3.0, since its operation has nothing to do with 'diff',
+ so the class name is misleading. The `TargetOperation` class should be used for
+ this use-case instead.
+
+2.7.0
+-----
+
+ * added DataCollectorTranslator for collecting the translated messages.
+
+2.6.0
+-----
+
+ * added possibility to cache catalogues
+ * added TranslatorBagInterface
+ * added LoggingTranslator
+ * added Translator::getMessages() for retrieving the message catalogue as an array
+
+2.5.0
+-----
+
+ * added relative file path template to the file dumpers
+ * added optional backup to the file dumpers
+ * changed IcuResFileDumper to extend FileDumper
+
+2.3.0
+-----
+
+ * added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues)
+ * added Translator::getFallbackLocales()
+ * deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method
+
+2.2.0
+-----
+
+ * QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3.
+ * [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now
+ throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found
+ and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid.
+ * changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException
+ (IcuDatFileLoader, IcuResFileLoader and QtFileLoader)
+
+2.1.0
+-----
+
+ * added support for more than one fallback locale
+ * added support for extracting translation messages from templates (Twig and PHP)
+ * added dumpers for translation catalogs
+ * added support for QT, gettext, and ResourceBundles
diff --git a/public/system/storage/vendor/symfony/translation/Catalogue/AbstractOperation.php b/public/system/storage/vendor/symfony/translation/Catalogue/AbstractOperation.php
new file mode 100644
index 0000000..9598e17
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Catalogue/AbstractOperation.php
@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Base catalogues binary operation class.
+ *
+ * A catalogue binary operation performs operation on
+ * source (the left argument) and target (the right argument) catalogues.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+abstract class AbstractOperation implements OperationInterface
+{
+ /**
+ * @var MessageCatalogueInterface The source catalogue
+ */
+ protected $source;
+
+ /**
+ * @var MessageCatalogueInterface The target catalogue
+ */
+ protected $target;
+
+ /**
+ * @var MessageCatalogue The result catalogue
+ */
+ protected $result;
+
+ /**
+ * @var null|array The domains affected by this operation
+ */
+ private $domains;
+
+ /**
+ * This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
+ *
+ * The data structure of this array is as follows:
+ * ```php
+ * array(
+ * 'domain 1' => array(
+ * 'all' => array(...),
+ * 'new' => array(...),
+ * 'obsolete' => array(...)
+ * ),
+ * 'domain 2' => array(
+ * 'all' => array(...),
+ * 'new' => array(...),
+ * 'obsolete' => array(...)
+ * ),
+ * ...
+ * )
+ * ```
+ *
+ * @var array The array that stores 'all', 'new' and 'obsolete' messages
+ */
+ protected $messages;
+
+ /**
+ * @param MessageCatalogueInterface $source The source catalogue
+ * @param MessageCatalogueInterface $target The target catalogue
+ *
+ * @throws \LogicException
+ */
+ public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
+ {
+ if ($source->getLocale() !== $target->getLocale()) {
+ throw new \LogicException('Operated catalogues must belong to the same locale.');
+ }
+
+ $this->source = $source;
+ $this->target = $target;
+ $this->result = new MessageCatalogue($source->getLocale());
+ $this->domains = null;
+ $this->messages = array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDomains()
+ {
+ if (null === $this->domains) {
+ $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains())));
+ }
+
+ return $this->domains;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessages($domain)
+ {
+ if (!in_array($domain, $this->getDomains())) {
+ throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
+ }
+
+ if (!isset($this->messages[$domain]['all'])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain]['all'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNewMessages($domain)
+ {
+ if (!in_array($domain, $this->getDomains())) {
+ throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
+ }
+
+ if (!isset($this->messages[$domain]['new'])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain]['new'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getObsoleteMessages($domain)
+ {
+ if (!in_array($domain, $this->getDomains())) {
+ throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
+ }
+
+ if (!isset($this->messages[$domain]['obsolete'])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain]['obsolete'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getResult()
+ {
+ foreach ($this->getDomains() as $domain) {
+ if (!isset($this->messages[$domain])) {
+ $this->processDomain($domain);
+ }
+ }
+
+ return $this->result;
+ }
+
+ /**
+ * Performs operation on source and target catalogues for the given domain and
+ * stores the results.
+ *
+ * @param string $domain The domain which the operation will be performed for
+ */
+ abstract protected function processDomain($domain);
+}
diff --git a/public/system/storage/vendor/symfony/translation/Catalogue/MergeOperation.php b/public/system/storage/vendor/symfony/translation/Catalogue/MergeOperation.php
new file mode 100644
index 0000000..6db3f80
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Catalogue/MergeOperation.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+/**
+ * Merge operation between two catalogues as follows:
+ * all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
+ * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
+ * obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅
+ * Basically, the result contains messages from both catalogues.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+class MergeOperation extends AbstractOperation
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function processDomain($domain)
+ {
+ $this->messages[$domain] = array(
+ 'all' => array(),
+ 'new' => array(),
+ 'obsolete' => array(),
+ );
+
+ foreach ($this->source->all($domain) as $id => $message) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->result->add(array($id => $message), $domain);
+ if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) {
+ $this->result->setMetadata($id, $keyMetadata, $domain);
+ }
+ }
+
+ foreach ($this->target->all($domain) as $id => $message) {
+ if (!$this->source->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->messages[$domain]['new'][$id] = $message;
+ $this->result->add(array($id => $message), $domain);
+ if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) {
+ $this->result->setMetadata($id, $keyMetadata, $domain);
+ }
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Catalogue/OperationInterface.php b/public/system/storage/vendor/symfony/translation/Catalogue/OperationInterface.php
new file mode 100644
index 0000000..87d888e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Catalogue/OperationInterface.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Represents an operation on catalogue(s).
+ *
+ * An instance of this interface performs an operation on one or more catalogues and
+ * stores intermediate and final results of the operation.
+ *
+ * The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and
+ * the following results are stored:
+ *
+ * Messages: also called 'all', are valid messages for the given domain after the operation is performed.
+ *
+ * New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}).
+ *
+ * Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}).
+ *
+ * Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'.
+ *
+ * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
+ */
+interface OperationInterface
+{
+ /**
+ * Returns domains affected by operation.
+ *
+ * @return array
+ */
+ public function getDomains();
+
+ /**
+ * Returns all valid messages ('all') after operation.
+ *
+ * @param string $domain
+ *
+ * @return array
+ */
+ public function getMessages($domain);
+
+ /**
+ * Returns new messages ('new') after operation.
+ *
+ * @param string $domain
+ *
+ * @return array
+ */
+ public function getNewMessages($domain);
+
+ /**
+ * Returns obsolete messages ('obsolete') after operation.
+ *
+ * @param string $domain
+ *
+ * @return array
+ */
+ public function getObsoleteMessages($domain);
+
+ /**
+ * Returns resulting catalogue ('result').
+ *
+ * @return MessageCatalogueInterface
+ */
+ public function getResult();
+}
diff --git a/public/system/storage/vendor/symfony/translation/Catalogue/TargetOperation.php b/public/system/storage/vendor/symfony/translation/Catalogue/TargetOperation.php
new file mode 100644
index 0000000..e081e13
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Catalogue/TargetOperation.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+/**
+ * Target operation between two catalogues:
+ * intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
+ * all = intersection ∪ (target ∖ intersection) = target
+ * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
+ * obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target}
+ * Basically, the result contains messages from the target catalogue.
+ *
+ * @author Michael Lee <michael.lee@zerustech.com>
+ */
+class TargetOperation extends AbstractOperation
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function processDomain($domain)
+ {
+ $this->messages[$domain] = array(
+ 'all' => array(),
+ 'new' => array(),
+ 'obsolete' => array(),
+ );
+
+ // For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
+ // because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
+ //
+ // For 'new' messages, the code can't be simplied as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));``
+ // because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback}
+ //
+ // For 'obsolete' messages, the code can't be simplifed as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))``
+ // because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
+
+ foreach ($this->source->all($domain) as $id => $message) {
+ if ($this->target->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->result->add(array($id => $message), $domain);
+ if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) {
+ $this->result->setMetadata($id, $keyMetadata, $domain);
+ }
+ } else {
+ $this->messages[$domain]['obsolete'][$id] = $message;
+ }
+ }
+
+ foreach ($this->target->all($domain) as $id => $message) {
+ if (!$this->source->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->messages[$domain]['new'][$id] = $message;
+ $this->result->add(array($id => $message), $domain);
+ if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) {
+ $this->result->setMetadata($id, $keyMetadata, $domain);
+ }
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/DataCollector/TranslationDataCollector.php b/public/system/storage/vendor/symfony/translation/DataCollector/TranslationDataCollector.php
new file mode 100644
index 0000000..cb59d0a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/DataCollector/TranslationDataCollector.php
@@ -0,0 +1,150 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\DataCollector\DataCollector;
+use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
+use Symfony\Component\Translation\DataCollectorTranslator;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ /**
+ * @var DataCollectorTranslator
+ */
+ private $translator;
+
+ /**
+ * @param DataCollectorTranslator $translator
+ */
+ public function __construct(DataCollectorTranslator $translator)
+ {
+ $this->translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lateCollect()
+ {
+ $messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages());
+
+ $this->data = $this->computeCount($messages);
+ $this->data['messages'] = $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ }
+
+ /**
+ * @return array
+ */
+ public function getMessages()
+ {
+ return isset($this->data['messages']) ? $this->data['messages'] : array();
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountMissings()
+ {
+ return isset($this->data[DataCollectorTranslator::MESSAGE_MISSING]) ? $this->data[DataCollectorTranslator::MESSAGE_MISSING] : 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountFallbacks()
+ {
+ return isset($this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK]) ? $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] : 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountDefines()
+ {
+ return isset($this->data[DataCollectorTranslator::MESSAGE_DEFINED]) ? $this->data[DataCollectorTranslator::MESSAGE_DEFINED] : 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'translation';
+ }
+
+ private function sanitizeCollectedMessages($messages)
+ {
+ $result = array();
+ foreach ($messages as $key => $message) {
+ $messageId = $message['locale'].$message['domain'].$message['id'];
+
+ if (!isset($result[$messageId])) {
+ $message['count'] = 1;
+ $message['parameters'] = !empty($message['parameters']) ? array($message['parameters']) : array();
+ $messages[$key]['translation'] = $this->sanitizeString($message['translation']);
+ $result[$messageId] = $message;
+ } else {
+ if (!empty($message['parameters'])) {
+ $result[$messageId]['parameters'][] = $message['parameters'];
+ }
+
+ ++$result[$messageId]['count'];
+ }
+
+ unset($messages[$key]);
+ }
+
+ return $result;
+ }
+
+ private function computeCount($messages)
+ {
+ $count = array(
+ DataCollectorTranslator::MESSAGE_DEFINED => 0,
+ DataCollectorTranslator::MESSAGE_MISSING => 0,
+ DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0,
+ );
+
+ foreach ($messages as $message) {
+ ++$count[$message['state']];
+ }
+
+ return $count;
+ }
+
+ private function sanitizeString($string, $length = 80)
+ {
+ $string = trim(preg_replace('/\s+/', ' ', $string));
+
+ if (false !== $encoding = mb_detect_encoding($string, null, true)) {
+ if (mb_strlen($string, $encoding) > $length) {
+ return mb_substr($string, 0, $length - 3, $encoding).'...';
+ }
+ } elseif (strlen($string) > $length) {
+ return substr($string, 0, $length - 3).'...';
+ }
+
+ return $string;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/DataCollectorTranslator.php b/public/system/storage/vendor/symfony/translation/DataCollectorTranslator.php
new file mode 100644
index 0000000..2446723
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/DataCollectorTranslator.php
@@ -0,0 +1,152 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface
+{
+ const MESSAGE_DEFINED = 0;
+ const MESSAGE_MISSING = 1;
+ const MESSAGE_EQUALS_FALLBACK = 2;
+
+ /**
+ * @var TranslatorInterface|TranslatorBagInterface
+ */
+ private $translator;
+
+ /**
+ * @var array
+ */
+ private $messages = array();
+
+ /**
+ * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
+ */
+ public function __construct(TranslatorInterface $translator)
+ {
+ if (!$translator instanceof TranslatorBagInterface) {
+ throw new \InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', get_class($translator)));
+ }
+
+ $this->translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+ {
+ $trans = $this->translator->trans($id, $parameters, $domain, $locale);
+ $this->collectMessage($locale, $domain, $id, $trans, $parameters);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+ {
+ $trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
+ $this->collectMessage($locale, $domain, $id, $trans, $parameters, $number);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->translator->setLocale($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->translator->getLocale();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue($locale = null)
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ /**
+ * Passes through all unknown calls onto the translator object.
+ */
+ public function __call($method, $args)
+ {
+ return call_user_func_array(array($this->translator, $method), $args);
+ }
+
+ /**
+ * @return array
+ */
+ public function getCollectedMessages()
+ {
+ return $this->messages;
+ }
+
+ /**
+ * @param string|null $locale
+ * @param string|null $domain
+ * @param string $id
+ * @param string $translation
+ * @param array|null $parameters
+ * @param int|null $number
+ */
+ private function collectMessage($locale, $domain, $id, $translation, $parameters = array(), $number = null)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $id = (string) $id;
+ $catalogue = $this->translator->getCatalogue($locale);
+ $locale = $catalogue->getLocale();
+ if ($catalogue->defines($id, $domain)) {
+ $state = self::MESSAGE_DEFINED;
+ } elseif ($catalogue->has($id, $domain)) {
+ $state = self::MESSAGE_EQUALS_FALLBACK;
+
+ $fallbackCatalogue = $catalogue->getFallbackCatalogue();
+ while ($fallbackCatalogue) {
+ if ($fallbackCatalogue->defines($id, $domain)) {
+ $locale = $fallbackCatalogue->getLocale();
+ break;
+ }
+
+ $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
+ }
+ } else {
+ $state = self::MESSAGE_MISSING;
+ }
+
+ $this->messages[] = array(
+ 'locale' => $locale,
+ 'domain' => $domain,
+ 'id' => $id,
+ 'translation' => $translation,
+ 'parameters' => $parameters,
+ 'transChoiceNumber' => $number,
+ 'state' => $state,
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/CsvFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/CsvFileDumper.php
new file mode 100644
index 0000000..fe5dccb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/CsvFileDumper.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * CsvFileDumper generates a csv formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class CsvFileDumper extends FileDumper
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $handle = fopen('php://memory', 'rb+');
+
+ foreach ($messages->all($domain) as $source => $target) {
+ fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure);
+ }
+
+ rewind($handle);
+ $output = stream_get_contents($handle);
+ fclose($handle);
+
+ return $output;
+ }
+
+ /**
+ * Sets the delimiter and escape character for CSV.
+ *
+ * @param string $delimiter delimiter character
+ * @param string $enclosure enclosure character
+ */
+ public function setCsvControl($delimiter = ';', $enclosure = '"')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'csv';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/DumperInterface.php b/public/system/storage/vendor/symfony/translation/Dumper/DumperInterface.php
new file mode 100644
index 0000000..cebc65e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/DumperInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * DumperInterface is the interface implemented by all translation dumpers.
+ * There is no common option.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface DumperInterface
+{
+ /**
+ * Dumps the message catalogue.
+ *
+ * @param MessageCatalogue $messages The message catalogue
+ * @param array $options Options that are used by the dumper
+ */
+ public function dump(MessageCatalogue $messages, $options = array());
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/FileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/FileDumper.php
new file mode 100644
index 0000000..9c9a8ee
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/FileDumper.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
+ * Performs backup of already existing files.
+ *
+ * Options:
+ * - path (mandatory): the directory where the files should be saved
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+abstract class FileDumper implements DumperInterface
+{
+ /**
+ * A template for the relative paths to files.
+ *
+ * @var string
+ */
+ protected $relativePathTemplate = '%domain%.%locale%.%extension%';
+
+ /**
+ * Make file backup before the dump.
+ *
+ * @var bool
+ */
+ private $backup = true;
+
+ /**
+ * Sets the template for the relative paths to files.
+ *
+ * @param string $relativePathTemplate A template for the relative paths to files
+ */
+ public function setRelativePathTemplate($relativePathTemplate)
+ {
+ $this->relativePathTemplate = $relativePathTemplate;
+ }
+
+ /**
+ * Sets backup flag.
+ *
+ * @param bool
+ */
+ public function setBackup($backup)
+ {
+ $this->backup = $backup;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dump(MessageCatalogue $messages, $options = array())
+ {
+ if (!array_key_exists('path', $options)) {
+ throw new \InvalidArgumentException('The file dumper needs a path option.');
+ }
+
+ // save a file for each domain
+ foreach ($messages->getDomains() as $domain) {
+ // backup
+ $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
+ if (file_exists($fullpath)) {
+ if ($this->backup) {
+ copy($fullpath, $fullpath.'~');
+ }
+ } else {
+ $directory = dirname($fullpath);
+ if (!file_exists($directory) && !@mkdir($directory, 0777, true)) {
+ throw new \RuntimeException(sprintf('Unable to create directory "%s".', $directory));
+ }
+ }
+ // save file
+ file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
+ }
+ }
+
+ /**
+ * Transforms a domain of a message catalogue to its string representation.
+ *
+ * @param MessageCatalogue $messages
+ * @param string $domain
+ * @param array $options
+ *
+ * @return string representation
+ */
+ abstract public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array());
+
+ /**
+ * Gets the file extension of the dumper.
+ *
+ * @return string file extension
+ */
+ abstract protected function getExtension();
+
+ /**
+ * Gets the relative file path using the template.
+ *
+ * @param string $domain The domain
+ * @param string $locale The locale
+ *
+ * @return string The relative file path
+ */
+ private function getRelativePath($domain, $locale)
+ {
+ return strtr($this->relativePathTemplate, array(
+ '%domain%' => $domain,
+ '%locale%' => $locale,
+ '%extension%' => $this->getExtension(),
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/IcuResFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/IcuResFileDumper.php
new file mode 100644
index 0000000..ceb4b42
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/IcuResFileDumper.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class IcuResFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $relativePathTemplate = '%domain%/%locale%.%extension%';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $data = $indexes = $resources = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $indexes .= pack('v', strlen($data) + 28);
+ $data .= $source."\0";
+ }
+
+ $data .= $this->writePadding($data);
+
+ $keyTop = $this->getPosition($data);
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $resources .= pack('V', $this->getPosition($data));
+
+ $data .= pack('V', strlen($target))
+ .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
+ .$this->writePadding($data)
+ ;
+ }
+
+ $resOffset = $this->getPosition($data);
+
+ $data .= pack('v', count($messages))
+ .$indexes
+ .$this->writePadding($data)
+ .$resources
+ ;
+
+ $bundleTop = $this->getPosition($data);
+
+ $root = pack('V7',
+ $resOffset + (2 << 28), // Resource Offset + Resource Type
+ 6, // Index length
+ $keyTop, // Index keys top
+ $bundleTop, // Index resources top
+ $bundleTop, // Index bundle top
+ count($messages), // Index max table length
+ 0 // Index attributes
+ );
+
+ $header = pack('vC2v4C12@32',
+ 32, // Header size
+ 0xDA, 0x27, // Magic number 1 and 2
+ 20, 0, 0, 2, // Rest of the header, ..., Size of a char
+ 0x52, 0x65, 0x73, 0x42, // Data format identifier
+ 1, 2, 0, 0, // Data version
+ 1, 4, 0, 0 // Unicode version
+ );
+
+ return $header.$root.$data;
+ }
+
+ private function writePadding($data)
+ {
+ $padding = strlen($data) % 4;
+
+ if ($padding) {
+ return str_repeat("\xAA", 4 - $padding);
+ }
+ }
+
+ private function getPosition($data)
+ {
+ return (strlen($data) + 28) / 4;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'res';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/IniFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/IniFileDumper.php
new file mode 100644
index 0000000..9ed3754
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/IniFileDumper.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IniFileDumper generates an ini formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class IniFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $output = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $escapeTarget = str_replace('"', '\"', $target);
+ $output .= $source.'="'.$escapeTarget."\"\n";
+ }
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'ini';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/JsonFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/JsonFileDumper.php
new file mode 100644
index 0000000..08b538e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/JsonFileDumper.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * JsonFileDumper generates an json formatted string representation of a message catalogue.
+ *
+ * @author singles
+ */
+class JsonFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ if (isset($options['json_encoding'])) {
+ $flags = $options['json_encoding'];
+ } else {
+ $flags = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
+ }
+
+ return json_encode($messages->all($domain), $flags);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'json';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/MoFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/MoFileDumper.php
new file mode 100644
index 0000000..f9aae42
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/MoFileDumper.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Loader\MoFileLoader;
+
+/**
+ * MoFileDumper generates a gettext formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class MoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $output = $sources = $targets = $sourceOffsets = $targetOffsets = '';
+ $offsets = array();
+ $size = 0;
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $offsets[] = array_map('strlen', array($sources, $source, $targets, $target));
+ $sources .= "\0".$source;
+ $targets .= "\0".$target;
+ ++$size;
+ }
+
+ $header = array(
+ 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
+ 'formatRevision' => 0,
+ 'count' => $size,
+ 'offsetId' => MoFileLoader::MO_HEADER_SIZE,
+ 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
+ 'sizeHashes' => 0,
+ 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
+ );
+
+ $sourcesSize = strlen($sources);
+ $sourcesStart = $header['offsetHashes'] + 1;
+
+ foreach ($offsets as $offset) {
+ $sourceOffsets .= $this->writeLong($offset[1])
+ .$this->writeLong($offset[0] + $sourcesStart);
+ $targetOffsets .= $this->writeLong($offset[3])
+ .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
+ }
+
+ $output = implode(array_map(array($this, 'writeLong'), $header))
+ .$sourceOffsets
+ .$targetOffsets
+ .$sources
+ .$targets
+ ;
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'mo';
+ }
+
+ private function writeLong($str)
+ {
+ return pack('V*', $str);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/PhpFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/PhpFileDumper.php
new file mode 100644
index 0000000..c7c37aa
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/PhpFileDumper.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PhpFileDumper generates PHP files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class PhpFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ return "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'php';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/PoFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/PoFileDumper.php
new file mode 100644
index 0000000..ed4418b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/PoFileDumper.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PoFileDumper generates a gettext formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class PoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $output = 'msgid ""'."\n";
+ $output .= 'msgstr ""'."\n";
+ $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
+ $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
+ $output .= '"Language: '.$messages->getLocale().'\n"'."\n";
+ $output .= "\n";
+
+ $newLine = false;
+ foreach ($messages->all($domain) as $source => $target) {
+ if ($newLine) {
+ $output .= "\n";
+ } else {
+ $newLine = true;
+ }
+ $output .= sprintf('msgid "%s"'."\n", $this->escape($source));
+ $output .= sprintf('msgstr "%s"', $this->escape($target));
+ }
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'po';
+ }
+
+ private function escape($str)
+ {
+ return addcslashes($str, "\0..\37\42\134");
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/QtFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/QtFileDumper.php
new file mode 100644
index 0000000..a9073f2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/QtFileDumper.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * QtFileDumper generates ts files from a message catalogue.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+ $ts = $dom->appendChild($dom->createElement('TS'));
+ $context = $ts->appendChild($dom->createElement('context'));
+ $context->appendChild($dom->createElement('name', $domain));
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $message = $context->appendChild($dom->createElement('message'));
+ $message->appendChild($dom->createElement('source', $source));
+ $message->appendChild($dom->createElement('translation', $target));
+ }
+
+ return $dom->saveXML();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'ts';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/XliffFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/XliffFileDumper.php
new file mode 100644
index 0000000..915dbca
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/XliffFileDumper.php
@@ -0,0 +1,183 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * XliffFileDumper generates xliff files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class XliffFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $xliffVersion = '1.2';
+ if (array_key_exists('xliff_version', $options)) {
+ $xliffVersion = $options['xliff_version'];
+ }
+
+ if (array_key_exists('default_locale', $options)) {
+ $defaultLocale = $options['default_locale'];
+ } else {
+ $defaultLocale = \Locale::getDefault();
+ }
+
+ if ('1.2' === $xliffVersion) {
+ return $this->dumpXliff1($defaultLocale, $messages, $domain, $options);
+ }
+ if ('2.0' === $xliffVersion) {
+ return $this->dumpXliff2($defaultLocale, $messages, $domain, $options);
+ }
+
+ throw new \InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'xlf';
+ }
+
+ private function dumpXliff1($defaultLocale, MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $toolInfo = array('tool-id' => 'symfony', 'tool-name' => 'Symfony');
+ if (array_key_exists('tool_info', $options)) {
+ $toolInfo = array_merge($toolInfo, $options['tool_info']);
+ }
+
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+
+ $xliff = $dom->appendChild($dom->createElement('xliff'));
+ $xliff->setAttribute('version', '1.2');
+ $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');
+
+ $xliffFile = $xliff->appendChild($dom->createElement('file'));
+ $xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale));
+ $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale()));
+ $xliffFile->setAttribute('datatype', 'plaintext');
+ $xliffFile->setAttribute('original', 'file.ext');
+
+ $xliffHead = $xliffFile->appendChild($dom->createElement('header'));
+ $xliffTool = $xliffHead->appendChild($dom->createElement('tool'));
+ foreach ($toolInfo as $id => $value) {
+ $xliffTool->setAttribute($id, $value);
+ }
+
+ $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
+ foreach ($messages->all($domain) as $source => $target) {
+ $translation = $dom->createElement('trans-unit');
+
+ $translation->setAttribute('id', md5($source));
+ $translation->setAttribute('resname', $source);
+
+ $s = $translation->appendChild($dom->createElement('source'));
+ $s->appendChild($dom->createTextNode($source));
+
+ // Does the target contain characters requiring a CDATA section?
+ $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
+
+ $targetElement = $dom->createElement('target');
+ $metadata = $messages->getMetadata($source, $domain);
+ if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
+ foreach ($metadata['target-attributes'] as $name => $value) {
+ $targetElement->setAttribute($name, $value);
+ }
+ }
+ $t = $translation->appendChild($targetElement);
+ $t->appendChild($text);
+
+ if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ foreach ($metadata['notes'] as $note) {
+ if (!isset($note['content'])) {
+ continue;
+ }
+
+ $n = $translation->appendChild($dom->createElement('note'));
+ $n->appendChild($dom->createTextNode($note['content']));
+
+ if (isset($note['priority'])) {
+ $n->setAttribute('priority', $note['priority']);
+ }
+
+ if (isset($note['from'])) {
+ $n->setAttribute('from', $note['from']);
+ }
+ }
+ }
+
+ $xliffBody->appendChild($translation);
+ }
+
+ return $dom->saveXML();
+ }
+
+ private function dumpXliff2($defaultLocale, MessageCatalogue $messages, $domain, array $options = array())
+ {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+
+ $xliff = $dom->appendChild($dom->createElement('xliff'));
+ $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0');
+ $xliff->setAttribute('version', '2.0');
+ $xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale));
+ $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));
+
+ $xliffFile = $xliff->appendChild($dom->createElement('file'));
+ $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $translation = $dom->createElement('unit');
+ $translation->setAttribute('id', md5($source));
+
+ $segment = $translation->appendChild($dom->createElement('segment'));
+
+ $s = $segment->appendChild($dom->createElement('source'));
+ $s->appendChild($dom->createTextNode($source));
+
+ // Does the target contain characters requiring a CDATA section?
+ $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
+
+ $targetElement = $dom->createElement('target');
+ $metadata = $messages->getMetadata($source, $domain);
+ if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
+ foreach ($metadata['target-attributes'] as $name => $value) {
+ $targetElement->setAttribute($name, $value);
+ }
+ }
+ $t = $segment->appendChild($targetElement);
+ $t->appendChild($text);
+
+ $xliffFile->appendChild($translation);
+ }
+
+ return $dom->saveXML();
+ }
+
+ /**
+ * @param string $key
+ * @param array|null $metadata
+ *
+ * @return bool
+ */
+ private function hasMetadataArrayInfo($key, $metadata = null)
+ {
+ return null !== $metadata && array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || is_array($metadata[$key]));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Dumper/YamlFileDumper.php b/public/system/storage/vendor/symfony/translation/Dumper/YamlFileDumper.php
new file mode 100644
index 0000000..625953c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Dumper/YamlFileDumper.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Util\ArrayConverter;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * YamlFileDumper generates yaml files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class YamlFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ if (!class_exists('Symfony\Component\Yaml\Yaml')) {
+ throw new \LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.');
+ }
+
+ $data = $messages->all($domain);
+
+ if (isset($options['as_tree']) && $options['as_tree']) {
+ $data = ArrayConverter::expandToTree($data);
+ }
+
+ if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) {
+ return Yaml::dump($data, $inline);
+ }
+
+ return Yaml::dump($data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'yml';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Exception/ExceptionInterface.php b/public/system/storage/vendor/symfony/translation/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..c85fb93
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Exception interface for all exceptions thrown by the component.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/translation/Exception/InvalidResourceException.php b/public/system/storage/vendor/symfony/translation/Exception/InvalidResourceException.php
new file mode 100644
index 0000000..cf07943
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Exception/InvalidResourceException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Thrown when a resource cannot be loaded.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/translation/Exception/NotFoundResourceException.php b/public/system/storage/vendor/symfony/translation/Exception/NotFoundResourceException.php
new file mode 100644
index 0000000..cff73ae
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Exception/NotFoundResourceException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Thrown when a resource does not exist.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/translation/Extractor/AbstractFileExtractor.php b/public/system/storage/vendor/symfony/translation/Extractor/AbstractFileExtractor.php
new file mode 100644
index 0000000..57fd493
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Extractor/AbstractFileExtractor.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+/**
+ * Base class used by classes that extract translation messages from files.
+ *
+ * @author Marcos D. Sánchez <marcosdsanchez@gmail.com>
+ */
+abstract class AbstractFileExtractor
+{
+ /**
+ * @param string|array $resource files, a file or a directory
+ *
+ * @return array
+ */
+ protected function extractFiles($resource)
+ {
+ if (is_array($resource) || $resource instanceof \Traversable) {
+ $files = array();
+ foreach ($resource as $file) {
+ if ($this->canBeExtracted($file)) {
+ $files[] = $this->toSplFileInfo($file);
+ }
+ }
+ } elseif (is_file($resource)) {
+ $files = $this->canBeExtracted($resource) ? array($this->toSplFileInfo($resource)) : array();
+ } else {
+ $files = $this->extractFromDirectory($resource);
+ }
+
+ return $files;
+ }
+
+ /**
+ * @param string $file
+ *
+ * @return \SplFileInfo
+ */
+ private function toSplFileInfo($file)
+ {
+ return ($file instanceof \SplFileInfo) ? $file : new \SplFileInfo($file);
+ }
+
+ /**
+ * @param string $file
+ *
+ * @return bool
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected function isFile($file)
+ {
+ if (!is_file($file)) {
+ throw new \InvalidArgumentException(sprintf('The "%s" file does not exist.', $file));
+ }
+
+ return true;
+ }
+
+ /**
+ * @param string $file
+ *
+ * @return bool
+ */
+ abstract protected function canBeExtracted($file);
+
+ /**
+ * @param string|array $resource files, a file or a directory
+ *
+ * @return array files to be extracted
+ */
+ abstract protected function extractFromDirectory($resource);
+}
diff --git a/public/system/storage/vendor/symfony/translation/Extractor/ChainExtractor.php b/public/system/storage/vendor/symfony/translation/Extractor/ChainExtractor.php
new file mode 100644
index 0000000..50e3c84
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Extractor/ChainExtractor.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ChainExtractor extracts translation messages from template files.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class ChainExtractor implements ExtractorInterface
+{
+ /**
+ * The extractors.
+ *
+ * @var ExtractorInterface[]
+ */
+ private $extractors = array();
+
+ /**
+ * Adds a loader to the translation extractor.
+ *
+ * @param string $format The format of the loader
+ * @param ExtractorInterface $extractor The loader
+ */
+ public function addExtractor($format, ExtractorInterface $extractor)
+ {
+ $this->extractors[$format] = $extractor;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPrefix($prefix)
+ {
+ foreach ($this->extractors as $extractor) {
+ $extractor->setPrefix($prefix);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extract($directory, MessageCatalogue $catalogue)
+ {
+ foreach ($this->extractors as $extractor) {
+ $extractor->extract($directory, $catalogue);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Extractor/ExtractorInterface.php b/public/system/storage/vendor/symfony/translation/Extractor/ExtractorInterface.php
new file mode 100644
index 0000000..438f80b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Extractor/ExtractorInterface.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * Extracts translation messages from a directory or files to the catalogue.
+ * New found messages are injected to the catalogue using the prefix.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface ExtractorInterface
+{
+ /**
+ * Extracts translation messages from files, a file or a directory to the catalogue.
+ *
+ * @param string|array $resource files, a file or a directory
+ * @param MessageCatalogue $catalogue The catalogue
+ */
+ public function extract($resource, MessageCatalogue $catalogue);
+
+ /**
+ * Sets the prefix that should be used for new found messages.
+ *
+ * @param string $prefix The prefix
+ */
+ public function setPrefix($prefix);
+}
diff --git a/public/system/storage/vendor/symfony/translation/IdentityTranslator.php b/public/system/storage/vendor/symfony/translation/IdentityTranslator.php
new file mode 100644
index 0000000..46a0463
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/IdentityTranslator.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * IdentityTranslator does not translate anything.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class IdentityTranslator implements TranslatorInterface
+{
+ private $selector;
+ private $locale;
+
+ /**
+ * Constructor.
+ *
+ * @param MessageSelector|null $selector The message selector for pluralization
+ */
+ public function __construct(MessageSelector $selector = null)
+ {
+ $this->selector = $selector ?: new MessageSelector();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale ?: \Locale::getDefault();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+ {
+ return strtr((string) $id, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+ {
+ return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Interval.php b/public/system/storage/vendor/symfony/translation/Interval.php
new file mode 100644
index 0000000..2a51156
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Interval.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * Tests if a given number belongs to a given math interval.
+ *
+ * An interval can represent a finite set of numbers:
+ *
+ * {1,2,3,4}
+ *
+ * An interval can represent numbers between two numbers:
+ *
+ * [1, +Inf]
+ * ]-1,2[
+ *
+ * The left delimiter can be [ (inclusive) or ] (exclusive).
+ * The right delimiter can be [ (exclusive) or ] (inclusive).
+ * Beside numbers, you can use -Inf and +Inf for the infinite.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation
+ */
+class Interval
+{
+ /**
+ * Tests if the given number is in the math interval.
+ *
+ * @param int $number A number
+ * @param string $interval An interval
+ *
+ * @return bool
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function test($number, $interval)
+ {
+ $interval = trim($interval);
+
+ if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) {
+ throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval));
+ }
+
+ if ($matches[1]) {
+ foreach (explode(',', $matches[2]) as $n) {
+ if ($number == $n) {
+ return true;
+ }
+ }
+ } else {
+ $leftNumber = self::convertNumber($matches['left']);
+ $rightNumber = self::convertNumber($matches['right']);
+
+ return
+ ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
+ && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
+ ;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a Regexp that matches valid intervals.
+ *
+ * @return string A Regexp (without the delimiters)
+ */
+ public static function getIntervalRegexp()
+ {
+ return <<<EOF
+ ({\s*
+ (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
+ \s*})
+
+ |
+
+ (?P<left_delimiter>[\[\]])
+ \s*
+ (?P<left>-Inf|\-?\d+(\.\d+)?)
+ \s*,\s*
+ (?P<right>\+?Inf|\-?\d+(\.\d+)?)
+ \s*
+ (?P<right_delimiter>[\[\]])
+EOF;
+ }
+
+ private static function convertNumber($number)
+ {
+ if ('-Inf' === $number) {
+ return log(0);
+ } elseif ('+Inf' === $number || 'Inf' === $number) {
+ return -log(0);
+ }
+
+ return (float) $number;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/LICENSE b/public/system/storage/vendor/symfony/translation/LICENSE
new file mode 100644
index 0000000..12a7453
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2016 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/symfony/translation/Loader/ArrayLoader.php b/public/system/storage/vendor/symfony/translation/Loader/ArrayLoader.php
new file mode 100644
index 0000000..9a595b7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/ArrayLoader.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ArrayLoader loads translations from a PHP array.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ArrayLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $locale, $domain = 'messages')
+ {
+ $this->flatten($resource);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($resource, $domain);
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an nested array of translations.
+ *
+ * The scheme used is:
+ * 'key' => array('key2' => array('key3' => 'value'))
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ *
+ * This function takes an array by reference and will modify it
+ *
+ * @param array &$messages The array that will be flattened
+ * @param array $subnode Current subnode being parsed, used internally for recursive calls
+ * @param string $path Current path being parsed, used internally for recursive calls
+ */
+ private function flatten(array &$messages, array $subnode = null, $path = null)
+ {
+ if (null === $subnode) {
+ $subnode = &$messages;
+ }
+ foreach ($subnode as $key => $value) {
+ if (is_array($value)) {
+ $nodePath = $path ? $path.'.'.$key : $key;
+ $this->flatten($messages, $value, $nodePath);
+ if (null === $path) {
+ unset($messages[$key]);
+ }
+ } elseif (null !== $path) {
+ $messages[$path.'.'.$key] = $value;
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/CsvFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/CsvFileLoader.php
new file mode 100644
index 0000000..f1d3443
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/CsvFileLoader.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * CsvFileLoader loads translations from CSV files.
+ *
+ * @author Saša Stamenković <umpirsky@gmail.com>
+ */
+class CsvFileLoader extends FileLoader
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+ private $escape = '\\';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ $messages = array();
+
+ try {
+ $file = new \SplFileObject($resource, 'rb');
+ } catch (\RuntimeException $e) {
+ throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
+ }
+
+ $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
+ $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);
+
+ foreach ($file as $data) {
+ if ('#' !== substr($data[0], 0, 1) && isset($data[1]) && 2 === count($data)) {
+ $messages[$data[0]] = $data[1];
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Sets the delimiter, enclosure, and escape character for CSV.
+ *
+ * @param string $delimiter delimiter character
+ * @param string $enclosure enclosure character
+ * @param string $escape escape character
+ */
+ public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ $this->escape = $escape;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/FileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/FileLoader.php
new file mode 100644
index 0000000..a7f24f4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/FileLoader.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Config\Resource\FileResource;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+abstract class FileLoader extends ArrayLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $locale, $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ $messages = $this->loadResource($resource);
+
+ // empty resource
+ if (null === $messages) {
+ $messages = array();
+ }
+
+ // not an array
+ if (!is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ $catalogue = parent::load($messages, $locale, $domain);
+
+ if (class_exists('Symfony\Component\Config\Resource\FileResource')) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /*
+ * @param string $resource
+ *
+ * @return array
+ *
+ * @throws InvalidResourceException If stream content has an invalid format.
+ */
+ abstract protected function loadResource($resource);
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/IcuDatFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/IcuDatFileLoader.php
new file mode 100644
index 0000000..71ba90a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/IcuDatFileLoader.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Config\Resource\FileResource;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuDatFileLoader extends IcuResFileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $locale, $domain = 'messages')
+ {
+ if (!stream_is_local($resource.'.dat')) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource.'.dat')) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ // HHVM compatibility: constructor throws on invalid resource
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists('Symfony\Component\Config\Resource\FileResource')) {
+ $catalogue->addResource(new FileResource($resource.'.dat'));
+ }
+
+ return $catalogue;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/IcuResFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/IcuResFileLoader.php
new file mode 100644
index 0000000..2f8037f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/IcuResFileLoader.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Config\Resource\DirectoryResource;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuResFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $locale, $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!is_dir($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ // HHVM compatibility: constructor throws on invalid resource
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists('Symfony\Component\Config\Resource\DirectoryResource')) {
+ $catalogue->addResource(new DirectoryResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an ResourceBundle.
+ *
+ * The scheme used is:
+ * key { key2 { key3 { "value" } } }
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ *
+ * This function takes an array by reference and will modify it
+ *
+ * @param \ResourceBundle $rb the ResourceBundle that will be flattened
+ * @param array $messages used internally for recursive calls
+ * @param string $path current path being parsed, used internally for recursive calls
+ *
+ * @return array the flattened ResourceBundle
+ */
+ protected function flatten(\ResourceBundle $rb, array &$messages = array(), $path = null)
+ {
+ foreach ($rb as $key => $value) {
+ $nodePath = $path ? $path.'.'.$key : $key;
+ if ($value instanceof \ResourceBundle) {
+ $this->flatten($value, $messages, $nodePath);
+ } else {
+ $messages[$nodePath] = $value;
+ }
+ }
+
+ return $messages;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/IniFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/IniFileLoader.php
new file mode 100644
index 0000000..11d9b27
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/IniFileLoader.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * IniFileLoader loads translations from an ini file.
+ *
+ * @author stealth35
+ */
+class IniFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ return parse_ini_file($resource, true);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/JsonFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/JsonFileLoader.php
new file mode 100644
index 0000000..ce4e91f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/JsonFileLoader.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * JsonFileLoader loads translations from an json file.
+ *
+ * @author singles
+ */
+class JsonFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ $messages = array();
+ if ($data = file_get_contents($resource)) {
+ $messages = json_decode($data, true);
+
+ if (0 < $errorCode = json_last_error()) {
+ throw new InvalidResourceException(sprintf('Error parsing JSON - %s', $this->getJSONErrorMessage($errorCode)));
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Translates JSON_ERROR_* constant into meaningful message.
+ *
+ * @param int $errorCode Error code returned by json_last_error() call
+ *
+ * @return string Message string
+ */
+ private function getJSONErrorMessage($errorCode)
+ {
+ switch ($errorCode) {
+ case JSON_ERROR_DEPTH:
+ return 'Maximum stack depth exceeded';
+ case JSON_ERROR_STATE_MISMATCH:
+ return 'Underflow or the modes mismatch';
+ case JSON_ERROR_CTRL_CHAR:
+ return 'Unexpected control character found';
+ case JSON_ERROR_SYNTAX:
+ return 'Syntax error, malformed JSON';
+ case JSON_ERROR_UTF8:
+ return 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ default:
+ return 'Unknown error';
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/LoaderInterface.php b/public/system/storage/vendor/symfony/translation/Loader/LoaderInterface.php
new file mode 100644
index 0000000..6b65fe3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/LoaderInterface.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * LoaderInterface is the interface implemented by all translation loaders.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface LoaderInterface
+{
+ /**
+ * Loads a locale.
+ *
+ * @param mixed $resource A resource
+ * @param string $locale A locale
+ * @param string $domain The domain
+ *
+ * @return MessageCatalogue A MessageCatalogue instance
+ *
+ * @throws NotFoundResourceException when the resource cannot be found
+ * @throws InvalidResourceException when the resource cannot be loaded
+ */
+ public function load($resource, $locale, $domain = 'messages');
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/MoFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/MoFileLoader.php
new file mode 100644
index 0000000..2fcada2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/MoFileLoader.php
@@ -0,0 +1,154 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
+ */
+class MoFileLoader extends FileLoader
+{
+ /**
+ * Magic used for validating the format of a MO file as well as
+ * detecting if the machine used to create that file was little endian.
+ *
+ * @var float
+ */
+ const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;
+
+ /**
+ * Magic used for validating the format of a MO file as well as
+ * detecting if the machine used to create that file was big endian.
+ *
+ * @var float
+ */
+ const MO_BIG_ENDIAN_MAGIC = 0xde120495;
+
+ /**
+ * The size of the header of a MO file in bytes.
+ *
+ * @var int Number of bytes
+ */
+ const MO_HEADER_SIZE = 28;
+
+ /**
+ * Parses machine object (MO) format, independent of the machine's endian it
+ * was created on. Both 32bit and 64bit systems are supported.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $stat = fstat($stream);
+
+ if ($stat['size'] < self::MO_HEADER_SIZE) {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+ $magic = unpack('V1', fread($stream, 4));
+ $magic = hexdec(substr(dechex(current($magic)), -8));
+
+ if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) {
+ $isBigEndian = false;
+ } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) {
+ $isBigEndian = true;
+ } else {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+
+ // formatRevision
+ $this->readLong($stream, $isBigEndian);
+ $count = $this->readLong($stream, $isBigEndian);
+ $offsetId = $this->readLong($stream, $isBigEndian);
+ $offsetTranslated = $this->readLong($stream, $isBigEndian);
+ // sizeHashes
+ $this->readLong($stream, $isBigEndian);
+ // offsetHashes
+ $this->readLong($stream, $isBigEndian);
+
+ $messages = array();
+
+ for ($i = 0; $i < $count; ++$i) {
+ $singularId = $pluralId = null;
+ $translated = null;
+
+ fseek($stream, $offsetId + $i * 8);
+
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $singularId = fread($stream, $length);
+
+ if (strpos($singularId, "\000") !== false) {
+ list($singularId, $pluralId) = explode("\000", $singularId);
+ }
+
+ fseek($stream, $offsetTranslated + $i * 8);
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $translated = fread($stream, $length);
+
+ if (strpos($translated, "\000") !== false) {
+ $translated = explode("\000", $translated);
+ }
+
+ $ids = array('singular' => $singularId, 'plural' => $pluralId);
+ $item = compact('ids', 'translated');
+
+ if (is_array($item['translated'])) {
+ $messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]);
+ if (isset($item['ids']['plural'])) {
+ $plurals = array();
+ foreach ($item['translated'] as $plural => $translated) {
+ $plurals[] = sprintf('{%d} %s', $plural, $translated);
+ }
+ $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
+ }
+ } elseif (!empty($item['ids']['singular'])) {
+ $messages[$item['ids']['singular']] = stripcslashes($item['translated']);
+ }
+ }
+
+ fclose($stream);
+
+ return array_filter($messages);
+ }
+
+ /**
+ * Reads an unsigned long from stream respecting endianess.
+ *
+ * @param resource $stream
+ * @param bool $isBigEndian
+ *
+ * @return int
+ */
+ private function readLong($stream, $isBigEndian)
+ {
+ $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
+ $result = current($result);
+
+ return (int) substr($result, -8);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/PhpFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/PhpFileLoader.php
new file mode 100644
index 0000000..a0050e8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/PhpFileLoader.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * PhpFileLoader loads translations from PHP files returning an array of translations.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class PhpFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ return require $resource;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/PoFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/PoFileLoader.php
new file mode 100644
index 0000000..40f5464
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/PoFileLoader.php
@@ -0,0 +1,151 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
+ * @copyright Copyright (c) 2012, Clemens Tolboom
+ */
+class PoFileLoader extends FileLoader
+{
+ /**
+ * Parses portable object (PO) format.
+ *
+ * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
+ * we should be able to parse files having:
+ *
+ * white-space
+ * # translator-comments
+ * #. extracted-comments
+ * #: reference...
+ * #, flag...
+ * #| msgid previous-untranslated-string
+ * msgid untranslated-string
+ * msgstr translated-string
+ *
+ * extra or different lines are:
+ *
+ * #| msgctxt previous-context
+ * #| msgid previous-untranslated-string
+ * msgctxt context
+ *
+ * #| msgid previous-untranslated-string-singular
+ * #| msgid_plural previous-untranslated-string-plural
+ * msgid untranslated-string-singular
+ * msgid_plural untranslated-string-plural
+ * msgstr[0] translated-string-case-0
+ * ...
+ * msgstr[N] translated-string-case-n
+ *
+ * The definition states:
+ * - white-space and comments are optional.
+ * - msgid "" that an empty singleline defines a header.
+ *
+ * This parser sacrifices some features of the reference implementation the
+ * differences to that implementation are as follows.
+ * - No support for comments spanning multiple lines.
+ * - Translator and extracted comments are treated as being the same type.
+ * - Message IDs are allowed to have other encodings as just US-ASCII.
+ *
+ * Items with an empty id are ignored.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $defaults = array(
+ 'ids' => array(),
+ 'translated' => null,
+ );
+
+ $messages = array();
+ $item = $defaults;
+ $flags = array();
+
+ while ($line = fgets($stream)) {
+ $line = trim($line);
+
+ if ($line === '') {
+ // Whitespace indicated current item is done
+ if (!in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ $item = $defaults;
+ $flags = array();
+ } elseif (substr($line, 0, 2) === '#,') {
+ $flags = array_map('trim', explode(',', substr($line, 2)));
+ } elseif (substr($line, 0, 7) === 'msgid "') {
+ // We start a new msg so save previous
+ // TODO: this fails when comments or contexts are added
+ $this->addMessage($messages, $item);
+ $item = $defaults;
+ $item['ids']['singular'] = substr($line, 7, -1);
+ } elseif (substr($line, 0, 8) === 'msgstr "') {
+ $item['translated'] = substr($line, 8, -1);
+ } elseif ($line[0] === '"') {
+ $continues = isset($item['translated']) ? 'translated' : 'ids';
+
+ if (is_array($item[$continues])) {
+ end($item[$continues]);
+ $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
+ } else {
+ $item[$continues] .= substr($line, 1, -1);
+ }
+ } elseif (substr($line, 0, 14) === 'msgid_plural "') {
+ $item['ids']['plural'] = substr($line, 14, -1);
+ } elseif (substr($line, 0, 7) === 'msgstr[') {
+ $size = strpos($line, ']');
+ $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
+ }
+ }
+ // save last item
+ if (!in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ fclose($stream);
+
+ return $messages;
+ }
+
+ /**
+ * Save a translation item to the messages.
+ *
+ * A .po file could contain by error missing plural indexes. We need to
+ * fix these before saving them.
+ *
+ * @param array $messages
+ * @param array $item
+ */
+ private function addMessage(array &$messages, array $item)
+ {
+ if (is_array($item['translated'])) {
+ $messages[stripcslashes($item['ids']['singular'])] = stripcslashes($item['translated'][0]);
+ if (isset($item['ids']['plural'])) {
+ $plurals = $item['translated'];
+ // PO are by definition indexed so sort by index.
+ ksort($plurals);
+ // Make sure every index is filled.
+ end($plurals);
+ $count = key($plurals);
+ // Fill missing spots with '-'.
+ $empties = array_fill(0, $count + 1, '-');
+ $plurals += $empties;
+ ksort($plurals);
+ $messages[stripcslashes($item['ids']['plural'])] = stripcslashes(implode('|', $plurals));
+ }
+ } elseif (!empty($item['ids']['singular'])) {
+ $messages[stripcslashes($item['ids']['singular'])] = stripcslashes($item['translated']);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/QtFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/QtFileLoader.php
new file mode 100644
index 0000000..657bd6e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/QtFileLoader.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Config\Resource\FileResource;
+
+/**
+ * QtFileLoader loads translations from QT Translations XML files.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $locale, $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $dom = XmlUtils::loadFile($resource);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
+ }
+
+ $internalErrors = libxml_use_internal_errors(true);
+ libxml_clear_errors();
+
+ $xpath = new \DOMXPath($dom);
+ $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');
+
+ $catalogue = new MessageCatalogue($locale);
+ if ($nodes->length == 1) {
+ $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
+ foreach ($translations as $translation) {
+ $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;
+
+ if (!empty($translationValue)) {
+ $catalogue->set(
+ (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
+ $translationValue,
+ $domain
+ );
+ }
+ $translation = $translation->nextSibling;
+ }
+
+ if (class_exists('Symfony\Component\Config\Resource\FileResource')) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+ }
+
+ libxml_use_internal_errors($internalErrors);
+
+ return $catalogue;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/XliffFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/XliffFileLoader.php
new file mode 100644
index 0000000..d3fbec9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/XliffFileLoader.php
@@ -0,0 +1,321 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Config\Resource\FileResource;
+
+/**
+ * XliffFileLoader loads translations from XLIFF files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class XliffFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $locale, $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ $catalogue = new MessageCatalogue($locale);
+ $this->extract($resource, $catalogue, $domain);
+
+ if (class_exists('Symfony\Component\Config\Resource\FileResource')) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ private function extract($resource, MessageCatalogue $catalogue, $domain)
+ {
+ try {
+ $dom = XmlUtils::loadFile($resource);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s": %s', $resource, $e->getMessage()), $e->getCode(), $e);
+ }
+
+ $xliffVersion = $this->getVersionNumber($dom);
+ $this->validateSchema($xliffVersion, $dom, $this->getSchema($xliffVersion));
+
+ if ('1.2' === $xliffVersion) {
+ $this->extractXliff1($dom, $catalogue, $domain);
+ }
+
+ if ('2.0' === $xliffVersion) {
+ $this->extractXliff2($dom, $catalogue, $domain);
+ }
+ }
+
+ /**
+ * Extract messages and metadata from DOMDocument into a MessageCatalogue.
+ *
+ * @param \DOMDocument $dom Source to extract messages and metadata
+ * @param MessageCatalogue $catalogue Catalogue where we'll collect messages and metadata
+ * @param string $domain The domain
+ */
+ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = strtoupper($dom->encoding);
+
+ $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2');
+ foreach ($xml->xpath('//xliff:trans-unit') as $translation) {
+ $attributes = $translation->attributes();
+
+ if (!(isset($attributes['resname']) || isset($translation->source))) {
+ continue;
+ }
+
+ $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) (isset($translation->target) ? $translation->target : $source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = array();
+ if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
+ $metadata['notes'] = $notes;
+ }
+ if (isset($translation->target) && $translation->target->attributes()) {
+ $metadata['target-attributes'] = array();
+ foreach ($translation->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+
+ /**
+ * @param \DOMDocument $dom
+ * @param MessageCatalogue $catalogue
+ * @param string $domain
+ */
+ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = strtoupper($dom->encoding);
+
+ $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');
+
+ foreach ($xml->xpath('//xliff:unit/xliff:segment') as $segment) {
+ $source = $segment->source;
+
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) (isset($segment->target) ? $segment->target : $source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = array();
+ if (isset($segment->target) && $segment->target->attributes()) {
+ $metadata['target-attributes'] = array();
+ foreach ($segment->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+
+ /**
+ * Convert a UTF8 string to the specified encoding.
+ *
+ * @param string $content String to decode
+ * @param string $encoding Target encoding
+ *
+ * @return string
+ */
+ private function utf8ToCharset($content, $encoding = null)
+ {
+ if ('UTF-8' !== $encoding && !empty($encoding)) {
+ return mb_convert_encoding($content, $encoding, 'UTF-8');
+ }
+
+ return $content;
+ }
+
+ /**
+ * Validates and parses the given file into a DOMDocument.
+ *
+ * @param string $file
+ * @param \DOMDocument $dom
+ * @param string $schema source of the schema
+ *
+ * @throws InvalidResourceException
+ */
+ private function validateSchema($file, \DOMDocument $dom, $schema)
+ {
+ $internalErrors = libxml_use_internal_errors(true);
+
+ $disableEntities = libxml_disable_entity_loader(false);
+
+ if (!@$dom->schemaValidateSource($schema)) {
+ libxml_disable_entity_loader($disableEntities);
+
+ throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: %s', $file, implode("\n", $this->getXmlErrors($internalErrors))));
+ }
+
+ libxml_disable_entity_loader($disableEntities);
+
+ $dom->normalizeDocument();
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+ }
+
+ private function getSchema($xliffVersion)
+ {
+ if ('1.2' === $xliffVersion) {
+ $schemaSource = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd');
+ $xmlUri = 'http://www.w3.org/2001/xml.xsd';
+ } elseif ('2.0' === $xliffVersion) {
+ $schemaSource = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-2.0.xsd');
+ $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
+ } else {
+ throw new \InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
+ }
+
+ return $this->fixXmlLocation($schemaSource, $xmlUri);
+ }
+
+ /**
+ * Internally changes the URI of a dependent xsd to be loaded locally.
+ *
+ * @param string $schemaSource Current content of schema file
+ * @param string $xmlUri External URI of XML to convert to local
+ *
+ * @return string
+ */
+ private function fixXmlLocation($schemaSource, $xmlUri)
+ {
+ $newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
+ $parts = explode('/', $newPath);
+ if (0 === stripos($newPath, 'phar://')) {
+ $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
+ if ($tmpfile) {
+ copy($newPath, $tmpfile);
+ $parts = explode('/', str_replace('\\', '/', $tmpfile));
+ }
+ }
+ $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
+ $newPath = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
+
+ return str_replace($xmlUri, $newPath, $schemaSource);
+ }
+
+ /**
+ * Returns the XML errors of the internal XML parser.
+ *
+ * @param bool $internalErrors
+ *
+ * @return array An array of errors
+ */
+ private function getXmlErrors($internalErrors)
+ {
+ $errors = array();
+ foreach (libxml_get_errors() as $error) {
+ $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
+ LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
+ $error->code,
+ trim($error->message),
+ $error->file ?: 'n/a',
+ $error->line,
+ $error->column
+ );
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+
+ return $errors;
+ }
+
+ /**
+ * Gets xliff file version based on the root "version" attribute.
+ * Defaults to 1.2 for backwards compatibility.
+ *
+ * @param \DOMDocument $dom
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return string
+ */
+ private function getVersionNumber(\DOMDocument $dom)
+ {
+ /** @var \DOMNode $xliff */
+ foreach ($dom->getElementsByTagName('xliff') as $xliff) {
+ $version = $xliff->attributes->getNamedItem('version');
+ if ($version) {
+ return $version->nodeValue;
+ }
+
+ $namespace = $xliff->attributes->getNamedItem('xmlns');
+ if ($namespace) {
+ if (substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34) !== 0) {
+ throw new \InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s"', $namespace));
+ }
+
+ return substr($namespace, 34);
+ }
+ }
+
+ // Falls back to v1.2
+ return '1.2';
+ }
+
+ /*
+ * @param \SimpleXMLElement|null $noteElement
+ * @param string|null $encoding
+ *
+ * @return array
+ */
+ private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, $encoding = null)
+ {
+ $notes = array();
+
+ if (null === $noteElement) {
+ return $notes;
+ }
+
+ foreach ($noteElement as $xmlNote) {
+ $noteAttributes = $xmlNote->attributes();
+ $note = array('content' => $this->utf8ToCharset((string) $xmlNote, $encoding));
+ if (isset($noteAttributes['priority'])) {
+ $note['priority'] = (int) $noteAttributes['priority'];
+ }
+
+ if (isset($noteAttributes['from'])) {
+ $note['from'] = (string) $noteAttributes['from'];
+ }
+
+ $notes[] = $note;
+ }
+
+ return $notes;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/YamlFileLoader.php b/public/system/storage/vendor/symfony/translation/Loader/YamlFileLoader.php
new file mode 100644
index 0000000..5d9a3ad
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/YamlFileLoader.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Yaml\Parser as YamlParser;
+use Symfony\Component\Yaml\Exception\ParseException;
+
+/**
+ * YamlFileLoader loads translations from Yaml files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class YamlFileLoader extends FileLoader
+{
+ private $yamlParser;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource($resource)
+ {
+ if (null === $this->yamlParser) {
+ if (!class_exists('Symfony\Component\Yaml\Parser')) {
+ throw new \LogicException('Loading translations from the YAML format requires the Symfony Yaml component.');
+ }
+
+ $this->yamlParser = new YamlParser();
+ }
+
+ try {
+ $messages = $this->yamlParser->parse(file_get_contents($resource));
+ } catch (ParseException $e) {
+ throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e);
+ }
+
+ return $messages;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd b/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd
new file mode 100644
index 0000000..3ce2a8e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd
@@ -0,0 +1,2223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+
+May-19-2004:
+- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements
+to <choice> itself.
+- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
+<alt-trans>.
+
+Oct-2005
+- updated version info to 1.2
+- equiv-trans attribute to <trans-unit> element
+- merged-trans attribute for <group> element
+- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source>
+- Create a new value "seg" for the mtype attribute of the <mrk> element
+- Add mid as an optional attribute for the <alt-trans> element
+
+Nov-14-2005
+- Changed name attribute for <context-group> from required to optional
+- Added extension point at <xliff>
+
+Jan-9-2006
+- Added alttranstype type attribute to <alt-trans>, and values
+
+Jan-10-2006
+- Corrected error with overwritten purposeValueList
+- Corrected name="AttrType_Version", attribute should have been "name"
+
+-->
+<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
+ <!-- Import for xml:lang and xml:space -->
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <!-- Attributes Lists -->
+ <xsd:simpleType name="XTend">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="x-[^\s]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="context-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a database content.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="element">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="elementtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linenumber">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the &lt;source&gt; is found.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numparams">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a the number of parameters contained within the &lt;source&gt;.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paramnotes">
+ <xsd:annotation>
+ <xsd:documentation>Indicates notes pertaining to the parameters in the &lt;source&gt;.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="record">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="recordtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sourcefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original &lt;file&gt; attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="count-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="num-usages">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="repetition">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="total">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a total count.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlineDelimitersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used other elements than &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="bold">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="italic">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="underlined">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="link">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlinePlaceholdersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used with &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="image">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a inline image.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a page break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a line break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mime-typeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="datatypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="asp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="c">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cdf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cfm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cpp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csharp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cstring">
+ <xsd:annotation>
+ <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csv">
+ <xsd:annotation>
+ <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates database data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentfooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filedialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="form">
+ <xsd:annotation>
+ <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="html">
+ <xsd:annotation>
+ <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="htmlbody">
+ <xsd:annotation>
+ <xsd:documentation>Indicates content within an HTML document’s &lt;body&gt; element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ini">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="interleaf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javaclass">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javapropertyresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javalistresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javascript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="jscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="layout">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lisp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="margin">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menufile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="messagefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mif">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mimetype">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="msglib">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pagefooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pageheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="parameters">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pascal">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="php">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="plaintext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="po">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="report">
+ <xsd:annotation>
+ <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resources">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resx">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="svg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vbscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="warning">
+ <xsd:annotation>
+ <xsd:documentation>Indicates warning message.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="winres">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xhtml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xsl">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xul">
+ <xsd:annotation>
+ <xsd:documentation>Indicates XUL elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mtypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="abbrev">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="acronym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="appellation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="collocation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="common-name">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetime">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="equation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="expanded-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="formula">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="head-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="initialism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="international-scientific-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="internationalism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="logical-expression">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="materials-management-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="name">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="near-synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="part-number">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phrase">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phraseological-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="protected">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="romanized-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="seg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="set-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="short-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sku">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="standard-text">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="symbol">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonymous-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="term">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transcribed-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transliterated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="truncated-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="variant">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="restypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="auto3state">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autocheckbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autoradiobutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bitmap">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="button">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="caption">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cell">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the cell in a table, for example the content of the &lt;td&gt; element in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkboxmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkedlistbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="colorchooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="combobox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxexitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="component">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="contextmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a context menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ctext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cursor">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetimepicker">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="defpushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlginit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="edit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="file">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a filename.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filechooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fn">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footnote.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a font name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="footer">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footer.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="frame">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a frame object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="grid">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="groupbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="header">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a header item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="heading">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a heading, such has the content of &lt;h1&gt;, &lt;h2&gt;, etc. in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="icon">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="iedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="keywords">
+ <xsd:annotation>
+ <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="label">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linklabel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="list">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list (a group of list-items, for example an &lt;ol&gt; or &lt;ul&gt; element in HTML).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ltext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menubar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuseparator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="message">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="monthcalendar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a calendar control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numericupdown">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="panel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="popupmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radio">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a radio button object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radiobuttonmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rcdata">
+ <xsd:annotation>
+ <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a row in a table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="scrollpane">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="separator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="shortcut">
+ <xsd:annotation>
+ <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="spinner">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="splitter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="state3">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="statusbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="string">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tabcontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="table">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="textbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="togglebutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="toolbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tooltip">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trackbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tree">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="uri">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="userbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="usercontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="var">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="versioninfo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="window">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a graphical window.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="size-unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="byte">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="char">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="col">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlgunit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="em">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="in">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in inches.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="percent">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pixel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="point">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in point.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="stateValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="final">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the terminating state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="new">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="signed-off">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="translated">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="state-qualifierValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="exact-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fuzzy-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="id-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-glossary">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-inherited">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-mt">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-repository">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-tm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mt-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-grammar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-inaccurate">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-length">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-spelling">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tm-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="word">
+ <xsd:annotation>
+ <xsd:documentation>Refers to words.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="page">
+ <xsd:annotation>
+ <xsd:documentation>Refers to pages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trans-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to &lt;trans-unit&gt; elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bin-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to &lt;bin-unit&gt; elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to glyphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="item">
+ <xsd:annotation>
+ <xsd:documentation>Refers to &lt;trans-unit&gt; and/or &lt;bin-unit&gt; elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="instance">
+ <xsd:annotation>
+ <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="character">
+ <xsd:annotation>
+ <xsd:documentation>Refers to characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="line">
+ <xsd:annotation>
+ <xsd:documentation>Refers to lines.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sentence">
+ <xsd:annotation>
+ <xsd:documentation>Refers to sentences.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paragraph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to paragraphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="segment">
+ <xsd:annotation>
+ <xsd:documentation>Refers to segments.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="placeable">
+ <xsd:annotation>
+ <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="priorityValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:positiveInteger">
+ <xsd:enumeration value="1">
+ <xsd:annotation>
+ <xsd:documentation>Highest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="2">
+ <xsd:annotation>
+ <xsd:documentation>High priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="3">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="4">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="5">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="6">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="7">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="8">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="9">
+ <xsd:annotation>
+ <xsd:documentation>Low priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="10">
+ <xsd:annotation>
+ <xsd:documentation>Lowest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueYesNo">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="yes">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="no">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueList">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:XTend">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="coord">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-x">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-y">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cx">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cy">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-name">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-size">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-weight">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="css-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="purposeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="information">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="location">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="alttranstypeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="proposal">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="previous-version">
+ <xsd:annotation>
+ <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected">
+ <xsd:annotation>
+ <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="reference">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="accepted">
+ <xsd:annotation>
+ <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Other Types -->
+ <xsd:complexType name="ElemType_ExternalReference">
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ </xsd:complexType>
+ <xsd:simpleType name="AttrType_purpose">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_datatype">
+ <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_restype">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_alttranstype">
+ <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_context-type">
+ <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state">
+ <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state-qualifier">
+ <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_count-type">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlineDelimiters">
+ <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlinePlaceholders">
+ <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_size-unit">
+ <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_mtype">
+ <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_unit">
+ <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_priority">
+ <xsd:union memberTypes="xlf:priorityValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_reformat">
+ <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_YesNo">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="yes"/>
+ <xsd:enumeration value="no"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Position">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="open"/>
+ <xsd:enumeration value="close"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_assoc">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="preceding"/>
+ <xsd:enumeration value="following"/>
+ <xsd:enumeration value="both"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_annotates">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="source"/>
+ <xsd:enumeration value="target"/>
+ <xsd:enumeration value="general"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Coordinates">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Version">
+ <xsd:annotation>
+ <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="1.2"/>
+ <xsd:enumeration value="1.1"/>
+ <xsd:enumeration value="1.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Groups -->
+ <xsd:group name="ElemGroup_TextContent">
+ <xsd:choice>
+ <xsd:element ref="xlf:g"/>
+ <xsd:element ref="xlf:bpt"/>
+ <xsd:element ref="xlf:ept"/>
+ <xsd:element ref="xlf:ph"/>
+ <xsd:element ref="xlf:it"/>
+ <xsd:element ref="xlf:mrk"/>
+ <xsd:element ref="xlf:x"/>
+ <xsd:element ref="xlf:bx"/>
+ <xsd:element ref="xlf:ex"/>
+ </xsd:choice>
+ </xsd:group>
+ <xsd:attributeGroup name="AttrGroup_TextContent">
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:attributeGroup>
+ <!-- XLIFF Structure -->
+ <xsd:element name="xliff">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ <xsd:element ref="xlf:file"/>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="file">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:header"/>
+ <xsd:element ref="xlf:body"/>
+ </xsd:sequence>
+ <xsd:attribute name="original" type="xsd:string" use="required"/>
+ <xsd:attribute name="source-language" type="xsd:language" use="required"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute ref="xml:space" use="optional"/>
+ <xsd:attribute name="category" type="xsd:string" use="optional"/>
+ <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
+ <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_group_id">
+ <xsd:selector xpath=".//xlf:group"/>
+ <xsd:field xpath="@id"/>
+ </xsd:unique>
+ <xsd:key name="K_unit_id">
+ <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
+ <xsd:field xpath="@id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
+ <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
+ <xsd:field xpath="@xid"/>
+ </xsd:keyref>
+ <xsd:key name="K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:tool"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="."/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:key name="K_count-group_name">
+ <xsd:selector xpath=".//xlf:count-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:key>
+ <xsd:unique name="U_context-group_name">
+ <xsd:selector xpath=".//xlf:context-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:unique>
+ <xsd:key name="K_phase-name">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:key>
+ <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
+ <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:keyref>
+ <xsd:unique name="U_uid">
+ <xsd:selector xpath=".//xlf:external-file"/>
+ <xsd:field xpath="@uid"/>
+ </xsd:unique>
+ </xsd:element>
+ <xsd:element name="header">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element minOccurs="0" ref="xlf:phase-group"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:tool"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="internal-file">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="form" type="xsd:string"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="external-file">
+ <xsd:complexType>
+ <xsd:attribute name="href" type="xsd:string" use="required"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="note">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
+ <xsd:attribute name="from" type="xsd:string" use="optional"/>
+ <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:phase"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:note"/>
+ </xsd:sequence>
+ <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="process-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:count"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:context"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
+ <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="tool">
+ <xsd:complexType mixed="true">
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="body">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="group">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="trans-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element minOccurs="0" ref="xlf:target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:alt-trans"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="seg-source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="target">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="alt-trans">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element maxOccurs="1" ref="xlf:target"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="origin" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="bin-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:bin-source"/>
+ <xsd:element minOccurs="0" ref="xlf:bin-target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:trans-unit"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-source">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-target">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Element for inline codes -->
+ <xsd:element name="g">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="x">
+ <xsd:complexType>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bx">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ex">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ph">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bpt">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ept">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="it">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="sub">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mrk">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="comment" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+</xsd:schema>
diff --git a/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-2.0.xsd b/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-2.0.xsd
new file mode 100644
index 0000000..963232f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xliff-core-2.0.xsd
@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ XLIFF Version 2.0
+ OASIS Standard
+ 05 August 2014
+ Copyright (c) OASIS Open 2014. All rights reserved.
+ Source: http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/schemas/
+ -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ xmlns:xlf="urn:oasis:names:tc:xliff:document:2.0"
+ targetNamespace="urn:oasis:names:tc:xliff:document:2.0">
+
+ <!-- Import -->
+
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="informativeCopiesOf3rdPartySchemas/w3c/xml.xsd"/>
+
+ <!-- Element Group -->
+
+ <xs:group name="inline">
+ <xs:choice>
+ <xs:element ref="xlf:cp"/>
+ <xs:element ref="xlf:ph"/>
+ <xs:element ref="xlf:pc"/>
+ <xs:element ref="xlf:sc"/>
+ <xs:element ref="xlf:ec"/>
+ <xs:element ref="xlf:mrk"/>
+ <xs:element ref="xlf:sm"/>
+ <xs:element ref="xlf:em"/>
+ </xs:choice>
+ </xs:group>
+
+ <!-- Attribute Types -->
+
+ <xs:simpleType name="yesNo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="yesNoFirstNo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="firstNo"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="dirValue">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="ltr"/>
+ <xs:enumeration value="rtl"/>
+ <xs:enumeration value="auto"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="appliesTo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="source"/>
+ <xs:enumeration value="target"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="userDefinedValue">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[^\s:]+:[^\s:]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="attrType_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="fmt"/>
+ <xs:enumeration value="ui"/>
+ <xs:enumeration value="quote"/>
+ <xs:enumeration value="link"/>
+ <xs:enumeration value="image"/>
+ <xs:enumeration value="other"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="typeForMrkValues">
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="generic"/>
+ <xs:enumeration value="comment"/>
+ <xs:enumeration value="term"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="attrType_typeForMrk">
+ <xs:union memberTypes="xlf:typeForMrkValues xlf:userDefinedValue"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="priorityValue">
+ <xs:restriction base="xs:positiveInteger">
+ <xs:minInclusive value="1"/>
+ <xs:maxInclusive value="10"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="stateType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="initial"/>
+ <xs:enumeration value="translated"/>
+ <xs:enumeration value="reviewed"/>
+ <xs:enumeration value="final"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- Structural Elements -->
+
+ <xs:element name="xliff">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:file"/>
+ </xs:sequence>
+ <xs:attribute name="version" use="required"/>
+ <xs:attribute name="srcLang" use="required"/>
+ <xs:attribute name="trgLang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional" default="default"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="file">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:skeleton"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="xlf:unit"/>
+ <xs:element ref="xlf:group"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="original" use="optional"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="skeleton">
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="href" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="group">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="xlf:unit"/>
+ <xs:element ref="xlf:group"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="unit">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:originalData"/>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="xlf:segment"/>
+ <xs:element ref="xlf:ignorable"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="segment">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="state" use="optional" type="xlf:stateType" default="initial"/>
+ <xs:attribute name="subState" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ignorable">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="notes">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:note"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="note">
+ <xs:complexType mixed="true">
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="appliesTo" use="optional" type="xlf:appliesTo"/>
+ <xs:attribute name="category" use="optional"/>
+ <xs:attribute name="priority" use="optional" type="xlf:priorityValue" default="1"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="originalData">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:data"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="data">
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="xlf:cp"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute ref="xml:space" use="optional" fixed="preserve"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="source">
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute ref="xml:lang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="target">
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute ref="xml:lang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:attribute name="order" use="optional" type="xs:positiveInteger"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Inline Elements -->
+
+ <xs:element name="cp">
+ <!-- Code Point -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="hex" use="required" type="xs:hexBinary"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ph">
+ <!-- Placeholder -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="pc">
+ <!-- Paired Code -->
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dispEnd" use="optional"/>
+ <xs:attribute name="dispStart" use="optional"/>
+ <xs:attribute name="equivEnd" use="optional"/>
+ <xs:attribute name="equivStart" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRefEnd" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRefStart" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlowsEnd" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subFlowsStart" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sc">
+ <!-- Start Code -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ec">
+ <!-- End Code -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
+ <xs:attribute name="startRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="mrk">
+ <!-- Annotation Marker -->
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
+ <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
+ <xs:attribute name="value" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sm">
+ <!-- Start Annotation Marker -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
+ <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
+ <xs:attribute name="value" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="em">
+ <!-- End Annotation Marker -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="startRef" use="required" type="xs:NMTOKEN"/>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git a/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xml.xsd b/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xml.xsd
new file mode 100644
index 0000000..a46162a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Loader/schema/dic/xliff-core/xml.xsd
@@ -0,0 +1,309 @@
+<?xml version='1.0'?>
+<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns ="http://www.w3.org/1999/xhtml"
+ xml:lang="en">
+
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+ <h1>About the XML namespace</h1>
+
+ <div class="bodytext">
+ <p>
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+ </p>
+ <p>
+ See <a href="http://www.w3.org/XML/1998/namespace.html">
+ http://www.w3.org/XML/1998/namespace.html</a> and
+ <a href="http://www.w3.org/TR/REC-xml">
+ http://www.w3.org/TR/REC-xml</a> for information
+ about this namespace.
+ </p>
+
+ <p>
+ Note that local names in this namespace are intended to be
+ defined only by the World Wide Web Consortium or its subgroups.
+ The names currently defined in this namespace are listed below.
+ They should not be used with conflicting semantics by any Working
+ Group, specification, or document instance.
+ </p>
+ <p>
+ See further below in this document for more information about <a
+ href="#usage">how to refer to this schema document from your own
+ XSD schema documents</a> and about <a href="#nsversioning">the
+ namespace-versioning policy governing this schema document</a>.
+ </p>
+ </div>
+ </div>
+
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:attribute name="lang">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>lang (as an attribute name)</h3>
+ <p>
+
+ denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.</p>
+
+ </div>
+ <div>
+ <h4>Notes</h4>
+ <p>
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility.
+ </p>
+ <p>
+
+ See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
+ http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
+ and the IANA language subtag registry at
+ <a href="http://www.iana.org/assignments/language-subtag-registry">
+ http://www.iana.org/assignments/language-subtag-registry</a>
+ for further information.
+ </p>
+ <p>
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:union memberTypes="xs:language">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value=""/>
+
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="space">
+ <xs:annotation>
+ <xs:documentation>
+
+ <div>
+
+ <h3>space (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.</p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
+ <xs:documentation>
+
+ <div>
+
+ <h3>base (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
+ for information about this attribute.
+ </p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="id" type="xs:ID">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>id (as an attribute name)</h3>
+ <p>
+
+ denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
+ for information about this attribute.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ <xs:attribute ref="xml:id"/>
+ </xs:attributeGroup>
+
+ <xs:annotation>
+
+ <xs:documentation>
+ <div>
+
+ <h3>Father (in any context at all)</h3>
+
+ <div class="bodytext">
+ <p>
+ denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+ </p>
+ <blockquote>
+ <p>
+
+ In appreciation for his vision, leadership and
+ dedication the W3C XML Plenary on this 10th day of
+ February, 2000, reserves for Jon Bosak in perpetuity
+ the XML name "xml:Father".
+ </p>
+ </blockquote>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+
+ <div xml:id="usage" id="usage">
+ <h2><a name="usage">About this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ This schema defines attributes and an attribute group suitable
+ for use by schemas wishing to allow <code>xml:base</code>,
+ <code>xml:lang</code>, <code>xml:space</code> or
+ <code>xml:id</code> attributes on elements they define.
+ </p>
+
+ <p>
+ To enable this, such a schema must import this schema for
+ the XML namespace, e.g. as follows:
+ </p>
+ <pre>
+ &lt;schema.. .>
+ .. .
+ &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ </pre>
+ <p>
+ or
+ </p>
+ <pre>
+
+ &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+ </pre>
+ <p>
+ Subsequently, qualified reference to any of the attributes or the
+ group defined below will have the desired effect, e.g.
+ </p>
+ <pre>
+ &lt;type.. .>
+ .. .
+ &lt;attributeGroup ref="xml:specialAttrs"/>
+ </pre>
+ <p>
+ will define a type which will schema-validate an instance element
+ with any of those attributes.
+ </p>
+
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+ <div id="nsversioning" xml:id="nsversioning">
+ <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a>.
+ </p>
+ <p>
+ At the date of issue it can also be found at
+ <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd</a>.
+ </p>
+
+ <p>
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML
+ Schema itself, or with the XML namespace itself. In other words,
+ if the XML Schema or XML namespaces change, the version of this
+ document at <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd
+ </a>
+ will change accordingly; the version at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd
+ </a>
+ will not change.
+ </p>
+ <p>
+
+ Previous dated (and unchanging) versions of this schema
+ document are at:
+ </p>
+ <ul>
+ <li><a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2007/08/xml.xsd">
+ http://www.w3.org/2007/08/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2004/10/xml.xsd">
+
+ http://www.w3.org/2004/10/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2001/03/xml.xsd">
+ http://www.w3.org/2001/03/xml.xsd</a></li>
+ </ul>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+</xs:schema>
diff --git a/public/system/storage/vendor/symfony/translation/LoggingTranslator.php b/public/system/storage/vendor/symfony/translation/LoggingTranslator.php
new file mode 100644
index 0000000..fa5c5cc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/LoggingTranslator.php
@@ -0,0 +1,124 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Psr\Log\LoggerInterface;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
+{
+ /**
+ * @var TranslatorInterface|TranslatorBagInterface
+ */
+ private $translator;
+
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
+ /**
+ * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
+ * @param LoggerInterface $logger
+ */
+ public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
+ {
+ if (!$translator instanceof TranslatorBagInterface) {
+ throw new \InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', get_class($translator)));
+ }
+
+ $this->translator = $translator;
+ $this->logger = $logger;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+ {
+ $trans = $this->translator->trans($id, $parameters, $domain, $locale);
+ $this->log($id, $domain, $locale);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+ {
+ $trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
+ $this->log($id, $domain, $locale);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->translator->setLocale($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->translator->getLocale();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue($locale = null)
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ /**
+ * Passes through all unknown calls onto the translator object.
+ */
+ public function __call($method, $args)
+ {
+ return call_user_func_array(array($this->translator, $method), $args);
+ }
+
+ /**
+ * Logs for missing translations.
+ *
+ * @param string $id
+ * @param string|null $domain
+ * @param string|null $locale
+ */
+ private function log($id, $domain, $locale)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $id = (string) $id;
+ $catalogue = $this->translator->getCatalogue($locale);
+ if ($catalogue->defines($id, $domain)) {
+ return;
+ }
+
+ if ($catalogue->has($id, $domain)) {
+ $this->logger->debug('Translation use fallback catalogue.', array('id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()));
+ } else {
+ $this->logger->warning('Translation not found.', array('id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/MessageCatalogue.php b/public/system/storage/vendor/symfony/translation/MessageCatalogue.php
new file mode 100644
index 0000000..dd354a8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/MessageCatalogue.php
@@ -0,0 +1,270 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+
+/**
+ * MessageCatalogue.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface
+{
+ private $messages = array();
+ private $metadata = array();
+ private $resources = array();
+ private $locale;
+ private $fallbackCatalogue;
+ private $parent;
+
+ /**
+ * Constructor.
+ *
+ * @param string $locale The locale
+ * @param array $messages An array of messages classified by domain
+ */
+ public function __construct($locale, array $messages = array())
+ {
+ $this->locale = $locale;
+ $this->messages = $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDomains()
+ {
+ return array_keys($this->messages);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function all($domain = null)
+ {
+ if (null === $domain) {
+ return $this->messages;
+ }
+
+ return isset($this->messages[$domain]) ? $this->messages[$domain] : array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set($id, $translation, $domain = 'messages')
+ {
+ $this->add(array($id => $translation), $domain);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($id, $domain = 'messages')
+ {
+ if (isset($this->messages[$domain][$id])) {
+ return true;
+ }
+
+ if (null !== $this->fallbackCatalogue) {
+ return $this->fallbackCatalogue->has($id, $domain);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defines($id, $domain = 'messages')
+ {
+ return isset($this->messages[$domain][$id]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($id, $domain = 'messages')
+ {
+ if (isset($this->messages[$domain][$id])) {
+ return $this->messages[$domain][$id];
+ }
+
+ if (null !== $this->fallbackCatalogue) {
+ return $this->fallbackCatalogue->get($id, $domain);
+ }
+
+ return $id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function replace($messages, $domain = 'messages')
+ {
+ $this->messages[$domain] = array();
+
+ $this->add($messages, $domain);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add($messages, $domain = 'messages')
+ {
+ if (!isset($this->messages[$domain])) {
+ $this->messages[$domain] = $messages;
+ } else {
+ $this->messages[$domain] = array_replace($this->messages[$domain], $messages);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addCatalogue(MessageCatalogueInterface $catalogue)
+ {
+ if ($catalogue->getLocale() !== $this->locale) {
+ throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale));
+ }
+
+ foreach ($catalogue->all() as $domain => $messages) {
+ $this->add($messages, $domain);
+ }
+
+ foreach ($catalogue->getResources() as $resource) {
+ $this->addResource($resource);
+ }
+
+ if ($catalogue instanceof MetadataAwareInterface) {
+ $metadata = $catalogue->getMetadata('', '');
+ $this->addMetadata($metadata);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
+ {
+ // detect circular references
+ $c = $catalogue;
+ while ($c = $c->getFallbackCatalogue()) {
+ if ($c->getLocale() === $this->getLocale()) {
+ throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ }
+ }
+
+ $c = $this;
+ do {
+ if ($c->getLocale() === $catalogue->getLocale()) {
+ throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ }
+ } while ($c = $c->parent);
+
+ $catalogue->parent = $this;
+ $this->fallbackCatalogue = $catalogue;
+
+ foreach ($catalogue->getResources() as $resource) {
+ $this->addResource($resource);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFallbackCatalogue()
+ {
+ return $this->fallbackCatalogue;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getResources()
+ {
+ return array_values($this->resources);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addResource(ResourceInterface $resource)
+ {
+ $this->resources[$resource->__toString()] = $resource;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata($key = '', $domain = 'messages')
+ {
+ if ('' == $domain) {
+ return $this->metadata;
+ }
+
+ if (isset($this->metadata[$domain])) {
+ if ('' == $key) {
+ return $this->metadata[$domain];
+ }
+
+ if (isset($this->metadata[$domain][$key])) {
+ return $this->metadata[$domain][$key];
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMetadata($key, $value, $domain = 'messages')
+ {
+ $this->metadata[$domain][$key] = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMetadata($key = '', $domain = 'messages')
+ {
+ if ('' == $domain) {
+ $this->metadata = array();
+ } elseif ('' == $key) {
+ unset($this->metadata[$domain]);
+ } else {
+ unset($this->metadata[$domain][$key]);
+ }
+ }
+
+ /**
+ * Adds current values with the new values.
+ *
+ * @param array $values Values to add
+ */
+ private function addMetadata(array $values)
+ {
+ foreach ($values as $domain => $keys) {
+ foreach ($keys as $key => $value) {
+ $this->setMetadata($key, $value, $domain);
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/MessageCatalogueInterface.php b/public/system/storage/vendor/symfony/translation/MessageCatalogueInterface.php
new file mode 100644
index 0000000..b1b516d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/MessageCatalogueInterface.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+
+/**
+ * MessageCatalogueInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface MessageCatalogueInterface
+{
+ /**
+ * Gets the catalogue locale.
+ *
+ * @return string The locale
+ */
+ public function getLocale();
+
+ /**
+ * Gets the domains.
+ *
+ * @return array An array of domains
+ */
+ public function getDomains();
+
+ /**
+ * Gets the messages within a given domain.
+ *
+ * If $domain is null, it returns all messages.
+ *
+ * @param string $domain The domain name
+ *
+ * @return array An array of messages
+ */
+ public function all($domain = null);
+
+ /**
+ * Sets a message translation.
+ *
+ * @param string $id The message id
+ * @param string $translation The messages translation
+ * @param string $domain The domain name
+ */
+ public function set($id, $translation, $domain = 'messages');
+
+ /**
+ * Checks if a message has a translation.
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return bool true if the message has a translation, false otherwise
+ */
+ public function has($id, $domain = 'messages');
+
+ /**
+ * Checks if a message has a translation (it does not take into account the fallback mechanism).
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return bool true if the message has a translation, false otherwise
+ */
+ public function defines($id, $domain = 'messages');
+
+ /**
+ * Gets a message translation.
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return string The message translation
+ */
+ public function get($id, $domain = 'messages');
+
+ /**
+ * Sets translations for a given domain.
+ *
+ * @param array $messages An array of translations
+ * @param string $domain The domain name
+ */
+ public function replace($messages, $domain = 'messages');
+
+ /**
+ * Adds translations for a given domain.
+ *
+ * @param array $messages An array of translations
+ * @param string $domain The domain name
+ */
+ public function add($messages, $domain = 'messages');
+
+ /**
+ * Merges translations from the given Catalogue into the current one.
+ *
+ * The two catalogues must have the same locale.
+ *
+ * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
+ */
+ public function addCatalogue(MessageCatalogueInterface $catalogue);
+
+ /**
+ * Merges translations from the given Catalogue into the current one
+ * only when the translation does not exist.
+ *
+ * This is used to provide default translations when they do not exist for the current locale.
+ *
+ * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
+ */
+ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue);
+
+ /**
+ * Gets the fallback catalogue.
+ *
+ * @return MessageCatalogueInterface|null A MessageCatalogueInterface instance or null when no fallback has been set
+ */
+ public function getFallbackCatalogue();
+
+ /**
+ * Returns an array of resources loaded to build this collection.
+ *
+ * @return ResourceInterface[] An array of resources
+ */
+ public function getResources();
+
+ /**
+ * Adds a resource for this collection.
+ *
+ * @param ResourceInterface $resource A resource instance
+ */
+ public function addResource(ResourceInterface $resource);
+}
diff --git a/public/system/storage/vendor/symfony/translation/MessageSelector.php b/public/system/storage/vendor/symfony/translation/MessageSelector.php
new file mode 100644
index 0000000..bdbb0f9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/MessageSelector.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * MessageSelector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class MessageSelector
+{
+ /**
+ * Given a message with different plural translations separated by a
+ * pipe (|), this method returns the correct portion of the message based
+ * on the given number, locale and the pluralization rules in the message
+ * itself.
+ *
+ * The message supports two different types of pluralization rules:
+ *
+ * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
+ * indexed: There is one apple|There are %count% apples
+ *
+ * The indexed solution can also contain labels (e.g. one: There is one apple).
+ * This is purely for making the translations more clear - it does not
+ * affect the functionality.
+ *
+ * The two methods can also be mixed:
+ * {0} There are no apples|one: There is one apple|more: There are %count% apples
+ *
+ * @param string $message The message being translated
+ * @param int $number The number of items represented for the message
+ * @param string $locale The locale to use for choosing
+ *
+ * @return string
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function choose($message, $number, $locale)
+ {
+ $parts = explode('|', $message);
+ $explicitRules = array();
+ $standardRules = array();
+ foreach ($parts as $part) {
+ $part = trim($part);
+
+ if (preg_match('/^(?P<interval>'.Interval::getIntervalRegexp().')\s*(?P<message>.*?)$/xs', $part, $matches)) {
+ $explicitRules[$matches['interval']] = $matches['message'];
+ } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
+ $standardRules[] = $matches[1];
+ } else {
+ $standardRules[] = $part;
+ }
+ }
+
+ // try to match an explicit rule, then fallback to the standard ones
+ foreach ($explicitRules as $interval => $m) {
+ if (Interval::test($number, $interval)) {
+ return $m;
+ }
+ }
+
+ $position = PluralizationRules::get($number, $locale);
+
+ if (!isset($standardRules[$position])) {
+ // when there's exactly one rule given, and that rule is a standard
+ // rule, use this rule
+ if (1 === count($parts) && isset($standardRules[0])) {
+ return $standardRules[0];
+ }
+
+ throw new \InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale, $number));
+ }
+
+ return $standardRules[$position];
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/MetadataAwareInterface.php b/public/system/storage/vendor/symfony/translation/MetadataAwareInterface.php
new file mode 100644
index 0000000..e93c6fb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/MetadataAwareInterface.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * MetadataAwareInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface MetadataAwareInterface
+{
+ /**
+ * Gets metadata for the given domain and key.
+ *
+ * Passing an empty domain will return an array with all metadata indexed by
+ * domain and then by key. Passing an empty key will return an array with all
+ * metadata for the given domain.
+ *
+ * @param string $key The key
+ * @param string $domain The domain name
+ *
+ * @return mixed The value that was set or an array with the domains/keys or null
+ */
+ public function getMetadata($key = '', $domain = 'messages');
+
+ /**
+ * Adds metadata to a message domain.
+ *
+ * @param string $key The key
+ * @param mixed $value The value
+ * @param string $domain The domain name
+ */
+ public function setMetadata($key, $value, $domain = 'messages');
+
+ /**
+ * Deletes metadata for the given key and domain.
+ *
+ * Passing an empty domain will delete all metadata. Passing an empty key will
+ * delete all metadata for the given domain.
+ *
+ * @param string $key The key
+ * @param string $domain The domain name
+ */
+ public function deleteMetadata($key = '', $domain = 'messages');
+}
diff --git a/public/system/storage/vendor/symfony/translation/PluralizationRules.php b/public/system/storage/vendor/symfony/translation/PluralizationRules.php
new file mode 100644
index 0000000..ef2be70
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/PluralizationRules.php
@@ -0,0 +1,209 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * Returns the plural rules for a given locale.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class PluralizationRules
+{
+ private static $rules = array();
+
+ /**
+ * Returns the plural position to use for the given locale and number.
+ *
+ * @param int $number The number
+ * @param string $locale The locale
+ *
+ * @return int The plural position
+ */
+ public static function get($number, $locale)
+ {
+ if ('pt_BR' === $locale) {
+ // temporary set a locale for brazilian
+ $locale = 'xbr';
+ }
+
+ if (strlen($locale) > 3) {
+ $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
+ }
+
+ if (isset(self::$rules[$locale])) {
+ $return = call_user_func(self::$rules[$locale], $number);
+
+ if (!is_int($return) || $return < 0) {
+ return 0;
+ }
+
+ return $return;
+ }
+
+ /*
+ * The plural rules are derived from code of the Zend Framework (2010-09-25),
+ * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
+ * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ */
+ switch ($locale) {
+ case 'az':
+ case 'bo':
+ case 'dz':
+ case 'id':
+ case 'ja':
+ case 'jv':
+ case 'ka':
+ case 'km':
+ case 'kn':
+ case 'ko':
+ case 'ms':
+ case 'th':
+ case 'tr':
+ case 'vi':
+ case 'zh':
+ return 0;
+ break;
+
+ case 'af':
+ case 'bn':
+ case 'bg':
+ case 'ca':
+ case 'da':
+ case 'de':
+ case 'el':
+ case 'en':
+ case 'eo':
+ case 'es':
+ case 'et':
+ case 'eu':
+ case 'fa':
+ case 'fi':
+ case 'fo':
+ case 'fur':
+ case 'fy':
+ case 'gl':
+ case 'gu':
+ case 'ha':
+ case 'he':
+ case 'hu':
+ case 'is':
+ case 'it':
+ case 'ku':
+ case 'lb':
+ case 'ml':
+ case 'mn':
+ case 'mr':
+ case 'nah':
+ case 'nb':
+ case 'ne':
+ case 'nl':
+ case 'nn':
+ case 'no':
+ case 'om':
+ case 'or':
+ case 'pa':
+ case 'pap':
+ case 'ps':
+ case 'pt':
+ case 'so':
+ case 'sq':
+ case 'sv':
+ case 'sw':
+ case 'ta':
+ case 'te':
+ case 'tk':
+ case 'ur':
+ case 'zu':
+ return ($number == 1) ? 0 : 1;
+
+ case 'am':
+ case 'bh':
+ case 'fil':
+ case 'fr':
+ case 'gun':
+ case 'hi':
+ case 'hy':
+ case 'ln':
+ case 'mg':
+ case 'nso':
+ case 'xbr':
+ case 'ti':
+ case 'wa':
+ return (($number == 0) || ($number == 1)) ? 0 : 1;
+
+ case 'be':
+ case 'bs':
+ case 'hr':
+ case 'ru':
+ case 'sr':
+ case 'uk':
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+
+ case 'cs':
+ case 'sk':
+ return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
+
+ case 'ga':
+ return ($number == 1) ? 0 : (($number == 2) ? 1 : 2);
+
+ case 'lt':
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+
+ case 'sl':
+ return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3));
+
+ case 'mk':
+ return ($number % 10 == 1) ? 0 : 1;
+
+ case 'mt':
+ return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
+
+ case 'lv':
+ return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2);
+
+ case 'pl':
+ return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
+
+ case 'cy':
+ return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3));
+
+ case 'ro':
+ return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
+
+ case 'ar':
+ return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
+
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * Overrides the default plural rule for a given locale.
+ *
+ * @param callable $rule A PHP callable
+ * @param string $locale The locale
+ */
+ public static function set(callable $rule, $locale)
+ {
+ if ('pt_BR' === $locale) {
+ // temporary set a locale for brazilian
+ $locale = 'xbr';
+ }
+
+ if (strlen($locale) > 3) {
+ $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
+ }
+
+ self::$rules[$locale] = $rule;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/README.md b/public/system/storage/vendor/symfony/translation/README.md
new file mode 100644
index 0000000..46f3d1f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/README.md
@@ -0,0 +1,13 @@
+Translation Component
+=====================
+
+The Translation component provides tools to internationalize your application.
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/translation/index.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php b/public/system/storage/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php
new file mode 100644
index 0000000..30c21af
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+abstract class AbstractOperationTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetEmptyDomains()
+ {
+ $this->assertEquals(
+ array(),
+ $this->createOperation(
+ new MessageCatalogue('en'),
+ new MessageCatalogue('en')
+ )->getDomains()
+ );
+ }
+
+ public function testGetMergedDomains()
+ {
+ $this->assertEquals(
+ array('a', 'b', 'c'),
+ $this->createOperation(
+ new MessageCatalogue('en', array('a' => array(), 'b' => array())),
+ new MessageCatalogue('en', array('b' => array(), 'c' => array()))
+ )->getDomains()
+ );
+ }
+
+ public function testGetMessagesFromUnknownDomain()
+ {
+ $this->setExpectedException('InvalidArgumentException');
+ $this->createOperation(
+ new MessageCatalogue('en'),
+ new MessageCatalogue('en')
+ )->getMessages('domain');
+ }
+
+ public function testGetEmptyMessages()
+ {
+ $this->assertEquals(
+ array(),
+ $this->createOperation(
+ new MessageCatalogue('en', array('a' => array())),
+ new MessageCatalogue('en')
+ )->getMessages('a')
+ );
+ }
+
+ public function testGetEmptyResult()
+ {
+ $this->assertEquals(
+ new MessageCatalogue('en'),
+ $this->createOperation(
+ new MessageCatalogue('en'),
+ new MessageCatalogue('en')
+ )->getResult()
+ );
+ }
+
+ abstract protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target);
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php b/public/system/storage/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php
new file mode 100644
index 0000000..8b51c15
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Catalogue;
+
+use Symfony\Component\Translation\Catalogue\MergeOperation;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+class MergeOperationTest extends AbstractOperationTest
+{
+ public function testGetMessagesFromSingleDomain()
+ {
+ $operation = $this->createOperation(
+ new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
+ new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
+ );
+
+ $this->assertEquals(
+ array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c'),
+ $operation->getMessages('messages')
+ );
+
+ $this->assertEquals(
+ array('c' => 'new_c'),
+ $operation->getNewMessages('messages')
+ );
+
+ $this->assertEquals(
+ array(),
+ $operation->getObsoleteMessages('messages')
+ );
+ }
+
+ public function testGetResultFromSingleDomain()
+ {
+ $this->assertEquals(
+ new MessageCatalogue('en', array(
+ 'messages' => array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c'),
+ )),
+ $this->createOperation(
+ new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
+ new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
+ )->getResult()
+ );
+ }
+
+ public function testGetResultWithMetadata()
+ {
+ $leftCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b')));
+ $leftCatalogue->setMetadata('a', 'foo', 'messages');
+ $leftCatalogue->setMetadata('b', 'bar', 'messages');
+ $rightCatalogue = new MessageCatalogue('en', array('messages' => array('b' => 'new_b', 'c' => 'new_c')));
+ $rightCatalogue->setMetadata('b', 'baz', 'messages');
+ $rightCatalogue->setMetadata('c', 'qux', 'messages');
+
+ $mergedCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c')));
+ $mergedCatalogue->setMetadata('a', 'foo', 'messages');
+ $mergedCatalogue->setMetadata('b', 'bar', 'messages');
+ $mergedCatalogue->setMetadata('c', 'qux', 'messages');
+
+ $this->assertEquals(
+ $mergedCatalogue,
+ $this->createOperation(
+ $leftCatalogue,
+ $rightCatalogue
+ )->getResult()
+ );
+ }
+
+ protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
+ {
+ return new MergeOperation($source, $target);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php b/public/system/storage/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php
new file mode 100644
index 0000000..271d17f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Catalogue;
+
+use Symfony\Component\Translation\Catalogue\TargetOperation;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+class TargetOperationTest extends AbstractOperationTest
+{
+ public function testGetMessagesFromSingleDomain()
+ {
+ $operation = $this->createOperation(
+ new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
+ new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
+ );
+
+ $this->assertEquals(
+ array('a' => 'old_a', 'c' => 'new_c'),
+ $operation->getMessages('messages')
+ );
+
+ $this->assertEquals(
+ array('c' => 'new_c'),
+ $operation->getNewMessages('messages')
+ );
+
+ $this->assertEquals(
+ array('b' => 'old_b'),
+ $operation->getObsoleteMessages('messages')
+ );
+ }
+
+ public function testGetResultFromSingleDomain()
+ {
+ $this->assertEquals(
+ new MessageCatalogue('en', array(
+ 'messages' => array('a' => 'old_a', 'c' => 'new_c'),
+ )),
+ $this->createOperation(
+ new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
+ new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
+ )->getResult()
+ );
+ }
+
+ public function testGetResultWithMetadata()
+ {
+ $leftCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b')));
+ $leftCatalogue->setMetadata('a', 'foo', 'messages');
+ $leftCatalogue->setMetadata('b', 'bar', 'messages');
+ $rightCatalogue = new MessageCatalogue('en', array('messages' => array('b' => 'new_b', 'c' => 'new_c')));
+ $rightCatalogue->setMetadata('b', 'baz', 'messages');
+ $rightCatalogue->setMetadata('c', 'qux', 'messages');
+
+ $diffCatalogue = new MessageCatalogue('en', array('messages' => array('b' => 'old_b', 'c' => 'new_c')));
+ $diffCatalogue->setMetadata('b', 'bar', 'messages');
+ $diffCatalogue->setMetadata('c', 'qux', 'messages');
+
+ $this->assertEquals(
+ $diffCatalogue,
+ $this->createOperation(
+ $leftCatalogue,
+ $rightCatalogue
+ )->getResult()
+ );
+ }
+
+ protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
+ {
+ return new TargetOperation($source, $target);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php b/public/system/storage/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php
new file mode 100644
index 0000000..3d1e86e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php
@@ -0,0 +1,148 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\DataCollector;
+
+use Symfony\Component\Translation\DataCollectorTranslator;
+use Symfony\Component\Translation\DataCollector\TranslationDataCollector;
+
+class TranslationDataCollectorTest extends \PHPUnit_Framework_TestCase
+{
+ protected function setUp()
+ {
+ if (!class_exists('Symfony\Component\HttpKernel\DataCollector\DataCollector')) {
+ $this->markTestSkipped('The "DataCollector" is not available');
+ }
+ }
+
+ public function testCollectEmptyMessages()
+ {
+ $translator = $this->getTranslator();
+ $translator->expects($this->any())->method('getCollectedMessages')->will($this->returnValue(array()));
+
+ $dataCollector = new TranslationDataCollector($translator);
+ $dataCollector->lateCollect();
+
+ $this->assertEquals(0, $dataCollector->getCountMissings());
+ $this->assertEquals(0, $dataCollector->getCountFallbacks());
+ $this->assertEquals(0, $dataCollector->getCountDefines());
+ $this->assertEquals(array(), $dataCollector->getMessages());
+ }
+
+ public function testCollect()
+ {
+ $collectedMessages = array(
+ array(
+ 'id' => 'foo',
+ 'translation' => 'foo (en)',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_DEFINED,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ ),
+ array(
+ 'id' => 'bar',
+ 'translation' => 'bar (fr)',
+ 'locale' => 'fr',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ ),
+ array(
+ 'id' => 'choice',
+ 'translation' => 'choice',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_MISSING,
+ 'parameters' => array('%count%' => 3),
+ 'transChoiceNumber' => 3,
+ ),
+ array(
+ 'id' => 'choice',
+ 'translation' => 'choice',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_MISSING,
+ 'parameters' => array('%count%' => 3),
+ 'transChoiceNumber' => 3,
+ ),
+ array(
+ 'id' => 'choice',
+ 'translation' => 'choice',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_MISSING,
+ 'parameters' => array('%count%' => 4, '%foo%' => 'bar'),
+ 'transChoiceNumber' => 4,
+ ),
+ );
+ $expectedMessages = array(
+ array(
+ 'id' => 'foo',
+ 'translation' => 'foo (en)',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_DEFINED,
+ 'count' => 1,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ ),
+ array(
+ 'id' => 'bar',
+ 'translation' => 'bar (fr)',
+ 'locale' => 'fr',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
+ 'count' => 1,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ ),
+ array(
+ 'id' => 'choice',
+ 'translation' => 'choice',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_MISSING,
+ 'count' => 3,
+ 'parameters' => array(
+ array('%count%' => 3),
+ array('%count%' => 3),
+ array('%count%' => 4, '%foo%' => 'bar'),
+ ),
+ 'transChoiceNumber' => 3,
+ ),
+ );
+
+ $translator = $this->getTranslator();
+ $translator->expects($this->any())->method('getCollectedMessages')->will($this->returnValue($collectedMessages));
+
+ $dataCollector = new TranslationDataCollector($translator);
+ $dataCollector->lateCollect();
+
+ $this->assertEquals(1, $dataCollector->getCountMissings());
+ $this->assertEquals(1, $dataCollector->getCountFallbacks());
+ $this->assertEquals(1, $dataCollector->getCountDefines());
+ $this->assertEquals($expectedMessages, array_values($dataCollector->getMessages()));
+ }
+
+ private function getTranslator()
+ {
+ $translator = $this
+ ->getMockBuilder('Symfony\Component\Translation\DataCollectorTranslator')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ return $translator;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php b/public/system/storage/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php
new file mode 100644
index 0000000..5ef8171
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\DataCollectorTranslator;
+use Symfony\Component\Translation\Loader\ArrayLoader;
+
+class DataCollectorTranslatorTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCollectMessages()
+ {
+ $collector = $this->createCollector();
+ $collector->setFallbackLocales(array('fr', 'ru'));
+
+ $collector->trans('foo');
+ $collector->trans('bar');
+ $collector->transChoice('choice', 0);
+ $collector->trans('bar_ru');
+ $collector->trans('bar_ru', array('foo' => 'bar'));
+
+ $expectedMessages = array();
+ $expectedMessages[] = array(
+ 'id' => 'foo',
+ 'translation' => 'foo (en)',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_DEFINED,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ );
+ $expectedMessages[] = array(
+ 'id' => 'bar',
+ 'translation' => 'bar (fr)',
+ 'locale' => 'fr',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ );
+ $expectedMessages[] = array(
+ 'id' => 'choice',
+ 'translation' => 'choice',
+ 'locale' => 'en',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_MISSING,
+ 'parameters' => array(),
+ 'transChoiceNumber' => 0,
+ );
+ $expectedMessages[] = array(
+ 'id' => 'bar_ru',
+ 'translation' => 'bar (ru)',
+ 'locale' => 'ru',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
+ 'parameters' => array(),
+ 'transChoiceNumber' => null,
+ );
+ $expectedMessages[] = array(
+ 'id' => 'bar_ru',
+ 'translation' => 'bar (ru)',
+ 'locale' => 'ru',
+ 'domain' => 'messages',
+ 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK,
+ 'parameters' => array('foo' => 'bar'),
+ 'transChoiceNumber' => null,
+ );
+
+ $this->assertEquals($expectedMessages, $collector->getCollectedMessages());
+ }
+
+ private function createCollector()
+ {
+ $translator = new Translator('en');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (en)'), 'en');
+ $translator->addResource('array', array('bar' => 'bar (fr)'), 'fr');
+ $translator->addResource('array', array('bar_ru' => 'bar (ru)'), 'ru');
+
+ $collector = new DataCollectorTranslator($translator);
+
+ return $collector;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php
new file mode 100644
index 0000000..9613192
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\CsvFileDumper;
+
+class CsvFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar', 'bar' => 'foo
+foo', 'foo;foo' => 'bar'));
+
+ $dumper = new CsvFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/valid.csv', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php
new file mode 100644
index 0000000..ed58546
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\FileDumper;
+
+class FileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDump()
+ {
+ $tempDir = sys_get_temp_dir();
+
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new ConcreteFileDumper();
+ $dumper->dump($catalogue, array('path' => $tempDir));
+
+ $this->assertTrue(file_exists($tempDir.'/messages.en.concrete'));
+ }
+
+ public function testDumpBackupsFileIfExisting()
+ {
+ $tempDir = sys_get_temp_dir();
+ $file = $tempDir.'/messages.en.concrete';
+ $backupFile = $file.'~';
+
+ @touch($file);
+
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new ConcreteFileDumper();
+ $dumper->dump($catalogue, array('path' => $tempDir));
+
+ $this->assertTrue(file_exists($backupFile));
+
+ @unlink($file);
+ @unlink($backupFile);
+ }
+
+ public function testDumpCreatesNestedDirectoriesAndFile()
+ {
+ $tempDir = sys_get_temp_dir();
+ $translationsDir = $tempDir.'/test/translations';
+ $file = $translationsDir.'/messages.en.concrete';
+
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new ConcreteFileDumper();
+ $dumper->setRelativePathTemplate('test/translations/%domain%.%locale%.%extension%');
+ $dumper->dump($catalogue, array('path' => $tempDir));
+
+ $this->assertTrue(file_exists($file));
+
+ @unlink($file);
+ @rmdir($translationsDir);
+ }
+}
+
+class ConcreteFileDumper extends FileDumper
+{
+ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
+ {
+ return '';
+ }
+
+ protected function getExtension()
+ {
+ return 'concrete';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php
new file mode 100644
index 0000000..618783c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\IcuResFileDumper;
+
+class IcuResFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new IcuResFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resourcebundle/res/en.res', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php
new file mode 100644
index 0000000..d8ae4b5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\IniFileDumper;
+
+class IniFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new IniFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.ini', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php
new file mode 100644
index 0000000..27e9f4d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\JsonFileDumper;
+
+class JsonFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new JsonFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.json', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+
+ public function testDumpWithCustomEncoding()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => '"bar"'));
+
+ $dumper = new JsonFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.dump.json', $dumper->formatCatalogue($catalogue, 'messages', array('json_encoding' => JSON_HEX_QUOT)));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php
new file mode 100644
index 0000000..c47656c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\MoFileDumper;
+
+class MoFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new MoFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.mo', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php
new file mode 100644
index 0000000..d24cd2b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\PhpFileDumper;
+
+class PhpFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new PhpFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.php', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php
new file mode 100644
index 0000000..445961a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\PoFileDumper;
+
+class PoFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new PoFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.po', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php
new file mode 100644
index 0000000..690a4d0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\QtFileDumper;
+
+class QtFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(array('foo' => 'bar'), 'resources');
+
+ $dumper = new QtFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.ts', $dumper->formatCatalogue($catalogue, 'resources'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php
new file mode 100644
index 0000000..072b605
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\XliffFileDumper;
+
+class XliffFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en_US');
+ $catalogue->add(array(
+ 'foo' => 'bar',
+ 'key' => '',
+ 'key.with.cdata' => '<source> & <target>',
+ ));
+ $catalogue->setMetadata('foo', array('notes' => array(array('priority' => 1, 'from' => 'bar', 'content' => 'baz'))));
+ $catalogue->setMetadata('key', array('notes' => array(array('content' => 'baz'), array('content' => 'qux'))));
+
+ $dumper = new XliffFileDumper();
+
+ $this->assertStringEqualsFile(
+ __DIR__.'/../fixtures/resources-clean.xlf',
+ $dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR'))
+ );
+ }
+
+ public function testFormatCatalogueXliff2()
+ {
+ $catalogue = new MessageCatalogue('en_US');
+ $catalogue->add(array(
+ 'foo' => 'bar',
+ 'key' => '',
+ 'key.with.cdata' => '<source> & <target>',
+ ));
+ $catalogue->setMetadata('key', array('target-attributes' => array('order' => 1)));
+
+ $dumper = new XliffFileDumper();
+
+ $this->assertStringEqualsFile(
+ __DIR__.'/../fixtures/resources-2.0-clean.xlf',
+ $dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR', 'xliff_version' => '2.0'))
+ );
+ }
+
+ public function testFormatCatalogueWithCustomToolInfo()
+ {
+ $options = array(
+ 'default_locale' => 'en_US',
+ 'tool_info' => array('tool-id' => 'foo', 'tool-name' => 'foo', 'tool-version' => '0.0', 'tool-company' => 'Foo'),
+ );
+
+ $catalogue = new MessageCatalogue('en_US');
+ $catalogue->add(array('foo' => 'bar'));
+
+ $dumper = new XliffFileDumper();
+
+ $this->assertStringEqualsFile(
+ __DIR__.'/../fixtures/resources-tool-info.xlf',
+ $dumper->formatCatalogue($catalogue, 'messages', $options)
+ );
+ }
+
+ public function testFormatCatalogueWithTargetAttributesMetadata()
+ {
+ $catalogue = new MessageCatalogue('en_US');
+ $catalogue->add(array(
+ 'foo' => 'bar',
+ ));
+ $catalogue->setMetadata('foo', array('target-attributes' => array('state' => 'needs-translation')));
+
+ $dumper = new XliffFileDumper();
+
+ $this->assertStringEqualsFile(
+ __DIR__.'/../fixtures/resources-target-attributes.xlf',
+ $dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR'))
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php b/public/system/storage/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php
new file mode 100644
index 0000000..d6bb477
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\YamlFileDumper;
+
+class YamlFileDumperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testTreeFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(
+ array(
+ 'foo.bar1' => 'value1',
+ 'foo.bar2' => 'value2',
+ ));
+
+ $dumper = new YamlFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/messages.yml', $dumper->formatCatalogue($catalogue, 'messages', array('as_tree' => true, 'inline' => 999)));
+ }
+
+ public function testLinearFormatCatalogue()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->add(
+ array(
+ 'foo.bar1' => 'value1',
+ 'foo.bar2' => 'value2',
+ ));
+
+ $dumper = new YamlFileDumper();
+
+ $this->assertStringEqualsFile(__DIR__.'/../fixtures/messages_linear.yml', $dumper->formatCatalogue($catalogue, 'messages'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/IdentityTranslatorTest.php b/public/system/storage/vendor/symfony/translation/Tests/IdentityTranslatorTest.php
new file mode 100644
index 0000000..352dd31
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/IdentityTranslatorTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Intl\Util\IntlTestHelper;
+use Symfony\Component\Translation\IdentityTranslator;
+
+class IdentityTranslatorTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getTransTests
+ */
+ public function testTrans($expected, $id, $parameters)
+ {
+ $translator = new IdentityTranslator();
+
+ $this->assertEquals($expected, $translator->trans($id, $parameters));
+ }
+
+ /**
+ * @dataProvider getTransChoiceTests
+ */
+ public function testTransChoiceWithExplicitLocale($expected, $id, $number, $parameters)
+ {
+ $translator = new IdentityTranslator();
+ $translator->setLocale('en');
+
+ $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
+ }
+
+ /**
+ * @dataProvider getTransChoiceTests
+ */
+ public function testTransChoiceWithDefaultLocale($expected, $id, $number, $parameters)
+ {
+ \Locale::setDefault('en');
+
+ $translator = new IdentityTranslator();
+
+ $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
+ }
+
+ public function testGetSetLocale()
+ {
+ $translator = new IdentityTranslator();
+ $translator->setLocale('en');
+
+ $this->assertEquals('en', $translator->getLocale());
+ }
+
+ public function testGetLocaleReturnsDefaultLocaleIfNotSet()
+ {
+ // in order to test with "pt_BR"
+ IntlTestHelper::requireFullIntl($this);
+
+ $translator = new IdentityTranslator();
+
+ \Locale::setDefault('en');
+ $this->assertEquals('en', $translator->getLocale());
+
+ \Locale::setDefault('pt_BR');
+ $this->assertEquals('pt_BR', $translator->getLocale());
+ }
+
+ public function getTransTests()
+ {
+ return array(
+ array('Symfony is great!', 'Symfony is great!', array()),
+ array('Symfony is awesome!', 'Symfony is %what%!', array('%what%' => 'awesome')),
+ );
+ }
+
+ public function getTransChoiceTests()
+ {
+ return array(
+ array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0, array('%count%' => 0)),
+ array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1, array('%count%' => 1)),
+ array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10, array('%count%' => 10)),
+ array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0, array('%count%' => 0)),
+ array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1, array('%count%' => 1)),
+ array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10, array('%count%' => 10)),
+ // custom validation messages may be coded with a fixed value
+ array('There are 2 apples', 'There are 2 apples', 2, array('%count%' => 2)),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/IntervalTest.php b/public/system/storage/vendor/symfony/translation/Tests/IntervalTest.php
new file mode 100644
index 0000000..075c98b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/IntervalTest.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\Interval;
+
+class IntervalTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getTests
+ */
+ public function testTest($expected, $number, $interval)
+ {
+ $this->assertEquals($expected, Interval::test($number, $interval));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testTestException()
+ {
+ Interval::test(1, 'foobar');
+ }
+
+ public function getTests()
+ {
+ return array(
+ array(true, 3, '{1,2, 3 ,4}'),
+ array(false, 10, '{1,2, 3 ,4}'),
+ array(false, 3, '[1,2]'),
+ array(true, 1, '[1,2]'),
+ array(true, 2, '[1,2]'),
+ array(false, 1, ']1,2['),
+ array(false, 2, ']1,2['),
+ array(true, log(0), '[-Inf,2['),
+ array(true, -log(0), '[-2,+Inf]'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php
new file mode 100644
index 0000000..463d3b5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\CsvFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class CsvFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new CsvFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.csv';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadDoesNothingIfEmpty()
+ {
+ $loader = new CsvFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.csv';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array(), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new CsvFileLoader();
+ $resource = __DIR__.'/../fixtures/not-exists.csv';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadNonLocalResource()
+ {
+ $loader = new CsvFileLoader();
+ $resource = 'http://example.com/resources.csv';
+ $loader->load($resource, 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php
new file mode 100644
index 0000000..888fb61
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\IcuDatFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+/**
+ * @requires extension intl
+ */
+class IcuDatFileLoaderTest extends LocalizedTestCase
+{
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadInvalidResource()
+ {
+ $loader = new IcuDatFileLoader();
+ $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted/resources', 'es', 'domain2');
+ }
+
+ public function testDatEnglishLoad()
+ {
+ // bundled resource is build using pkgdata command which at least in ICU 4.2 comes in extremely! buggy form
+ // you must specify an temporary build directory which is not the same as current directory and
+ // MUST reside on the same partition. pkgdata -p resources -T /srv -d.packagelist.txt
+ $loader = new IcuDatFileLoader();
+ $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('symfony' => 'Symfony 2 is great'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource.'.dat')), $catalogue->getResources());
+ }
+
+ public function testDatFrenchLoad()
+ {
+ $loader = new IcuDatFileLoader();
+ $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources';
+ $catalogue = $loader->load($resource, 'fr', 'domain1');
+
+ $this->assertEquals(array('symfony' => 'Symfony 2 est génial'), $catalogue->all('domain1'));
+ $this->assertEquals('fr', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource.'.dat')), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new IcuDatFileLoader();
+ $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php
new file mode 100644
index 0000000..8d9ed19
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\IcuResFileLoader;
+use Symfony\Component\Config\Resource\DirectoryResource;
+
+/**
+ * @requires extension intl
+ */
+class IcuResFileLoaderTest extends LocalizedTestCase
+{
+ public function testLoad()
+ {
+ // resource is build using genrb command
+ $loader = new IcuResFileLoader();
+ $resource = __DIR__.'/../fixtures/resourcebundle/res';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new DirectoryResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new IcuResFileLoader();
+ $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadInvalidResource()
+ {
+ $loader = new IcuResFileLoader();
+ $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted', 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php
new file mode 100644
index 0000000..1a5de0e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\IniFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class IniFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new IniFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.ini';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadDoesNothingIfEmpty()
+ {
+ $loader = new IniFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.ini';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array(), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new IniFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.ini';
+ $loader->load($resource, 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php
new file mode 100644
index 0000000..cd5d633
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\JsonFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class JsonFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new JsonFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.json';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadDoesNothingIfEmpty()
+ {
+ $loader = new JsonFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.json';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array(), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new JsonFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.json';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ * @expectedExceptionMessage Error parsing JSON - Syntax error, malformed JSON
+ */
+ public function testParseException()
+ {
+ $loader = new JsonFileLoader();
+ $resource = __DIR__.'/../fixtures/malformed.json';
+ $loader->load($resource, 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php
new file mode 100644
index 0000000..0d1fff7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+abstract class LocalizedTestCase extends \PHPUnit_Framework_TestCase
+{
+ protected function setUp()
+ {
+ if (!extension_loaded('intl')) {
+ $this->markTestSkipped('Extension intl is required.');
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php
new file mode 100644
index 0000000..34078d0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\MoFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class MoFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new MoFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.mo';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadPlurals()
+ {
+ $loader = new MoFileLoader();
+ $resource = __DIR__.'/../fixtures/plurals.mo';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar', 'foos' => '{0} bar|{1} bars'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new MoFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.mo';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadInvalidResource()
+ {
+ $loader = new MoFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.mo';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ public function testLoadEmptyTranslation()
+ {
+ $loader = new MoFileLoader();
+ $resource = __DIR__.'/../fixtures/empty-translation.mo';
+ $catalogue = $loader->load($resource, 'en', 'message');
+
+ $this->assertEquals(array(), $catalogue->all('message'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php
new file mode 100644
index 0000000..0816b0f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\PhpFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new PhpFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.php';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new PhpFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.php';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadThrowsAnExceptionIfFileNotLocal()
+ {
+ $loader = new PhpFileLoader();
+ $resource = 'http://example.com/resources.php';
+ $loader->load($resource, 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php
new file mode 100644
index 0000000..5d340c7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\PoFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class PoFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadPlurals()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/plurals.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar', 'foos' => 'bar|bars'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadDoesNothingIfEmpty()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array(), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.po';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ public function testLoadEmptyTranslation()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/empty-translation.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => ''), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testEscapedId()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/escaped-id.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $messages = $catalogue->all('domain1');
+ $this->assertArrayHasKey('escaped "foo"', $messages);
+ $this->assertEquals('escaped "bar"', $messages['escaped "foo"']);
+ }
+
+ public function testEscapedIdPlurals()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/escaped-id-plurals.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $messages = $catalogue->all('domain1');
+ $this->assertArrayHasKey('escaped "foo"', $messages);
+ $this->assertArrayHasKey('escaped "foos"', $messages);
+ $this->assertEquals('escaped "bar"', $messages['escaped "foo"']);
+ $this->assertEquals('escaped "bar"|escaped "bars"', $messages['escaped "foos"']);
+ }
+
+ public function testSkipFuzzyTranslations()
+ {
+ $loader = new PoFileLoader();
+ $resource = __DIR__.'/../fixtures/fuzzy-translations.po';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $messages = $catalogue->all('domain1');
+ $this->assertArrayHasKey('foo1', $messages);
+ $this->assertArrayNotHasKey('foo2', $messages);
+ $this->assertArrayHasKey('foo3', $messages);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php
new file mode 100644
index 0000000..3aca86a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\QtFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class QtFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new QtFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.ts';
+ $catalogue = $loader->load($resource, 'en', 'resources');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('resources'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new QtFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.ts';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadNonLocalResource()
+ {
+ $loader = new QtFileLoader();
+ $resource = 'http://domain1.com/resources.ts';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadInvalidResource()
+ {
+ $loader = new QtFileLoader();
+ $resource = __DIR__.'/../fixtures/invalid-xml-resources.xlf';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ public function testLoadEmptyResource()
+ {
+ $loader = new QtFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.xlf';
+ $this->setExpectedException('Symfony\Component\Translation\Exception\InvalidResourceException', sprintf('Unable to load "%s".', $resource));
+ $loader->load($resource, 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php
new file mode 100644
index 0000000..2f466d8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php
@@ -0,0 +1,183 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\XliffFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class XliffFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.xlf';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ $this->assertSame(array(), libxml_get_errors());
+ $this->assertContainsOnly('string', $catalogue->all('domain1'));
+ }
+
+ public function testLoadWithInternalErrorsEnabled()
+ {
+ $internalErrors = libxml_use_internal_errors(true);
+
+ $this->assertSame(array(), libxml_get_errors());
+
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.xlf';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ $this->assertSame(array(), libxml_get_errors());
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+ }
+
+ public function testLoadWithExternalEntitiesDisabled()
+ {
+ $disableEntities = libxml_disable_entity_loader(true);
+
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.xlf';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ libxml_disable_entity_loader($disableEntities);
+
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadWithResname()
+ {
+ $loader = new XliffFileLoader();
+ $catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo'), $catalogue->all('domain1'));
+ }
+
+ public function testIncompleteResource()
+ {
+ $loader = new XliffFileLoader();
+ $catalogue = $loader->load(__DIR__.'/../fixtures/resources.xlf', 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar', 'extra' => 'extra', 'key' => '', 'test' => 'with'), $catalogue->all('domain1'));
+ }
+
+ public function testEncoding()
+ {
+ $loader = new XliffFileLoader();
+ $catalogue = $loader->load(__DIR__.'/../fixtures/encoding.xlf', 'en', 'domain1');
+
+ $this->assertEquals(utf8_decode('föö'), $catalogue->get('bar', 'domain1'));
+ $this->assertEquals(utf8_decode('bär'), $catalogue->get('foo', 'domain1'));
+ $this->assertEquals(array('notes' => array(array('content' => utf8_decode('bäz')))), $catalogue->getMetadata('foo', 'domain1'));
+ }
+
+ public function testTargetAttributesAreStoredCorrectly()
+ {
+ $loader = new XliffFileLoader();
+ $catalogue = $loader->load(__DIR__.'/../fixtures/with-attributes.xlf', 'en', 'domain1');
+
+ $metadata = $catalogue->getMetadata('foo', 'domain1');
+ $this->assertEquals('translated', $metadata['target-attributes']['state']);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadInvalidResource()
+ {
+ $loader = new XliffFileLoader();
+ $loader->load(__DIR__.'/../fixtures/resources.php', 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadResourceDoesNotValidate()
+ {
+ $loader = new XliffFileLoader();
+ $loader->load(__DIR__.'/../fixtures/non-valid.xlf', 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.xlf';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadThrowsAnExceptionIfFileNotLocal()
+ {
+ $loader = new XliffFileLoader();
+ $resource = 'http://example.com/resources.xlf';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ * @expectedExceptionMessage Document types are not allowed.
+ */
+ public function testDocTypeIsNotAllowed()
+ {
+ $loader = new XliffFileLoader();
+ $loader->load(__DIR__.'/../fixtures/withdoctype.xlf', 'en', 'domain1');
+ }
+
+ public function testParseEmptyFile()
+ {
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.xlf';
+ $this->setExpectedException('Symfony\Component\Translation\Exception\InvalidResourceException', sprintf('Unable to load "%s":', $resource));
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ public function testLoadNotes()
+ {
+ $loader = new XliffFileLoader();
+ $catalogue = $loader->load(__DIR__.'/../fixtures/withnote.xlf', 'en', 'domain1');
+
+ $this->assertEquals(array('notes' => array(array('priority' => 1, 'content' => 'foo'))), $catalogue->getMetadata('foo', 'domain1'));
+ // message without target
+ $this->assertEquals(array('notes' => array(array('content' => 'bar', 'from' => 'foo'))), $catalogue->getMetadata('extra', 'domain1'));
+ // message with empty target
+ $this->assertEquals(array('notes' => array(array('content' => 'baz'), array('priority' => 2, 'from' => 'bar', 'content' => 'qux'))), $catalogue->getMetadata('key', 'domain1'));
+ }
+
+ public function testLoadVersion2()
+ {
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/resources-2.0.xlf';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ $this->assertSame(array(), libxml_get_errors());
+
+ $domains = $catalogue->all();
+ $this->assertCount(3, $domains['domain1']);
+ $this->assertContainsOnly('string', $catalogue->all('domain1'));
+
+ // target attributes
+ $this->assertEquals(array('target-attributes' => array('order' => 1)), $catalogue->getMetadata('bar', 'domain1'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php b/public/system/storage/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php
new file mode 100644
index 0000000..00f7163
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Loader;
+
+use Symfony\Component\Translation\Loader\YamlFileLoader;
+use Symfony\Component\Config\Resource\FileResource;
+
+class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoad()
+ {
+ $loader = new YamlFileLoader();
+ $resource = __DIR__.'/../fixtures/resources.yml';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ public function testLoadDoesNothingIfEmpty()
+ {
+ $loader = new YamlFileLoader();
+ $resource = __DIR__.'/../fixtures/empty.yml';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals(array(), $catalogue->all('domain1'));
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testLoadNonExistingResource()
+ {
+ $loader = new YamlFileLoader();
+ $resource = __DIR__.'/../fixtures/non-existing.yml';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadThrowsAnExceptionIfFileNotLocal()
+ {
+ $loader = new YamlFileLoader();
+ $resource = 'http://example.com/resources.yml';
+ $loader->load($resource, 'en', 'domain1');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
+ */
+ public function testLoadThrowsAnExceptionIfNotAnArray()
+ {
+ $loader = new YamlFileLoader();
+ $resource = __DIR__.'/../fixtures/non-valid.yml';
+ $loader->load($resource, 'en', 'domain1');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/LoggingTranslatorTest.php b/public/system/storage/vendor/symfony/translation/Tests/LoggingTranslatorTest.php
new file mode 100644
index 0000000..9f3e849
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/LoggingTranslatorTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\LoggingTranslator;
+use Symfony\Component\Translation\Loader\ArrayLoader;
+
+class LoggingTranslatorTest extends \PHPUnit_Framework_TestCase
+{
+ public function testTransWithNoTranslationIsLogged()
+ {
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+ $logger->expects($this->exactly(2))
+ ->method('warning')
+ ->with('Translation not found.')
+ ;
+
+ $translator = new Translator('ar');
+ $loggableTranslator = new LoggingTranslator($translator, $logger);
+ $loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
+ $loggableTranslator->trans('bar');
+ }
+
+ public function testTransChoiceFallbackIsLogged()
+ {
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+ $logger->expects($this->once())
+ ->method('debug')
+ ->with('Translation use fallback catalogue.')
+ ;
+
+ $translator = new Translator('ar');
+ $translator->setFallbackLocales(array('en'));
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en');
+ $loggableTranslator = new LoggingTranslator($translator, $logger);
+ $loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/MessageCatalogueTest.php b/public/system/storage/vendor/symfony/translation/Tests/MessageCatalogueTest.php
new file mode 100644
index 0000000..6f55b8c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/MessageCatalogueTest.php
@@ -0,0 +1,214 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+class MessageCatalogueTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetLocale()
+ {
+ $catalogue = new MessageCatalogue('en');
+
+ $this->assertEquals('en', $catalogue->getLocale());
+ }
+
+ public function testGetDomains()
+ {
+ $catalogue = new MessageCatalogue('en', array('domain1' => array(), 'domain2' => array()));
+
+ $this->assertEquals(array('domain1', 'domain2'), $catalogue->getDomains());
+ }
+
+ public function testAll()
+ {
+ $catalogue = new MessageCatalogue('en', $messages = array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+
+ $this->assertEquals(array('foo' => 'foo'), $catalogue->all('domain1'));
+ $this->assertEquals(array(), $catalogue->all('domain88'));
+ $this->assertEquals($messages, $catalogue->all());
+ }
+
+ public function testHas()
+ {
+ $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+
+ $this->assertTrue($catalogue->has('foo', 'domain1'));
+ $this->assertFalse($catalogue->has('bar', 'domain1'));
+ $this->assertFalse($catalogue->has('foo', 'domain88'));
+ }
+
+ public function testGetSet()
+ {
+ $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+ $catalogue->set('foo1', 'foo1', 'domain1');
+
+ $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
+ $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
+ }
+
+ public function testAdd()
+ {
+ $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+ $catalogue->add(array('foo1' => 'foo1'), 'domain1');
+
+ $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
+ $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
+
+ $catalogue->add(array('foo' => 'bar'), 'domain1');
+ $this->assertEquals('bar', $catalogue->get('foo', 'domain1'));
+ $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
+
+ $catalogue->add(array('foo' => 'bar'), 'domain88');
+ $this->assertEquals('bar', $catalogue->get('foo', 'domain88'));
+ }
+
+ public function testReplace()
+ {
+ $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+ $catalogue->replace($messages = array('foo1' => 'foo1'), 'domain1');
+
+ $this->assertEquals($messages, $catalogue->all('domain1'));
+ }
+
+ public function testAddCatalogue()
+ {
+ $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
+ $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
+
+ $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
+ $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
+
+ $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+ $catalogue->addResource($r);
+
+ $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo1' => 'foo1')));
+ $catalogue1->addResource($r1);
+
+ $catalogue->addCatalogue($catalogue1);
+
+ $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
+ $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
+
+ $this->assertEquals(array($r, $r1), $catalogue->getResources());
+ }
+
+ public function testAddFallbackCatalogue()
+ {
+ $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
+ $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
+
+ $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
+ $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
+
+ $catalogue = new MessageCatalogue('en_US', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
+ $catalogue->addResource($r);
+
+ $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo' => 'bar', 'foo1' => 'foo1')));
+ $catalogue1->addResource($r1);
+
+ $catalogue->addFallbackCatalogue($catalogue1);
+
+ $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
+ $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
+
+ $this->assertEquals(array($r, $r1), $catalogue->getResources());
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testAddFallbackCatalogueWithParentCircularReference()
+ {
+ $main = new MessageCatalogue('en_US');
+ $fallback = new MessageCatalogue('fr_FR');
+
+ $fallback->addFallbackCatalogue($main);
+ $main->addFallbackCatalogue($fallback);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testAddFallbackCatalogueWithFallbackCircularReference()
+ {
+ $fr = new MessageCatalogue('fr');
+ $en = new MessageCatalogue('en');
+ $es = new MessageCatalogue('es');
+
+ $fr->addFallbackCatalogue($en);
+ $es->addFallbackCatalogue($en);
+ $en->addFallbackCatalogue($fr);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testAddCatalogueWhenLocaleIsNotTheSameAsTheCurrentOne()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->addCatalogue(new MessageCatalogue('fr', array()));
+ }
+
+ public function testGetAddResource()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
+ $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
+ $catalogue->addResource($r);
+ $catalogue->addResource($r);
+ $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
+ $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
+ $catalogue->addResource($r1);
+
+ $this->assertEquals(array($r, $r1), $catalogue->getResources());
+ }
+
+ public function testMetadataDelete()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $this->assertEquals(array(), $catalogue->getMetadata('', ''), 'Metadata is empty');
+ $catalogue->deleteMetadata('key', 'messages');
+ $catalogue->deleteMetadata('', 'messages');
+ $catalogue->deleteMetadata();
+ }
+
+ public function testMetadataSetGetDelete()
+ {
+ $catalogue = new MessageCatalogue('en');
+ $catalogue->setMetadata('key', 'value');
+ $this->assertEquals('value', $catalogue->getMetadata('key', 'messages'), "Metadata 'key' = 'value'");
+
+ $catalogue->setMetadata('key2', array());
+ $this->assertEquals(array(), $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 is array');
+
+ $catalogue->deleteMetadata('key2', 'messages');
+ $this->assertNull($catalogue->getMetadata('key2', 'messages'), 'Metadata key2 should is deleted.');
+
+ $catalogue->deleteMetadata('key2', 'domain');
+ $this->assertNull($catalogue->getMetadata('key2', 'domain'), 'Metadata key2 should is deleted.');
+ }
+
+ public function testMetadataMerge()
+ {
+ $cat1 = new MessageCatalogue('en');
+ $cat1->setMetadata('a', 'b');
+ $this->assertEquals(array('messages' => array('a' => 'b')), $cat1->getMetadata('', ''), 'Cat1 contains messages metadata.');
+
+ $cat2 = new MessageCatalogue('en');
+ $cat2->setMetadata('b', 'c', 'domain');
+ $this->assertEquals(array('domain' => array('b' => 'c')), $cat2->getMetadata('', ''), 'Cat2 contains domain metadata.');
+
+ $cat1->addCatalogue($cat2);
+ $this->assertEquals(array('messages' => array('a' => 'b'), 'domain' => array('b' => 'c')), $cat1->getMetadata('', ''), 'Cat1 contains merged metadata.');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/MessageSelectorTest.php b/public/system/storage/vendor/symfony/translation/Tests/MessageSelectorTest.php
new file mode 100644
index 0000000..f89bed1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/MessageSelectorTest.php
@@ -0,0 +1,130 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\MessageSelector;
+
+class MessageSelectorTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getChooseTests
+ */
+ public function testChoose($expected, $id, $number)
+ {
+ $selector = new MessageSelector();
+
+ $this->assertEquals($expected, $selector->choose($id, $number, 'en'));
+ }
+
+ public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
+ {
+ $selector = new MessageSelector();
+
+ $this->assertEquals('There are two apples', $selector->choose('There are two apples', 2, 'en'));
+ }
+
+ /**
+ * @dataProvider getNonMatchingMessages
+ * @expectedException \InvalidArgumentException
+ */
+ public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
+ {
+ $selector = new MessageSelector();
+
+ $selector->choose($id, $number, 'en');
+ }
+
+ public function getNonMatchingMessages()
+ {
+ return array(
+ array('{0} There are no apples|{1} There is one apple', 2),
+ array('{1} There is one apple|]1,Inf] There are %count% apples', 0),
+ array('{1} There is one apple|]2,Inf] There are %count% apples', 2),
+ array('{0} There are no apples|There is one apple', 2),
+ );
+ }
+
+ public function getChooseTests()
+ {
+ return array(
+ array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
+ array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
+ array('There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
+
+ array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),
+
+ array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
+ array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10),
+ array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
+
+ array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
+ array('There is one apple', 'There is one apple|There are %count% apples', 1),
+ array('There are %count% apples', 'There is one apple|There are %count% apples', 10),
+
+ array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 0),
+ array('There is one apple', 'one: There is one apple|more: There are %count% apples', 1),
+ array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 10),
+
+ array('There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0),
+ array('There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1),
+ array('There are %count% apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10),
+
+ array('', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0),
+ array('', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1),
+
+ // Indexed only tests which are Gettext PoFile* compatible strings.
+ array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
+ array('There is one apple', 'There is one apple|There are %count% apples', 1),
+ array('There are %count% apples', 'There is one apple|There are %count% apples', 2),
+
+ // Tests for float numbers
+ array('There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7),
+ array('There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1),
+ array('There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7),
+ array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
+ array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0),
+ array('There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
+
+ // Test texts with new-lines
+ // with double-quotes and \n in id & double-quotes and actual newlines in text
+ array("This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 0),
+ // with double-quotes and \n in id and single-quotes and actual newlines in text
+ array("This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 1),
+ array("This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 5),
+ // with double-quotes and id split accros lines
+ array('This is a text with a
+ new-line in it. Selector = 1.', '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 1),
+ // with single-quotes and id split accros lines
+ array('This is a text with a
+ new-line in it. Selector > 1.', '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 5),
+ // with single-quotes and \n in text
+ array('This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0),
+ // with double-quotes and id split accros lines
+ array("This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/PluralizationRulesTest.php b/public/system/storage/vendor/symfony/translation/Tests/PluralizationRulesTest.php
new file mode 100644
index 0000000..78bbc87
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/PluralizationRulesTest.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\PluralizationRules;
+
+/**
+ * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
+ * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms.
+ *
+ * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
+ * The mozilla code is also interesting to check for.
+ *
+ * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
+ *
+ * The goal to cover all languages is to far fetched so this test case is smaller.
+ *
+ * @author Clemens Tolboom clemens@build2be.nl
+ */
+class PluralizationRulesTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * We test failed langcode here.
+ *
+ * TODO: The languages mentioned in the data provide need to get fixed somehow within PluralizationRules.
+ *
+ * @dataProvider failingLangcodes
+ */
+ public function testFailedLangcodes($nplural, $langCodes)
+ {
+ $matrix = $this->generateTestData($langCodes);
+ $this->validateMatrix($nplural, $matrix, false);
+ }
+
+ /**
+ * @dataProvider successLangcodes
+ */
+ public function testLangcodes($nplural, $langCodes)
+ {
+ $matrix = $this->generateTestData($langCodes);
+ $this->validateMatrix($nplural, $matrix);
+ }
+
+ /**
+ * This array should contain all currently known langcodes.
+ *
+ * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
+ *
+ * @return array
+ */
+ public function successLangcodes()
+ {
+ return array(
+ array('1', array('ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky')),
+ array('2', array('nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM')),
+ array('3', array('be', 'bs', 'cs', 'hr')),
+ array('4', array('cy', 'mt', 'sl')),
+ array('5', array()),
+ array('6', array('ar')),
+ );
+ }
+
+ /**
+ * This array should be at least empty within the near future.
+ *
+ * This both depends on a complete list trying to add above as understanding
+ * the plural rules of the current failing languages.
+ *
+ * @return array with nplural together with langcodes
+ */
+ public function failingLangcodes()
+ {
+ return array(
+ array('1', array('fa')),
+ array('2', array('jbo')),
+ array('3', array('cbs')),
+ array('4', array('gd', 'kw')),
+ array('5', array('ga')),
+ array('6', array()),
+ );
+ }
+
+ /**
+ * We validate only on the plural coverage. Thus the real rules is not tested.
+ *
+ * @param string $nplural plural expected
+ * @param array $matrix containing langcodes and their plural index values
+ * @param bool $expectSuccess
+ */
+ protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
+ {
+ foreach ($matrix as $langCode => $data) {
+ $indexes = array_flip($data);
+ if ($expectSuccess) {
+ $this->assertEquals($nplural, count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
+ } else {
+ $this->assertNotEquals((int) $nplural, count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
+ }
+ }
+ }
+
+ protected function generateTestData($langCodes)
+ {
+ $matrix = array();
+ foreach ($langCodes as $langCode) {
+ for ($count = 0; $count < 200; ++$count) {
+ $plural = PluralizationRules::get($count, $langCode);
+ $matrix[$langCode][$count] = $plural;
+ }
+ }
+
+ return $matrix;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/TranslatorCacheTest.php b/public/system/storage/vendor/symfony/translation/Tests/TranslatorCacheTest.php
new file mode 100644
index 0000000..7509358
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/TranslatorCacheTest.php
@@ -0,0 +1,299 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
+use Symfony\Component\Translation\Loader\ArrayLoader;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\MessageCatalogue;
+
+class TranslatorCacheTest extends \PHPUnit_Framework_TestCase
+{
+ protected $tmpDir;
+
+ protected function setUp()
+ {
+ $this->tmpDir = sys_get_temp_dir().'/sf2_translation';
+ $this->deleteTmpDir();
+ }
+
+ protected function tearDown()
+ {
+ $this->deleteTmpDir();
+ }
+
+ protected function deleteTmpDir()
+ {
+ if (!file_exists($dir = $this->tmpDir)) {
+ return;
+ }
+
+ $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->tmpDir), \RecursiveIteratorIterator::CHILD_FIRST);
+ foreach ($iterator as $path) {
+ if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) {
+ continue;
+ }
+ if ($path->isDir()) {
+ rmdir($path->__toString());
+ } else {
+ unlink($path->__toString());
+ }
+ }
+ rmdir($this->tmpDir);
+ }
+
+ /**
+ * @dataProvider runForDebugAndProduction
+ */
+ public function testThatACacheIsUsed($debug)
+ {
+ $locale = 'any_locale';
+ $format = 'some_format';
+ $msgid = 'test';
+
+ // Prime the cache
+ $translator = new Translator($locale, null, $this->tmpDir, $debug);
+ $translator->addLoader($format, new ArrayLoader());
+ $translator->addResource($format, array($msgid => 'OK'), $locale);
+ $translator->trans($msgid);
+
+ // Try again and see we get a valid result whilst no loader can be used
+ $translator = new Translator($locale, null, $this->tmpDir, $debug);
+ $translator->addLoader($format, $this->createFailingLoader());
+ $translator->addResource($format, array($msgid => 'OK'), $locale);
+ $this->assertEquals('OK', $translator->trans($msgid), '-> caching does not work in '.($debug ? 'debug' : 'production'));
+ }
+
+ public function testCatalogueIsReloadedWhenResourcesAreNoLongerFresh()
+ {
+ /*
+ * The testThatACacheIsUsed() test showed that we don't need the loader as long as the cache
+ * is fresh.
+ *
+ * Now we add a Resource that is never fresh and make sure that the
+ * cache is discarded (the loader is called twice).
+ *
+ * We need to run this for debug=true only because in production the cache
+ * will never be revalidated.
+ */
+
+ $locale = 'any_locale';
+ $format = 'some_format';
+ $msgid = 'test';
+
+ $catalogue = new MessageCatalogue($locale, array());
+ $catalogue->addResource(new StaleResource()); // better use a helper class than a mock, because it gets serialized in the cache and re-loaded
+
+ /** @var LoaderInterface|\PHPUnit_Framework_MockObject_MockObject $loader */
+ $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $loader
+ ->expects($this->exactly(2))
+ ->method('load')
+ ->will($this->returnValue($catalogue))
+ ;
+
+ // 1st pass
+ $translator = new Translator($locale, null, $this->tmpDir, true);
+ $translator->addLoader($format, $loader);
+ $translator->addResource($format, null, $locale);
+ $translator->trans($msgid);
+
+ // 2nd pass
+ $translator = new Translator($locale, null, $this->tmpDir, true);
+ $translator->addLoader($format, $loader);
+ $translator->addResource($format, null, $locale);
+ $translator->trans($msgid);
+ }
+
+ /**
+ * @dataProvider runForDebugAndProduction
+ */
+ public function testDifferentTranslatorsForSameLocaleDoNotOverwriteEachOthersCache($debug)
+ {
+ /*
+ * Similar to the previous test. After we used the second translator, make
+ * sure there's still a useable cache for the first one.
+ */
+
+ $locale = 'any_locale';
+ $format = 'some_format';
+ $msgid = 'test';
+
+ // Create a Translator and prime its cache
+ $translator = new Translator($locale, null, $this->tmpDir, $debug);
+ $translator->addLoader($format, new ArrayLoader());
+ $translator->addResource($format, array($msgid => 'OK'), $locale);
+ $translator->trans($msgid);
+
+ // Create another Translator with a different catalogue for the same locale
+ $translator = new Translator($locale, null, $this->tmpDir, $debug);
+ $translator->addLoader($format, new ArrayLoader());
+ $translator->addResource($format, array($msgid => 'FAIL'), $locale);
+ $translator->trans($msgid);
+
+ // Now the first translator must still have a useable cache.
+ $translator = new Translator($locale, null, $this->tmpDir, $debug);
+ $translator->addLoader($format, $this->createFailingLoader());
+ $translator->addResource($format, array($msgid => 'OK'), $locale);
+ $this->assertEquals('OK', $translator->trans($msgid), '-> the cache was overwritten by another translator instance in '.($debug ? 'debug' : 'production'));
+ }
+
+ public function testDifferentCacheFilesAreUsedForDifferentSetsOfFallbackLocales()
+ {
+ /*
+ * Because the cache file contains a catalogue including all of its fallback
+ * catalogues, we must take the set of fallback locales into consideration when
+ * loading a catalogue from the cache.
+ */
+ $translator = new Translator('a', null, $this->tmpDir);
+ $translator->setFallbackLocales(array('b'));
+
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (a)'), 'a');
+ $translator->addResource('array', array('bar' => 'bar (b)'), 'b');
+
+ $this->assertEquals('bar (b)', $translator->trans('bar'));
+
+ // Remove fallback locale
+ $translator->setFallbackLocales(array());
+ $this->assertEquals('bar', $translator->trans('bar'));
+
+ // Use a fresh translator with no fallback locales, result should be the same
+ $translator = new Translator('a', null, $this->tmpDir);
+
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (a)'), 'a');
+ $translator->addResource('array', array('bar' => 'bar (b)'), 'b');
+
+ $this->assertEquals('bar', $translator->trans('bar'));
+ }
+
+ public function testPrimaryAndFallbackCataloguesContainTheSameMessagesRegardlessOfCaching()
+ {
+ /*
+ * As a safeguard against potential BC breaks, make sure that primary and fallback
+ * catalogues (reachable via getFallbackCatalogue()) always contain the full set of
+ * messages provided by the loader. This must also be the case when these catalogues
+ * are (internally) read from a cache.
+ *
+ * Optimizations inside the translator must not change this behaviour.
+ */
+
+ /*
+ * Create a translator that loads two catalogues for two different locales.
+ * The catalogues contain distinct sets of messages.
+ */
+ $translator = new Translator('a', null, $this->tmpDir);
+ $translator->setFallbackLocales(array('b'));
+
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (a)'), 'a');
+ $translator->addResource('array', array('foo' => 'foo (b)'), 'b');
+ $translator->addResource('array', array('bar' => 'bar (b)'), 'b');
+
+ $catalogue = $translator->getCatalogue('a');
+ $this->assertFalse($catalogue->defines('bar')); // Sure, the "a" catalogue does not contain that message.
+
+ $fallback = $catalogue->getFallbackCatalogue();
+ $this->assertTrue($fallback->defines('foo')); // "foo" is present in "a" and "b"
+
+ /*
+ * Now, repeat the same test.
+ * Behind the scenes, the cache is used. But that should not matter, right?
+ */
+ $translator = new Translator('a', null, $this->tmpDir);
+ $translator->setFallbackLocales(array('b'));
+
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (a)'), 'a');
+ $translator->addResource('array', array('foo' => 'foo (b)'), 'b');
+ $translator->addResource('array', array('bar' => 'bar (b)'), 'b');
+
+ $catalogue = $translator->getCatalogue('a');
+ $this->assertFalse($catalogue->defines('bar'));
+
+ $fallback = $catalogue->getFallbackCatalogue();
+ $this->assertTrue($fallback->defines('foo'));
+ }
+
+ public function testRefreshCacheWhenResourcesAreNoLongerFresh()
+ {
+ $resource = $this->getMock('Symfony\Component\Config\Resource\SelfCheckingResourceInterface');
+ $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $resource->method('isFresh')->will($this->returnValue(false));
+ $loader
+ ->expects($this->exactly(2))
+ ->method('load')
+ ->will($this->returnValue($this->getCatalogue('fr', array(), array($resource))));
+
+ // prime the cache
+ $translator = new Translator('fr', null, $this->tmpDir, true);
+ $translator->addLoader('loader', $loader);
+ $translator->addResource('loader', 'foo', 'fr');
+ $translator->trans('foo');
+
+ // prime the cache second time
+ $translator = new Translator('fr', null, $this->tmpDir, true);
+ $translator->addLoader('loader', $loader);
+ $translator->addResource('loader', 'foo', 'fr');
+ $translator->trans('foo');
+ }
+
+ protected function getCatalogue($locale, $messages, $resources = array())
+ {
+ $catalogue = new MessageCatalogue($locale);
+ foreach ($messages as $key => $translation) {
+ $catalogue->set($key, $translation);
+ }
+ foreach ($resources as $resource) {
+ $catalogue->addResource($resource);
+ }
+
+ return $catalogue;
+ }
+
+ public function runForDebugAndProduction()
+ {
+ return array(array(true), array(false));
+ }
+
+ /**
+ * @return LoaderInterface
+ */
+ private function createFailingLoader()
+ {
+ $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $loader
+ ->expects($this->never())
+ ->method('load');
+
+ return $loader;
+ }
+}
+
+class StaleResource implements SelfCheckingResourceInterface
+{
+ public function isFresh($timestamp)
+ {
+ return false;
+ }
+
+ public function getResource()
+ {
+ }
+
+ public function __toString()
+ {
+ return '';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/TranslatorTest.php b/public/system/storage/vendor/symfony/translation/Tests/TranslatorTest.php
new file mode 100644
index 0000000..0f65d3e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/TranslatorTest.php
@@ -0,0 +1,533 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests;
+
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\MessageSelector;
+use Symfony\Component\Translation\Loader\ArrayLoader;
+use Symfony\Component\Translation\MessageCatalogue;
+
+class TranslatorTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getInvalidLocalesTests
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorInvalidLocale($locale)
+ {
+ $translator = new Translator($locale, new MessageSelector());
+ }
+
+ /**
+ * @dataProvider getValidLocalesTests
+ */
+ public function testConstructorValidLocale($locale)
+ {
+ $translator = new Translator($locale, new MessageSelector());
+
+ $this->assertEquals($locale, $translator->getLocale());
+ }
+
+ public function testConstructorWithoutLocale()
+ {
+ $translator = new Translator(null, new MessageSelector());
+
+ $this->assertNull($translator->getLocale());
+ }
+
+ public function testSetGetLocale()
+ {
+ $translator = new Translator('en');
+
+ $this->assertEquals('en', $translator->getLocale());
+
+ $translator->setLocale('fr');
+ $this->assertEquals('fr', $translator->getLocale());
+ }
+
+ /**
+ * @dataProvider getInvalidLocalesTests
+ * @expectedException \InvalidArgumentException
+ */
+ public function testSetInvalidLocale($locale)
+ {
+ $translator = new Translator('fr', new MessageSelector());
+ $translator->setLocale($locale);
+ }
+
+ /**
+ * @dataProvider getValidLocalesTests
+ */
+ public function testSetValidLocale($locale)
+ {
+ $translator = new Translator($locale, new MessageSelector());
+ $translator->setLocale($locale);
+
+ $this->assertEquals($locale, $translator->getLocale());
+ }
+
+ public function testGetCatalogue()
+ {
+ $translator = new Translator('en');
+
+ $this->assertEquals(new MessageCatalogue('en'), $translator->getCatalogue());
+
+ $translator->setLocale('fr');
+ $this->assertEquals(new MessageCatalogue('fr'), $translator->getCatalogue('fr'));
+ }
+
+ public function testGetCatalogueReturnsConsolidatedCatalogue()
+ {
+ /*
+ * This will be useful once we refactor so that different domains will be loaded lazily (on-demand).
+ * In that case, getCatalogue() will probably have to load all missing domains in order to return
+ * one complete catalogue.
+ */
+
+ $locale = 'whatever';
+ $translator = new Translator($locale);
+ $translator->addLoader('loader-a', new ArrayLoader());
+ $translator->addLoader('loader-b', new ArrayLoader());
+ $translator->addResource('loader-a', array('foo' => 'foofoo'), $locale, 'domain-a');
+ $translator->addResource('loader-b', array('bar' => 'foobar'), $locale, 'domain-b');
+
+ /*
+ * Test that we get a single catalogue comprising messages
+ * from different loaders and different domains
+ */
+ $catalogue = $translator->getCatalogue($locale);
+ $this->assertTrue($catalogue->defines('foo', 'domain-a'));
+ $this->assertTrue($catalogue->defines('bar', 'domain-b'));
+ }
+
+ public function testSetFallbackLocales()
+ {
+ $translator = new Translator('en');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en');
+ $translator->addResource('array', array('bar' => 'foobar'), 'fr');
+
+ // force catalogue loading
+ $translator->trans('bar');
+
+ $translator->setFallbackLocales(array('fr'));
+ $this->assertEquals('foobar', $translator->trans('bar'));
+ }
+
+ public function testSetFallbackLocalesMultiple()
+ {
+ $translator = new Translator('en');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (en)'), 'en');
+ $translator->addResource('array', array('bar' => 'bar (fr)'), 'fr');
+
+ // force catalogue loading
+ $translator->trans('bar');
+
+ $translator->setFallbackLocales(array('fr_FR', 'fr'));
+ $this->assertEquals('bar (fr)', $translator->trans('bar'));
+ }
+
+ /**
+ * @dataProvider getInvalidLocalesTests
+ * @expectedException \InvalidArgumentException
+ */
+ public function testSetFallbackInvalidLocales($locale)
+ {
+ $translator = new Translator('fr', new MessageSelector());
+ $translator->setFallbackLocales(array('fr', $locale));
+ }
+
+ /**
+ * @dataProvider getValidLocalesTests
+ */
+ public function testSetFallbackValidLocales($locale)
+ {
+ $translator = new Translator($locale, new MessageSelector());
+ $translator->setFallbackLocales(array('fr', $locale));
+ // no assertion. this method just asserts that no exception is thrown
+ }
+
+ public function testTransWithFallbackLocale()
+ {
+ $translator = new Translator('fr_FR');
+ $translator->setFallbackLocales(array('en'));
+
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('bar' => 'foobar'), 'en');
+
+ $this->assertEquals('foobar', $translator->trans('bar'));
+ }
+
+ /**
+ * @dataProvider getInvalidLocalesTests
+ * @expectedException \InvalidArgumentException
+ */
+ public function testAddResourceInvalidLocales($locale)
+ {
+ $translator = new Translator('fr', new MessageSelector());
+ $translator->addResource('array', array('foo' => 'foofoo'), $locale);
+ }
+
+ /**
+ * @dataProvider getValidLocalesTests
+ */
+ public function testAddResourceValidLocales($locale)
+ {
+ $translator = new Translator('fr', new MessageSelector());
+ $translator->addResource('array', array('foo' => 'foofoo'), $locale);
+ // no assertion. this method just asserts that no exception is thrown
+ }
+
+ public function testAddResourceAfterTrans()
+ {
+ $translator = new Translator('fr');
+ $translator->addLoader('array', new ArrayLoader());
+
+ $translator->setFallbackLocales(array('en'));
+
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en');
+ $this->assertEquals('foofoo', $translator->trans('foo'));
+
+ $translator->addResource('array', array('bar' => 'foobar'), 'en');
+ $this->assertEquals('foobar', $translator->trans('bar'));
+ }
+
+ /**
+ * @dataProvider getTransFileTests
+ * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
+ */
+ public function testTransWithoutFallbackLocaleFile($format, $loader)
+ {
+ $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
+ $translator = new Translator('en');
+ $translator->addLoader($format, new $loaderClass());
+ $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en');
+ $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en');
+
+ // force catalogue loading
+ $translator->trans('foo');
+ }
+
+ /**
+ * @dataProvider getTransFileTests
+ */
+ public function testTransWithFallbackLocaleFile($format, $loader)
+ {
+ $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
+ $translator = new Translator('en_GB');
+ $translator->addLoader($format, new $loaderClass());
+ $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en_GB');
+ $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en', 'resources');
+
+ $this->assertEquals('bar', $translator->trans('foo', array(), 'resources'));
+ }
+
+ public function testTransWithFallbackLocaleBis()
+ {
+ $translator = new Translator('en_US');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
+ $translator->addResource('array', array('bar' => 'foobar'), 'en');
+ $this->assertEquals('foobar', $translator->trans('bar'));
+ }
+
+ public function testTransWithFallbackLocaleTer()
+ {
+ $translator = new Translator('fr_FR');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foo (en_US)'), 'en_US');
+ $translator->addResource('array', array('bar' => 'bar (en)'), 'en');
+
+ $translator->setFallbackLocales(array('en_US', 'en'));
+
+ $this->assertEquals('foo (en_US)', $translator->trans('foo'));
+ $this->assertEquals('bar (en)', $translator->trans('bar'));
+ }
+
+ public function testTransNonExistentWithFallback()
+ {
+ $translator = new Translator('fr');
+ $translator->setFallbackLocales(array('en'));
+ $translator->addLoader('array', new ArrayLoader());
+ $this->assertEquals('non-existent', $translator->trans('non-existent'));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testWhenAResourceHasNoRegisteredLoader()
+ {
+ $translator = new Translator('en');
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en');
+
+ $translator->trans('foo');
+ }
+
+ public function testFallbackCatalogueResources()
+ {
+ $translator = new Translator('en_GB', new MessageSelector());
+ $translator->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
+ $translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB');
+ $translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en');
+
+ // force catalogue loading
+ $this->assertEquals('bar', $translator->trans('foo', array()));
+
+ $resources = $translator->getCatalogue('en')->getResources();
+ $this->assertCount(1, $resources);
+ $this->assertContains(__DIR__.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'resources.yml', $resources);
+
+ $resources = $translator->getCatalogue('en_GB')->getResources();
+ $this->assertCount(2, $resources);
+ $this->assertContains(__DIR__.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'empty.yml', $resources);
+ $this->assertContains(__DIR__.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'resources.yml', $resources);
+ }
+
+ /**
+ * @dataProvider getTransTests
+ */
+ public function testTrans($expected, $id, $translation, $parameters, $locale, $domain)
+ {
+ $translator = new Translator('en');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array((string) $id => $translation), $locale, $domain);
+
+ $this->assertEquals($expected, $translator->trans($id, $parameters, $domain, $locale));
+ }
+
+ /**
+ * @dataProvider getInvalidLocalesTests
+ * @expectedException \InvalidArgumentException
+ */
+ public function testTransInvalidLocale($locale)
+ {
+ $translator = new Translator('en', new MessageSelector());
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en');
+
+ $translator->trans('foo', array(), '', $locale);
+ }
+
+ /**
+ * @dataProvider getValidLocalesTests
+ */
+ public function testTransValidLocale($locale)
+ {
+ $translator = new Translator($locale, new MessageSelector());
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('test' => 'OK'), $locale);
+
+ $this->assertEquals('OK', $translator->trans('test'));
+ $this->assertEquals('OK', $translator->trans('test', array(), null, $locale));
+ }
+
+ /**
+ * @dataProvider getFlattenedTransTests
+ */
+ public function testFlattenedTrans($expected, $messages, $id)
+ {
+ $translator = new Translator('en');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', $messages, 'fr', '');
+
+ $this->assertEquals($expected, $translator->trans($id, array(), '', 'fr'));
+ }
+
+ /**
+ * @dataProvider getTransChoiceTests
+ */
+ public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
+ {
+ $translator = new Translator('en');
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array((string) $id => $translation), $locale, $domain);
+
+ $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters, $domain, $locale));
+ }
+
+ /**
+ * @dataProvider getInvalidLocalesTests
+ * @expectedException \InvalidArgumentException
+ */
+ public function testTransChoiceInvalidLocale($locale)
+ {
+ $translator = new Translator('en', new MessageSelector());
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en');
+
+ $translator->transChoice('foo', 1, array(), '', $locale);
+ }
+
+ /**
+ * @dataProvider getValidLocalesTests
+ */
+ public function testTransChoiceValidLocale($locale)
+ {
+ $translator = new Translator('en', new MessageSelector());
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('foo' => 'foofoo'), 'en');
+
+ $translator->transChoice('foo', 1, array(), '', $locale);
+ // no assertion. this method just asserts that no exception is thrown
+ }
+
+ public function getTransFileTests()
+ {
+ return array(
+ array('csv', 'CsvFileLoader'),
+ array('ini', 'IniFileLoader'),
+ array('mo', 'MoFileLoader'),
+ array('po', 'PoFileLoader'),
+ array('php', 'PhpFileLoader'),
+ array('ts', 'QtFileLoader'),
+ array('xlf', 'XliffFileLoader'),
+ array('yml', 'YamlFileLoader'),
+ array('json', 'JsonFileLoader'),
+ );
+ }
+
+ public function getTransTests()
+ {
+ return array(
+ array('Symfony est super !', 'Symfony is great!', 'Symfony est super !', array(), 'fr', ''),
+ array('Symfony est awesome !', 'Symfony is %what%!', 'Symfony est %what% !', array('%what%' => 'awesome'), 'fr', ''),
+ array('Symfony est super !', new StringClass('Symfony is great!'), 'Symfony est super !', array(), 'fr', ''),
+ );
+ }
+
+ public function getFlattenedTransTests()
+ {
+ $messages = array(
+ 'symfony' => array(
+ 'is' => array(
+ 'great' => 'Symfony est super!',
+ ),
+ ),
+ 'foo' => array(
+ 'bar' => array(
+ 'baz' => 'Foo Bar Baz',
+ ),
+ 'baz' => 'Foo Baz',
+ ),
+ );
+
+ return array(
+ array('Symfony est super!', $messages, 'symfony.is.great'),
+ array('Foo Bar Baz', $messages, 'foo.bar.baz'),
+ array('Foo Baz', $messages, 'foo.baz'),
+ );
+ }
+
+ public function getTransChoiceTests()
+ {
+ return array(
+ array('Il y a 0 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
+ array('Il y a 1 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
+ array('Il y a 10 pommes', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),
+
+ array('Il y a 0 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
+ array('Il y a 1 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
+ array('Il y a 10 pommes', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),
+
+ array('Il y a 0 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
+ array('Il y a 1 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
+ array('Il y a 10 pommes', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),
+
+ array('Il n\'y a aucune pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
+ array('Il y a 1 pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
+ array('Il y a 10 pommes', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),
+
+ array('Il y a 0 pomme', new StringClass('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
+ );
+ }
+
+ public function getInvalidLocalesTests()
+ {
+ return array(
+ array('fr FR'),
+ array('français'),
+ array('fr+en'),
+ array('utf#8'),
+ array('fr&en'),
+ array('fr~FR'),
+ array(' fr'),
+ array('fr '),
+ array('fr*'),
+ array('fr/FR'),
+ array('fr\\FR'),
+ );
+ }
+
+ public function getValidLocalesTests()
+ {
+ return array(
+ array(''),
+ array(null),
+ array('fr'),
+ array('francais'),
+ array('FR'),
+ array('frFR'),
+ array('fr-FR'),
+ array('fr_FR'),
+ array('fr.FR'),
+ array('fr-FR.UTF8'),
+ array('sr@latin'),
+ );
+ }
+
+ public function testTransChoiceFallback()
+ {
+ $translator = new Translator('ru');
+ $translator->setFallbackLocales(array('en'));
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en');
+
+ $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
+ }
+
+ public function testTransChoiceFallbackBis()
+ {
+ $translator = new Translator('ru');
+ $translator->setFallbackLocales(array('en_US', 'en'));
+ $translator->addLoader('array', new ArrayLoader());
+ $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en_US');
+
+ $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
+ }
+
+ public function testTransChoiceFallbackWithNoTranslation()
+ {
+ $translator = new Translator('ru');
+ $translator->setFallbackLocales(array('en'));
+ $translator->addLoader('array', new ArrayLoader());
+
+ // consistent behavior with Translator::trans(), which returns the string
+ // unchanged if it can't be found
+ $this->assertEquals('some_message2', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
+ }
+}
+
+class StringClass
+{
+ protected $str;
+
+ public function __construct($str)
+ {
+ $this->str = $str;
+ }
+
+ public function __toString()
+ {
+ return $this->str;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php b/public/system/storage/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php
new file mode 100644
index 0000000..9eea275
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Util;
+
+use Symfony\Component\Translation\Util\ArrayConverter;
+
+class ArrayConverterTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider messsagesData
+ */
+ public function testDump($input, $expectedOutput)
+ {
+ $this->assertEquals($expectedOutput, ArrayConverter::expandToTree($input));
+ }
+
+ public function messsagesData()
+ {
+ return array(
+ array(
+ // input
+ array(
+ 'foo1' => 'bar',
+ 'foo.bar' => 'value',
+ ),
+ // expected output
+ array(
+ 'foo1' => 'bar',
+ 'foo' => array('bar' => 'value'),
+ ),
+ ),
+ array(
+ // input
+ array(
+ 'foo.bar' => 'value1',
+ 'foo.bar.test' => 'value2',
+ ),
+ // expected output
+ array(
+ 'foo' => array(
+ 'bar' => 'value1',
+ 'bar.test' => 'value2',
+ ),
+ ),
+ ),
+ array(
+ // input
+ array(
+ 'foo.level2.level3.level4' => 'value1',
+ 'foo.level2' => 'value2',
+ 'foo.bar' => 'value3',
+ ),
+ // expected output
+ array(
+ 'foo' => array(
+ 'level2' => 'value2',
+ 'level2.level3.level4' => 'value1',
+ 'bar' => 'value3',
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php b/public/system/storage/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php
new file mode 100644
index 0000000..f7a8a83
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Writer;
+
+use Symfony\Component\Translation\Dumper\DumperInterface;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Writer\TranslationWriter;
+
+class TranslationWriterTest extends \PHPUnit_Framework_TestCase
+{
+ public function testWriteTranslations()
+ {
+ $dumper = $this->getMock('Symfony\Component\Translation\Dumper\DumperInterface');
+ $dumper
+ ->expects($this->once())
+ ->method('dump');
+
+ $writer = new TranslationWriter();
+ $writer->addDumper('test', $dumper);
+ $writer->writeTranslations(new MessageCatalogue(array()), 'test');
+ }
+
+ public function testDisableBackup()
+ {
+ $nonBackupDumper = new NonBackupDumper();
+ $backupDumper = new BackupDumper();
+
+ $writer = new TranslationWriter();
+ $writer->addDumper('non_backup', $nonBackupDumper);
+ $writer->addDumper('backup', $backupDumper);
+ $writer->disableBackup();
+
+ $this->assertFalse($backupDumper->backup, 'backup can be disabled if setBackup() method does exist');
+ }
+}
+
+class NonBackupDumper implements DumperInterface
+{
+ public function dump(MessageCatalogue $messages, $options = array())
+ {
+ }
+}
+
+class BackupDumper implements DumperInterface
+{
+ public $backup = true;
+
+ public function dump(MessageCatalogue $messages, $options = array())
+ {
+ }
+
+ public function setBackup($backup)
+ {
+ $this->backup = $backup;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.mo b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.mo
new file mode 100644
index 0000000..ed01000
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.mo
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.po
new file mode 100644
index 0000000..ff6f22a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty-translation.po
@@ -0,0 +1,3 @@
+msgid "foo"
+msgstr ""
+
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.csv b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.csv
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.csv
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.ini b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.ini
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.ini
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.json b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.json
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.mo b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.mo
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.mo
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.po
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.po
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.xlf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.xlf
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.yml b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.yml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/empty.yml
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/encoding.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/encoding.xlf
new file mode 100644
index 0000000..0a88f92
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/encoding.xlf
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1" resname="foo">
+ <source>foo</source>
+ <target>br</target>
+ <note>bz</note>
+ </trans-unit>
+ <trans-unit id="2" resname="bar">
+ <source>bar</source>
+ <target>f</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po
new file mode 100644
index 0000000..c412aa2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po
@@ -0,0 +1,10 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+
+msgid "escaped \"foo\""
+msgid_plural "escaped \"foos\""
+msgstr[0] "escaped \"bar\""
+msgstr[1] "escaped \"bars\""
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id.po
new file mode 100644
index 0000000..308eadd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/escaped-id.po
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+
+msgid "escaped \"foo\""
+msgstr "escaped \"bar\""
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po
new file mode 100644
index 0000000..04d4047
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po
@@ -0,0 +1,10 @@
+#, php-format
+msgid "foo1"
+msgstr "bar1"
+
+#, fuzzy, php-format
+msgid "foo2"
+msgstr "fuzzy bar2"
+
+msgid "foo3"
+msgstr "bar3"
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf
new file mode 100644
index 0000000..7bf6c98
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>foo</source>
+ <target>bar
+ </trans-unit>
+ <trans-unit id="2">
+ <source>extra</source>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>key</source>
+ <target></target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>test</source>
+ <target>with</target>
+ <note>note</note>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/malformed.json b/public/system/storage/vendor/symfony/translation/Tests/fixtures/malformed.json
new file mode 100644
index 0000000..4563ec6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/malformed.json
@@ -0,0 +1,3 @@
+{
+ "foo" "bar"
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/messages.yml b/public/system/storage/vendor/symfony/translation/Tests/fixtures/messages.yml
new file mode 100644
index 0000000..d4f82d7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/messages.yml
@@ -0,0 +1,3 @@
+foo:
+ bar1: value1
+ bar2: value2
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/messages_linear.yml b/public/system/storage/vendor/symfony/translation/Tests/fixtures/messages_linear.yml
new file mode 100644
index 0000000..6c1687d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/messages_linear.yml
@@ -0,0 +1,2 @@
+foo.bar1: value1
+foo.bar2: value2
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.xlf
new file mode 100644
index 0000000..734fc97
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.xlf
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit>
+ <source>foo</source>
+ <target>bar</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.yml b/public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.yml
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/non-valid.yml
@@ -0,0 +1 @@
+foo
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.mo b/public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.mo
new file mode 100644
index 0000000..6445e77
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.mo
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.po
new file mode 100644
index 0000000..439c41a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/plurals.po
@@ -0,0 +1,5 @@
+msgid "foo"
+msgid_plural "foos"
+msgstr[0] "bar"
+msgstr[1] "bars"
+
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resname.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resname.xlf
new file mode 100644
index 0000000..2df16af
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resname.xlf
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1" resname="foo">
+ <source></source>
+ <target>bar</target>
+ </trans-unit>
+ <trans-unit id="2" resname="bar">
+ <source>bar source</source>
+ <target>baz</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>baz</source>
+ <target>foo</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat
new file mode 100644
index 0000000..391250c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat
@@ -0,0 +1 @@
+XXX \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.res b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.res
new file mode 100644
index 0000000..1fc1436
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.res
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt
new file mode 100644
index 0000000..3d9e9ea
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt
@@ -0,0 +1,3 @@
+en{
+ symfony{"Symfony is great"}
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.res b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.res
new file mode 100644
index 0000000..f584160
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.res
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt
new file mode 100644
index 0000000..182d0a0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt
@@ -0,0 +1,3 @@
+fr{
+ symfony{"Symfony est génial"}
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt
new file mode 100644
index 0000000..c5783ed
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt
@@ -0,0 +1,2 @@
+en.res
+fr.res
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat
new file mode 100644
index 0000000..563b0ea
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res
new file mode 100644
index 0000000..ad894a9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf
new file mode 100644
index 0000000..2efa155
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="fr-FR" trgLang="en-US">
+ <file id="messages.en_US">
+ <unit id="acbd18db4cc2f85cedef654fccc4a4d8">
+ <segment>
+ <source>foo</source>
+ <target>bar</target>
+ </segment>
+ </unit>
+ <unit id="3c6e0b8a9c15224a8228b9a98ca1531d">
+ <segment>
+ <source>key</source>
+ <target order="1"></target>
+ </segment>
+ </unit>
+ <unit id="18e6a493872558d949b4c16ea1fa6ab6">
+ <segment>
+ <source>key.with.cdata</source>
+ <target><![CDATA[<source> & <target>]]></target>
+ </segment>
+ </unit>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf
new file mode 100644
index 0000000..166172a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf
@@ -0,0 +1,25 @@
+<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en-US" trgLang="ja-JP">
+ <file id="f1" original="Graphic Example.psd">
+ <skeleton href="Graphic Example.psd.skl"/>
+ <unit id="1">
+ <segment>
+ <source>Quetzal</source>
+ <target>Quetzal</target>
+ </segment>
+ </unit>
+ <group id="1">
+ <unit id="2">
+ <segment>
+ <source>foo</source>
+ <target>XLIFF 文書を編集、または処理 するアプリケーションです。</target>
+ </segment>
+ </unit>
+ <unit id="3">
+ <segment>
+ <source>bar</source>
+ <target order="1">XLIFF データ・マネージャ</target>
+ </segment>
+ </unit>
+ </group>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf
new file mode 100644
index 0000000..436e19e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="fr-FR" target-language="en-US" datatype="plaintext" original="file.ext">
+ <header>
+ <tool tool-id="symfony" tool-name="Symfony"/>
+ </header>
+ <body>
+ <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
+ <source>foo</source>
+ <target>bar</target>
+ <note priority="1" from="bar">baz</note>
+ </trans-unit>
+ <trans-unit id="3c6e0b8a9c15224a8228b9a98ca1531d" resname="key">
+ <source>key</source>
+ <target></target>
+ <note>baz</note>
+ <note>qux</note>
+ </trans-unit>
+ <trans-unit id="18e6a493872558d949b4c16ea1fa6ab6" resname="key.with.cdata">
+ <source>key.with.cdata</source>
+ <target><![CDATA[<source> & <target>]]></target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf
new file mode 100644
index 0000000..e3afb49
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="fr-FR" target-language="en-US" datatype="plaintext" original="file.ext">
+ <header>
+ <tool tool-id="symfony" tool-name="Symfony"/>
+ </header>
+ <body>
+ <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
+ <source>foo</source>
+ <target state="needs-translation">bar</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf
new file mode 100644
index 0000000..1ed06d2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en-US" target-language="en-US" datatype="plaintext" original="file.ext">
+ <header>
+ <tool tool-id="foo" tool-name="foo" tool-version="0.0" tool-company="Foo"/>
+ </header>
+ <body>
+ <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
+ <source>foo</source>
+ <target>bar</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.csv b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.csv
new file mode 100644
index 0000000..374b9eb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.csv
@@ -0,0 +1,4 @@
+"foo"; "bar"
+#"bar"; "foo"
+"incorrect"; "number"; "columns"; "will"; "be"; "ignored"
+"incorrect" \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.dump.json b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.dump.json
new file mode 100644
index 0000000..335965d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.dump.json
@@ -0,0 +1 @@
+{"foo":"\u0022bar\u0022"} \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ini b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ini
new file mode 100644
index 0000000..4953062
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ini
@@ -0,0 +1 @@
+foo="bar"
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.json b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.json
new file mode 100644
index 0000000..8a79687
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.json
@@ -0,0 +1,3 @@
+{
+ "foo": "bar"
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.mo b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.mo
new file mode 100644
index 0000000..0a96602
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.mo
Binary files differ
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.php b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.php
new file mode 100644
index 0000000..c291398
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.php
@@ -0,0 +1,5 @@
+<?php
+
+return array (
+ 'foo' => 'bar',
+);
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.po b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.po
new file mode 100644
index 0000000..ccfce6b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.po
@@ -0,0 +1,8 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+
+msgid "foo"
+msgstr "bar" \ No newline at end of file
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ts b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ts
new file mode 100644
index 0000000..40e1852
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.ts
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TS>
+ <context>
+ <name>resources</name>
+ <message>
+ <source>foo</source>
+ <translation>bar</translation>
+ </message>
+ </context>
+</TS>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.xlf
new file mode 100644
index 0000000..b0e5988
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.xlf
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>foo</source>
+ <target>bar</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>extra</source>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>key</source>
+ <target></target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>test</source>
+ <target>with</target>
+ <note>note</note>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.yml b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.yml
new file mode 100644
index 0000000..20e9ff3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/resources.yml
@@ -0,0 +1 @@
+foo: bar
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/valid.csv b/public/system/storage/vendor/symfony/translation/Tests/fixtures/valid.csv
new file mode 100644
index 0000000..59882e5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/valid.csv
@@ -0,0 +1,4 @@
+foo;bar
+bar;"foo
+foo"
+"foo;foo";bar
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf
new file mode 100644
index 0000000..7873062
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>foo</source>
+ <target state="translated">bar</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>extra</source>
+ <target state="needs-translation">bar</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>key</source>
+ <target></target>
+ <note>baz</note>
+ <note priority="2" from="bar">qux</note>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf
new file mode 100644
index 0000000..f83e834
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE foo>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>foo</source>
+ <target>bar</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Tests/fixtures/withnote.xlf b/public/system/storage/vendor/symfony/translation/Tests/fixtures/withnote.xlf
new file mode 100644
index 0000000..b1d3f83
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Tests/fixtures/withnote.xlf
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>foo</source>
+ <target>bar</target>
+ <note priority="1">foo</note>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>extra</source>
+ <note from="foo">bar</note>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>key</source>
+ <target></target>
+ <note>baz</note>
+ <note priority="2" from="bar">qux</note>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/translation/Translator.php b/public/system/storage/vendor/symfony/translation/Translator.php
new file mode 100644
index 0000000..309a2b8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Translator.php
@@ -0,0 +1,441 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Config\ConfigCacheInterface;
+use Symfony\Component\Config\ConfigCacheFactoryInterface;
+use Symfony\Component\Config\ConfigCacheFactory;
+
+/**
+ * Translator.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Translator implements TranslatorInterface, TranslatorBagInterface
+{
+ /**
+ * @var MessageCatalogueInterface[]
+ */
+ protected $catalogues = array();
+
+ /**
+ * @var string
+ */
+ private $locale;
+
+ /**
+ * @var array
+ */
+ private $fallbackLocales = array();
+
+ /**
+ * @var LoaderInterface[]
+ */
+ private $loaders = array();
+
+ /**
+ * @var array
+ */
+ private $resources = array();
+
+ /**
+ * @var MessageSelector
+ */
+ private $selector;
+
+ /**
+ * @var string
+ */
+ private $cacheDir;
+
+ /**
+ * @var bool
+ */
+ private $debug;
+
+ /**
+ * @var ConfigCacheFactoryInterface|null
+ */
+ private $configCacheFactory;
+
+ /**
+ * Constructor.
+ *
+ * @param string $locale The locale
+ * @param MessageSelector|null $selector The message selector for pluralization
+ * @param string|null $cacheDir The directory to use for the cache
+ * @param bool $debug Use cache in debug mode ?
+ *
+ * @throws \InvalidArgumentException If a locale contains invalid characters
+ */
+ public function __construct($locale, MessageSelector $selector = null, $cacheDir = null, $debug = false)
+ {
+ $this->setLocale($locale);
+ $this->selector = $selector ?: new MessageSelector();
+ $this->cacheDir = $cacheDir;
+ $this->debug = $debug;
+ }
+
+ /**
+ * Sets the ConfigCache factory to use.
+ *
+ * @param ConfigCacheFactoryInterface $configCacheFactory
+ */
+ public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
+ {
+ $this->configCacheFactory = $configCacheFactory;
+ }
+
+ /**
+ * Adds a Loader.
+ *
+ * @param string $format The name of the loader (@see addResource())
+ * @param LoaderInterface $loader A LoaderInterface instance
+ */
+ public function addLoader($format, LoaderInterface $loader)
+ {
+ $this->loaders[$format] = $loader;
+ }
+
+ /**
+ * Adds a Resource.
+ *
+ * @param string $format The name of the loader (@see addLoader())
+ * @param mixed $resource The resource name
+ * @param string $locale The locale
+ * @param string $domain The domain
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function addResource($format, $resource, $locale, $domain = null)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $this->assertValidLocale($locale);
+
+ $this->resources[$locale][] = array($format, $resource, $domain);
+
+ if (in_array($locale, $this->fallbackLocales)) {
+ $this->catalogues = array();
+ } else {
+ unset($this->catalogues[$locale]);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->assertValidLocale($locale);
+ $this->locale = $locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * Sets the fallback locales.
+ *
+ * @param array $locales The fallback locales
+ *
+ * @throws \InvalidArgumentException If a locale contains invalid characters
+ */
+ public function setFallbackLocales(array $locales)
+ {
+ // needed as the fallback locales are linked to the already loaded catalogues
+ $this->catalogues = array();
+
+ foreach ($locales as $locale) {
+ $this->assertValidLocale($locale);
+ }
+
+ $this->fallbackLocales = $locales;
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @return array $locales The fallback locales
+ */
+ public function getFallbackLocales()
+ {
+ return $this->fallbackLocales;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ return strtr($this->getCatalogue($locale)->get((string) $id, $domain), $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $id = (string) $id;
+ $catalogue = $this->getCatalogue($locale);
+ $locale = $catalogue->getLocale();
+ while (!$catalogue->defines($id, $domain)) {
+ if ($cat = $catalogue->getFallbackCatalogue()) {
+ $catalogue = $cat;
+ $locale = $catalogue->getLocale();
+ } else {
+ break;
+ }
+ }
+
+ return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue($locale = null)
+ {
+ if (null === $locale) {
+ $locale = $this->getLocale();
+ } else {
+ $this->assertValidLocale($locale);
+ }
+
+ if (!isset($this->catalogues[$locale])) {
+ $this->loadCatalogue($locale);
+ }
+
+ return $this->catalogues[$locale];
+ }
+
+ /**
+ * Gets the loaders.
+ *
+ * @return array LoaderInterface[]
+ */
+ protected function getLoaders()
+ {
+ return $this->loaders;
+ }
+
+ /**
+ * @param string $locale
+ */
+ protected function loadCatalogue($locale)
+ {
+ if (null === $this->cacheDir) {
+ $this->initializeCatalogue($locale);
+ } else {
+ $this->initializeCacheCatalogue($locale);
+ }
+ }
+
+ /**
+ * @param string $locale
+ */
+ protected function initializeCatalogue($locale)
+ {
+ $this->assertValidLocale($locale);
+
+ try {
+ $this->doLoadCatalogue($locale);
+ } catch (NotFoundResourceException $e) {
+ if (!$this->computeFallbackLocales($locale)) {
+ throw $e;
+ }
+ }
+ $this->loadFallbackCatalogues($locale);
+ }
+
+ /**
+ * @param string $locale
+ */
+ private function initializeCacheCatalogue($locale)
+ {
+ if (isset($this->catalogues[$locale])) {
+ /* Catalogue already initialized. */
+ return;
+ }
+
+ $this->assertValidLocale($locale);
+ $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
+ function (ConfigCacheInterface $cache) use ($locale) {
+ $this->dumpCatalogue($locale, $cache);
+ }
+ );
+
+ if (isset($this->catalogues[$locale])) {
+ /* Catalogue has been initialized as it was written out to cache. */
+ return;
+ }
+
+ /* Read catalogue from cache. */
+ $this->catalogues[$locale] = include $cache->getPath();
+ }
+
+ private function dumpCatalogue($locale, ConfigCacheInterface $cache)
+ {
+ $this->initializeCatalogue($locale);
+ $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
+
+ $content = sprintf(<<<EOF
+<?php
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+\$catalogue = new MessageCatalogue('%s', %s);
+
+%s
+return \$catalogue;
+
+EOF
+ ,
+ $locale,
+ var_export($this->catalogues[$locale]->all(), true),
+ $fallbackContent
+ );
+
+ $cache->write($content, $this->catalogues[$locale]->getResources());
+ }
+
+ private function getFallbackContent(MessageCatalogue $catalogue)
+ {
+ $fallbackContent = '';
+ $current = '';
+ $replacementPattern = '/[^a-z0-9_]/i';
+ $fallbackCatalogue = $catalogue->getFallbackCatalogue();
+ while ($fallbackCatalogue) {
+ $fallback = $fallbackCatalogue->getLocale();
+ $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
+ $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
+
+ $fallbackContent .= sprintf(<<<EOF
+\$catalogue%s = new MessageCatalogue('%s', %s);
+\$catalogue%s->addFallbackCatalogue(\$catalogue%s);
+
+EOF
+ ,
+ $fallbackSuffix,
+ $fallback,
+ var_export($fallbackCatalogue->all(), true),
+ $currentSuffix,
+ $fallbackSuffix
+ );
+ $current = $fallbackCatalogue->getLocale();
+ $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
+ }
+
+ return $fallbackContent;
+ }
+
+ private function getCatalogueCachePath($locale)
+ {
+ return $this->cacheDir.'/catalogue.'.$locale.'.'.sha1(serialize($this->fallbackLocales)).'.php';
+ }
+
+ private function doLoadCatalogue($locale)
+ {
+ $this->catalogues[$locale] = new MessageCatalogue($locale);
+
+ if (isset($this->resources[$locale])) {
+ foreach ($this->resources[$locale] as $resource) {
+ if (!isset($this->loaders[$resource[0]])) {
+ throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
+ }
+ $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
+ }
+ }
+ }
+
+ private function loadFallbackCatalogues($locale)
+ {
+ $current = $this->catalogues[$locale];
+
+ foreach ($this->computeFallbackLocales($locale) as $fallback) {
+ if (!isset($this->catalogues[$fallback])) {
+ $this->doLoadCatalogue($fallback);
+ }
+
+ $fallbackCatalogue = new MessageCatalogue($fallback, $this->catalogues[$fallback]->all());
+ foreach ($this->catalogues[$fallback]->getResources() as $resource) {
+ $fallbackCatalogue->addResource($resource);
+ }
+ $current->addFallbackCatalogue($fallbackCatalogue);
+ $current = $fallbackCatalogue;
+ }
+ }
+
+ protected function computeFallbackLocales($locale)
+ {
+ $locales = array();
+ foreach ($this->fallbackLocales as $fallback) {
+ if ($fallback === $locale) {
+ continue;
+ }
+
+ $locales[] = $fallback;
+ }
+
+ if (strrchr($locale, '_') !== false) {
+ array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_'))));
+ }
+
+ return array_unique($locales);
+ }
+
+ /**
+ * Asserts that the locale is valid, throws an Exception if not.
+ *
+ * @param string $locale Locale to tests
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ protected function assertValidLocale($locale)
+ {
+ if (1 !== preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
+ throw new \InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
+ }
+ }
+
+ /**
+ * Provides the ConfigCache factory implementation, falling back to a
+ * default implementation if necessary.
+ *
+ * @return ConfigCacheFactoryInterface $configCacheFactory
+ */
+ private function getConfigCacheFactory()
+ {
+ if (!$this->configCacheFactory) {
+ $this->configCacheFactory = new ConfigCacheFactory($this->debug);
+ }
+
+ return $this->configCacheFactory;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/TranslatorBagInterface.php b/public/system/storage/vendor/symfony/translation/TranslatorBagInterface.php
new file mode 100644
index 0000000..14fbb17
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/TranslatorBagInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * TranslatorBagInterface.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface TranslatorBagInterface
+{
+ /**
+ * Gets the catalogue by locale.
+ *
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return MessageCatalogueInterface
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function getCatalogue($locale = null);
+}
diff --git a/public/system/storage/vendor/symfony/translation/TranslatorInterface.php b/public/system/storage/vendor/symfony/translation/TranslatorInterface.php
new file mode 100644
index 0000000..6916c33
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/TranslatorInterface.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * TranslatorInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface TranslatorInterface
+{
+ /**
+ * Translates the given message.
+ *
+ * @param string $id The message id (may also be an object that can be cast to string)
+ * @param array $parameters An array of parameters for the message
+ * @param string|null $domain The domain for the message or null to use the default
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return string The translated string
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null);
+
+ /**
+ * Translates the given choice message by choosing a translation according to a number.
+ *
+ * @param string $id The message id (may also be an object that can be cast to string)
+ * @param int $number The number to use to find the indice of the message
+ * @param array $parameters An array of parameters for the message
+ * @param string|null $domain The domain for the message or null to use the default
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return string The translated string
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null);
+
+ /**
+ * Sets the current locale.
+ *
+ * @param string $locale The locale
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function setLocale($locale);
+
+ /**
+ * Returns the current locale.
+ *
+ * @return string The locale
+ */
+ public function getLocale();
+}
diff --git a/public/system/storage/vendor/symfony/translation/Util/ArrayConverter.php b/public/system/storage/vendor/symfony/translation/Util/ArrayConverter.php
new file mode 100644
index 0000000..60a55e9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Util/ArrayConverter.php
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Util;
+
+/**
+ * ArrayConverter generates tree like structure from a message catalogue.
+ * e.g. this
+ * 'foo.bar1' => 'test1',
+ * 'foo.bar2' => 'test2'
+ * converts to follows:
+ * foo:
+ * bar1: test1
+ * bar2: test2.
+ *
+ * @author Gennady Telegin <gtelegin@gmail.com>
+ */
+class ArrayConverter
+{
+ /**
+ * Converts linear messages array to tree-like array.
+ * For example this rray('foo.bar' => 'value') will be converted to array('foo' => array('bar' => 'value')).
+ *
+ * @param array $messages Linear messages array
+ *
+ * @return array Tree-like messages array
+ */
+ public static function expandToTree(array $messages)
+ {
+ $tree = array();
+
+ foreach ($messages as $id => $value) {
+ $referenceToElement = &self::getElementByPath($tree, explode('.', $id));
+
+ $referenceToElement = $value;
+
+ unset($referenceToElement);
+ }
+
+ return $tree;
+ }
+
+ private static function &getElementByPath(array &$tree, array $parts)
+ {
+ $elem = &$tree;
+ $parentOfElem = null;
+
+ foreach ($parts as $i => $part) {
+ if (isset($elem[$part]) && is_string($elem[$part])) {
+ /* Process next case:
+ * 'foo': 'test1',
+ * 'foo.bar': 'test2'
+ *
+ * $tree['foo'] was string before we found array {bar: test2}.
+ * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
+ */
+ $elem = &$elem[ implode('.', array_slice($parts, $i)) ];
+ break;
+ }
+ $parentOfElem = &$elem;
+ $elem = &$elem[$part];
+ }
+
+ if (is_array($elem) && count($elem) > 0 && $parentOfElem) {
+ /* Process next case:
+ * 'foo.bar': 'test1'
+ * 'foo': 'test2'
+ *
+ * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
+ * Cancel treating $tree['foo'] as array and cancel back it expansion,
+ * e.g. make it $tree['foo.bar'] = 'test1' again.
+ */
+ self::cancelExpand($parentOfElem, $part, $elem);
+ }
+
+ return $elem;
+ }
+
+ private static function cancelExpand(array &$tree, $prefix, array $node)
+ {
+ $prefix .= '.';
+
+ foreach ($node as $id => $value) {
+ if (is_string($value)) {
+ $tree[$prefix.$id] = $value;
+ } else {
+ self::cancelExpand($tree, $prefix.$id, $value);
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/Writer/TranslationWriter.php b/public/system/storage/vendor/symfony/translation/Writer/TranslationWriter.php
new file mode 100644
index 0000000..2f5eaa1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/Writer/TranslationWriter.php
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Writer;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Dumper\DumperInterface;
+
+/**
+ * TranslationWriter writes translation messages.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class TranslationWriter
+{
+ /**
+ * Dumpers used for export.
+ *
+ * @var array
+ */
+ private $dumpers = array();
+
+ /**
+ * Adds a dumper to the writer.
+ *
+ * @param string $format The format of the dumper
+ * @param DumperInterface $dumper The dumper
+ */
+ public function addDumper($format, DumperInterface $dumper)
+ {
+ $this->dumpers[$format] = $dumper;
+ }
+
+ /**
+ * Disables dumper backup.
+ */
+ public function disableBackup()
+ {
+ foreach ($this->dumpers as $dumper) {
+ if (method_exists($dumper, 'setBackup')) {
+ $dumper->setBackup(false);
+ }
+ }
+ }
+
+ /**
+ * Obtains the list of supported formats.
+ *
+ * @return array
+ */
+ public function getFormats()
+ {
+ return array_keys($this->dumpers);
+ }
+
+ /**
+ * Writes translation from the catalogue according to the selected format.
+ *
+ * @param MessageCatalogue $catalogue The message catalogue to dump
+ * @param string $format The format to use to dump the messages
+ * @param array $options Options that are passed to the dumper
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array())
+ {
+ if (!isset($this->dumpers[$format])) {
+ throw new \InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
+ }
+
+ // get the right dumper
+ $dumper = $this->dumpers[$format];
+
+ if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0777, true) && !is_dir($options['path'])) {
+ throw new \RuntimeException(sprintf('Translation Writer was not able to create directory "%s"', $options['path']));
+ }
+
+ // save
+ $dumper->dump($catalogue, $options);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/composer.json b/public/system/storage/vendor/symfony/translation/composer.json
new file mode 100644
index 0000000..916cd1a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/composer.json
@@ -0,0 +1,48 @@
+{
+ "name": "symfony/translation",
+ "type": "library",
+ "description": "Symfony Translation Component",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.5.9",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "require-dev": {
+ "symfony/config": "~2.8|~3.0",
+ "symfony/intl": "~2.8|~3.0",
+ "symfony/yaml": "~2.8|~3.0",
+ "psr/log": "~1.0"
+ },
+ "conflict": {
+ "symfony/config": "<2.8"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/yaml": "",
+ "psr/log": "To use logging capability in translator"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Translation\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/translation/phpunit.xml.dist b/public/system/storage/vendor/symfony/translation/phpunit.xml.dist
new file mode 100644
index 0000000..c25ec5e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/translation/phpunit.xml.dist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+ backupGlobals="false"
+ colors="true"
+ bootstrap="vendor/autoload.php"
+>
+ <php>
+ <ini name="error_reporting" value="-1" />
+ </php>
+
+ <testsuites>
+ <testsuite name="Symfony Translation Component Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/symfony/validator/.gitignore b/public/system/storage/vendor/symfony/validator/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/public/system/storage/vendor/symfony/validator/CHANGELOG.md b/public/system/storage/vendor/symfony/validator/CHANGELOG.md
new file mode 100644
index 0000000..0ff667b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/CHANGELOG.md
@@ -0,0 +1,175 @@
+CHANGELOG
+=========
+
+2.8.0
+-----
+
+ * added the BIC (SWIFT-Code) validator
+
+2.7.0
+-----
+
+ * deprecated `DefaultTranslator` in favor of `Symfony\Component\Translation\IdentityTranslator`
+ * deprecated PHP7-incompatible constraints (Null, True, False) and related validators (NullValidator, TrueValidator, FalseValidator) in favor of their `Is`-prefixed equivalent
+
+2.6.0
+-----
+
+ * [BC BREAK] `FileValidator` disallow empty files
+ * [BC BREAK] `UserPasswordValidator` source message change
+ * [BC BREAK] added internal `ExecutionContextInterface::setConstraint()`
+ * added `ConstraintViolation::getConstraint()`
+ * [BC BREAK] The `ExpressionValidator` will now evaluate the Expression even when the property value is null or an empty string
+ * deprecated `ClassMetadata::hasMemberMetadatas()`
+ * deprecated `ClassMetadata::getMemberMetadatas()`
+ * deprecated `ClassMetadata::addMemberMetadata()`
+ * [BC BREAK] added `Mapping\MetadataInterface::getConstraints()`
+ * added generic "payload" option to all constraints for attaching domain-specific data
+ * [BC BREAK] added `ConstraintViolationBuilderInterface::setCause()`
+
+2.5.0
+-----
+
+ * deprecated `ApcCache` in favor of `DoctrineCache`
+ * added `DoctrineCache` to adapt any Doctrine cache
+ * `GroupSequence` now implements `ArrayAccess`, `Countable` and `Traversable`
+ * [BC BREAK] changed `ClassMetadata::getGroupSequence()` to return a `GroupSequence` instance instead of an array
+ * `Callback` can now be put onto properties (useful when you pass a closure to the constraint)
+ * deprecated `ClassBasedInterface`
+ * deprecated `MetadataInterface`
+ * deprecated `PropertyMetadataInterface`
+ * deprecated `PropertyMetadataContainerInterface`
+ * deprecated `Mapping\ElementMetadata`
+ * added `Mapping\MetadataInterface`
+ * added `Mapping\ClassMetadataInterface`
+ * added `Mapping\PropertyMetadataInterface`
+ * added `Mapping\GenericMetadata`
+ * added `Mapping\CascadingStrategy`
+ * added `Mapping\TraversalStrategy`
+ * deprecated `Mapping\ClassMetadata::accept()`
+ * deprecated `Mapping\MemberMetadata::accept()`
+ * removed array type hint of `Mapping\ClassMetadata::setGroupSequence()`
+ * deprecated `MetadataFactoryInterface`
+ * deprecated `Mapping\BlackholeMetadataFactory`
+ * deprecated `Mapping\ClassMetadataFactory`
+ * added `Mapping\Factory\MetadataFactoryInterface`
+ * added `Mapping\Factory\BlackHoleMetadataFactory`
+ * added `Mapping\Factory\LazyLoadingMetadataFactory`
+ * deprecated `ExecutionContextInterface`
+ * deprecated `ExecutionContext`
+ * deprecated `GlobalExecutionContextInterface`
+ * added `Context\ExecutionContextInterface`
+ * added `Context\ExecutionContext`
+ * added `Context\ExecutionContextFactoryInterface`
+ * added `Context\ExecutionContextFactory`
+ * deprecated `ValidatorInterface`
+ * deprecated `Validator`
+ * deprecated `ValidationVisitorInterface`
+ * deprecated `ValidationVisitor`
+ * added `Validator\ValidatorInterface`
+ * added `Validator\RecursiveValidator`
+ * added `Validator\ContextualValidatorInterface`
+ * added `Validator\RecursiveContextualValidator`
+ * added `Violation\ConstraintViolationBuilderInterface`
+ * added `Violation\ConstraintViolationBuilder`
+ * added `ConstraintViolation::getParameters()`
+ * added `ConstraintViolation::getPlural()`
+ * added `Constraints\Traverse`
+ * deprecated `$deep` property in `Constraints\Valid`
+ * added `ValidatorBuilderInterface::setApiVersion()`
+ * added `Validation::API_VERSION_2_4`
+ * added `Validation::API_VERSION_2_5`
+ * added `Exception\OutOfBoundsException`
+ * added `Exception\UnsupportedMetadataException`
+ * made `Exception\ValidatorException` extend `Exception\RuntimeException`
+ * added `Util\PropertyPath`
+ * made the PropertyAccess component an optional dependency
+ * deprecated `ValidatorBuilder::setPropertyAccessor()`
+ * deprecated `validate` and `validateValue` on `Validator\Context\ExecutionContext` use `getValidator()` together with `inContext()` instead
+
+2.4.0
+-----
+
+ * added a constraint the uses the expression language
+ * added `minRatio`, `maxRatio`, `allowSquare`, `allowLandscape`, and `allowPortrait` to Image validator
+
+2.3.29
+------
+
+ * fixed compatibility with PHP7 and up by introducing new constraints (IsNull, IsTrue, IsFalse) and related validators (IsNullValidator, IsTrueValidator, IsFalseValidator)
+
+2.3.0
+-----
+
+ * added the ISBN, ISSN, and IBAN validators
+ * copied the constraints `Optional` and `Required` to the
+ `Symfony\Component\Validator\Constraints\` namespace and deprecated the original
+ classes.
+ * added comparison validators (EqualTo, NotEqualTo, LessThan, LessThanOrEqualTo, GreaterThan, GreaterThanOrEqualTo, IdenticalTo, NotIdenticalTo)
+
+2.2.0
+-----
+
+ * added a CardScheme validator
+ * added a Luhn validator
+ * moved @api-tags from `Validator` to `ValidatorInterface`
+ * moved @api-tags from `ConstraintViolation` to the new `ConstraintViolationInterface`
+ * moved @api-tags from `ConstraintViolationList` to the new `ConstraintViolationListInterface`
+ * moved @api-tags from `ExecutionContext` to the new `ExecutionContextInterface`
+ * [BC BREAK] `ConstraintValidatorInterface::initialize` is now type hinted against `ExecutionContextInterface` instead of `ExecutionContext`
+ * [BC BREAK] changed the visibility of the properties in `Validator` from protected to private
+ * deprecated `ClassMetadataFactoryInterface` in favor of the new `MetadataFactoryInterface`
+ * deprecated `ClassMetadataFactory::getClassMetadata` in favor of `getMetadataFor`
+ * created `MetadataInterface`, `PropertyMetadataInterface`, `ClassBasedInterface` and `PropertyMetadataContainerInterface`
+ * deprecated `GraphWalker` in favor of the new `ValidationVisitorInterface`
+ * deprecated `ExecutionContext::addViolationAtPath`
+ * deprecated `ExecutionContext::addViolationAtSubPath` in favor of `ExecutionContextInterface::addViolationAt`
+ * deprecated `ExecutionContext::getCurrentClass` in favor of `ExecutionContextInterface::getClassName`
+ * deprecated `ExecutionContext::getCurrentProperty` in favor of `ExecutionContextInterface::getPropertyName`
+ * deprecated `ExecutionContext::getCurrentValue` in favor of `ExecutionContextInterface::getValue`
+ * deprecated `ExecutionContext::getGraphWalker` in favor of `ExecutionContextInterface::validate` and `ExecutionContextInterface::validateValue`
+ * improved `ValidatorInterface::validateValue` to accept arrays of constraints
+ * changed `ValidatorInterface::getMetadataFactory` to return a `MetadataFactoryInterface` instead of a `ClassMetadataFactoryInterface`
+ * removed `ClassMetadataFactoryInterface` type hint from `ValidatorBuilderInterface::setMetadataFactory`.
+ As of Symfony 2.3, this method will be typed against `MetadataFactoryInterface` instead.
+ * [BC BREAK] the switches `traverse` and `deep` in the `Valid` constraint and in `GraphWalker::walkReference`
+ are ignored for arrays now. Arrays are always traversed recursively.
+ * added dependency to Translation component
+ * violation messages are now translated with a TranslatorInterface implementation
+ * [BC BREAK] inserted argument `$message` in the constructor of `ConstraintViolation`
+ * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `ExecutionContext`
+ * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `GraphWalker`
+ * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `ValidationVisitor`
+ * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `Validator`
+ * [BC BREAK] added `setTranslator()` and `setTranslationDomain()` to `ValidatorBuilderInterface`
+ * improved the Validator to support pluralized messages by default
+ * [BC BREAK] changed the source of all pluralized messages in the translation files to the pluralized version
+ * added ExceptionInterface, BadMethodCallException and InvalidArgumentException
+
+2.1.0
+-----
+
+ * added support for `ctype_*` assertions in `TypeValidator`
+ * improved the ImageValidator with min width, max width, min height, and max height constraints
+ * added support for MIME with wildcard in FileValidator
+ * changed Collection validator to add "missing" and "extra" errors to
+ individual fields
+ * changed default value for `extraFieldsMessage` and `missingFieldsMessage`
+ in Collection constraint
+ * made ExecutionContext immutable
+ * deprecated Constraint methods `setMessage`, `getMessageTemplate` and
+ `getMessageParameters`
+ * added support for dynamic group sequences with the GroupSequenceProvider pattern
+ * [BC BREAK] ConstraintValidatorInterface method `isValid` has been renamed to
+ `validate`, its return value was dropped. ConstraintValidator still contains
+ `isValid` for BC
+ * [BC BREAK] collections in fields annotated with `Valid` are not traversed
+ recursively anymore by default. `Valid` contains a new property `deep`
+ which enables the BC behavior.
+ * added Count constraint
+ * added Length constraint
+ * added Range constraint
+ * deprecated the Min and Max constraints
+ * deprecated the MinLength and MaxLength constraints
+ * added Validation and ValidatorBuilderInterface
+ * deprecated ValidatorContext, ValidatorContextInterface and ValidatorFactory
diff --git a/public/system/storage/vendor/symfony/validator/ClassBasedInterface.php b/public/system/storage/vendor/symfony/validator/ClassBasedInterface.php
new file mode 100644
index 0000000..c57da27
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ClassBasedInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * An object backed by a PHP class.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Mapping\ClassMetadataInterface} instead.
+ */
+interface ClassBasedInterface
+{
+ /**
+ * Returns the name of the backing PHP class.
+ *
+ * @return string The name of the backing class
+ */
+ public function getClassName();
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraint.php b/public/system/storage/vendor/symfony/validator/Constraint.php
new file mode 100644
index 0000000..45d4bcf
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraint.php
@@ -0,0 +1,298 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\InvalidArgumentException;
+use Symfony\Component\Validator\Exception\InvalidOptionsException;
+use Symfony\Component\Validator\Exception\MissingOptionsException;
+
+/**
+ * Contains the properties of a constraint definition.
+ *
+ * A constraint can be defined on a class, a property or a getter method.
+ * The Constraint class encapsulates all the configuration required for
+ * validating this class, property or getter result successfully.
+ *
+ * Constraint instances are immutable and serializable.
+ *
+ * @property array $groups The groups that the constraint belongs to
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class Constraint
+{
+ /**
+ * The name of the group given to all constraints with no explicit group.
+ */
+ const DEFAULT_GROUP = 'Default';
+
+ /**
+ * Marks a constraint that can be put onto classes.
+ */
+ const CLASS_CONSTRAINT = 'class';
+
+ /**
+ * Marks a constraint that can be put onto properties.
+ */
+ const PROPERTY_CONSTRAINT = 'property';
+
+ /**
+ * Maps error codes to the names of their constants.
+ */
+ protected static $errorNames = array();
+
+ /**
+ * Domain-specific data attached to a constraint.
+ *
+ * @var mixed
+ */
+ public $payload;
+
+ /**
+ * Returns the name of the given error code.
+ *
+ * @param string $errorCode The error code
+ *
+ * @return string The name of the error code
+ *
+ * @throws InvalidArgumentException If the error code does not exist
+ */
+ public static function getErrorName($errorCode)
+ {
+ if (!isset(static::$errorNames[$errorCode])) {
+ throw new InvalidArgumentException(sprintf('The error code "%s" does not exist for constraint of type "%s".', $errorCode, \get_called_class()));
+ }
+
+ return static::$errorNames[$errorCode];
+ }
+
+ /**
+ * Initializes the constraint with options.
+ *
+ * You should pass an associative array. The keys should be the names of
+ * existing properties in this class. The values should be the value for these
+ * properties.
+ *
+ * Alternatively you can override the method getDefaultOption() to return the
+ * name of an existing property. If no associative array is passed, this
+ * property is set instead.
+ *
+ * You can force that certain options are set by overriding
+ * getRequiredOptions() to return the names of these options. If any
+ * option is not set here, an exception is thrown.
+ *
+ * @param mixed $options The options (as associative array)
+ * or the value for the default
+ * option (any other type)
+ *
+ * @throws InvalidOptionsException When you pass the names of non-existing
+ * options
+ * @throws MissingOptionsException When you don't pass any of the options
+ * returned by getRequiredOptions()
+ * @throws ConstraintDefinitionException When you don't pass an associative
+ * array, but getDefaultOption() returns
+ * null
+ */
+ public function __construct($options = null)
+ {
+ $invalidOptions = array();
+ $missingOptions = array_flip((array) $this->getRequiredOptions());
+ $knownOptions = get_object_vars($this);
+
+ // The "groups" option is added to the object lazily
+ $knownOptions['groups'] = true;
+
+ if (\is_array($options) && \count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) {
+ $options[$this->getDefaultOption()] = $options['value'];
+ unset($options['value']);
+ }
+
+ if (\is_array($options)) {
+ reset($options);
+ }
+ if (\is_array($options) && \count($options) > 0 && \is_string(key($options))) {
+ foreach ($options as $option => $value) {
+ if (array_key_exists($option, $knownOptions)) {
+ $this->$option = $value;
+ unset($missingOptions[$option]);
+ } else {
+ $invalidOptions[] = $option;
+ }
+ }
+ } elseif (null !== $options && !(\is_array($options) && 0 === \count($options))) {
+ $option = $this->getDefaultOption();
+
+ if (null === $option) {
+ throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint %s', \get_class($this)));
+ }
+
+ if (array_key_exists($option, $knownOptions)) {
+ $this->$option = $options;
+ unset($missingOptions[$option]);
+ } else {
+ $invalidOptions[] = $option;
+ }
+ }
+
+ if (\count($invalidOptions) > 0) {
+ throw new InvalidOptionsException(sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), \get_class($this)), $invalidOptions);
+ }
+
+ if (\count($missingOptions) > 0) {
+ throw new MissingOptionsException(sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), \get_class($this)), array_keys($missingOptions));
+ }
+ }
+
+ /**
+ * Sets the value of a lazily initialized option.
+ *
+ * Corresponding properties are added to the object on first access. Hence
+ * this method will be called at most once per constraint instance and
+ * option name.
+ *
+ * @param string $option The option name
+ * @param mixed $value The value to set
+ *
+ * @throws InvalidOptionsException If an invalid option name is given
+ */
+ public function __set($option, $value)
+ {
+ if ('groups' === $option) {
+ $this->groups = (array) $value;
+
+ return;
+ }
+
+ throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, \get_class($this)), array($option));
+ }
+
+ /**
+ * Returns the value of a lazily initialized option.
+ *
+ * Corresponding properties are added to the object on first access. Hence
+ * this method will be called at most once per constraint instance and
+ * option name.
+ *
+ * @param string $option The option name
+ *
+ * @return mixed The value of the option
+ *
+ * @throws InvalidOptionsException If an invalid option name is given
+ *
+ * @internal this method should not be used or overwritten in userland code
+ */
+ public function __get($option)
+ {
+ if ('groups' === $option) {
+ $this->groups = array(self::DEFAULT_GROUP);
+
+ return $this->groups;
+ }
+
+ throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, \get_class($this)), array($option));
+ }
+
+ /**
+ * @param string $option The option name
+ *
+ * @return bool
+ */
+ public function __isset($option)
+ {
+ return 'groups' === $option;
+ }
+
+ /**
+ * Adds the given group if this constraint is in the Default group.
+ *
+ * @param string $group
+ */
+ public function addImplicitGroupName($group)
+ {
+ if (\in_array(self::DEFAULT_GROUP, $this->groups) && !\in_array($group, $this->groups)) {
+ $this->groups[] = $group;
+ }
+ }
+
+ /**
+ * Returns the name of the default option.
+ *
+ * Override this method to define a default option.
+ *
+ * @return string
+ *
+ * @see __construct()
+ */
+ public function getDefaultOption()
+ {
+ }
+
+ /**
+ * Returns the name of the required options.
+ *
+ * Override this method if you want to define required options.
+ *
+ * @return array
+ *
+ * @see __construct()
+ */
+ public function getRequiredOptions()
+ {
+ return array();
+ }
+
+ /**
+ * Returns the name of the class that validates this constraint.
+ *
+ * By default, this is the fully qualified name of the constraint class
+ * suffixed with "Validator". You can override this method to change that
+ * behaviour.
+ *
+ * @return string
+ */
+ public function validatedBy()
+ {
+ return \get_class($this).'Validator';
+ }
+
+ /**
+ * Returns whether the constraint can be put onto classes, properties or
+ * both.
+ *
+ * This method should return one or more of the constants
+ * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT.
+ *
+ * @return string|array One or more constant values
+ */
+ public function getTargets()
+ {
+ return self::PROPERTY_CONSTRAINT;
+ }
+
+ /**
+ * Optimizes the serialized value to minimize storage space.
+ *
+ * @return array The properties to serialize
+ *
+ * @internal This method may be replaced by an implementation of
+ * {@link \Serializable} in the future. Please don't use or
+ * overwrite it.
+ */
+ public function __sleep()
+ {
+ // Initialize "groups" option if it is not set
+ $this->groups;
+
+ return array_keys(get_object_vars($this));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintValidator.php b/public/system/storage/vendor/symfony/validator/ConstraintValidator.php
new file mode 100644
index 0000000..6f8c05a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintValidator.php
@@ -0,0 +1,214 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+use Symfony\Component\Validator\Context\ExecutionContextInterface as ExecutionContextInterface2Dot5;
+use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
+use Symfony\Component\Validator\Violation\LegacyConstraintViolationBuilder;
+
+/**
+ * Base class for constraint validators.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class ConstraintValidator implements ConstraintValidatorInterface
+{
+ /**
+ * Whether to format {@link \DateTime} objects as RFC-3339 dates
+ * ("Y-m-d H:i:s").
+ */
+ const PRETTY_DATE = 1;
+
+ /**
+ * Whether to cast objects with a "__toString()" method to strings.
+ */
+ const OBJECT_TO_STRING = 2;
+
+ /**
+ * @var ExecutionContextInterface2Dot5
+ */
+ protected $context;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function initialize(ExecutionContextInterface $context)
+ {
+ $this->context = $context;
+ }
+
+ /**
+ * Wrapper for {@link ExecutionContextInterface::buildViolation} that
+ * supports the 2.4 context API.
+ *
+ * @param string $message The violation message
+ * @param array $parameters The message parameters
+ *
+ * @return ConstraintViolationBuilderInterface The violation builder
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ protected function buildViolation($message, array $parameters = array())
+ {
+ @trigger_error('The '.__METHOD__.' is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ if ($this->context instanceof ExecutionContextInterface2Dot5) {
+ return $this->context->buildViolation($message, $parameters);
+ }
+
+ return new LegacyConstraintViolationBuilder($this->context, $message, $parameters);
+ }
+
+ /**
+ * Wrapper for {@link ExecutionContextInterface::buildViolation} that
+ * supports the 2.4 context API.
+ *
+ * @param ExecutionContextInterface $context The context to use
+ * @param string $message The violation message
+ * @param array $parameters The message parameters
+ *
+ * @return ConstraintViolationBuilderInterface The violation builder
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ protected function buildViolationInContext(ExecutionContextInterface $context, $message, array $parameters = array())
+ {
+ @trigger_error('The '.__METHOD__.' is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ if ($context instanceof ExecutionContextInterface2Dot5) {
+ return $context->buildViolation($message, $parameters);
+ }
+
+ return new LegacyConstraintViolationBuilder($context, $message, $parameters);
+ }
+
+ /**
+ * Returns a string representation of the type of the value.
+ *
+ * This method should be used if you pass the type of a value as
+ * message parameter to a constraint violation. Note that such
+ * parameters should usually not be included in messages aimed at
+ * non-technical people.
+ *
+ * @param mixed $value The value to return the type of
+ *
+ * @return string The type of the value
+ */
+ protected function formatTypeOf($value)
+ {
+ return \is_object($value) ? \get_class($value) : \gettype($value);
+ }
+
+ /**
+ * Returns a string representation of the value.
+ *
+ * This method returns the equivalent PHP tokens for most scalar types
+ * (i.e. "false" for false, "1" for 1 etc.). Strings are always wrapped
+ * in double quotes ("). Objects, arrays and resources are formatted as
+ * "object", "array" and "resource". If the $format bitmask contains
+ * the PRETTY_DATE bit, then {@link \DateTime} objects will be formatted
+ * as RFC-3339 dates ("Y-m-d H:i:s").
+ *
+ * Be careful when passing message parameters to a constraint violation
+ * that (may) contain objects, arrays or resources. These parameters
+ * should only be displayed for technical users. Non-technical users
+ * won't know what an "object", "array" or "resource" is and will be
+ * confused by the violation message.
+ *
+ * @param mixed $value The value to format as string
+ * @param int $format A bitwise combination of the format
+ * constants in this class
+ *
+ * @return string The string representation of the passed value
+ */
+ protected function formatValue($value, $format = 0)
+ {
+ $isDateTime = $value instanceof \DateTime || $value instanceof \DateTimeInterface;
+
+ if (($format & self::PRETTY_DATE) && $isDateTime) {
+ if (class_exists('IntlDateFormatter')) {
+ $locale = \Locale::getDefault();
+ $formatter = new \IntlDateFormatter($locale, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT);
+
+ // neither the native nor the stub IntlDateFormatter support
+ // DateTimeImmutable as of yet
+ if (!$value instanceof \DateTime) {
+ $value = new \DateTime(
+ $value->format('Y-m-d H:i:s.u e'),
+ $value->getTimezone()
+ );
+ }
+
+ return $formatter->format($value);
+ }
+
+ return $value->format('Y-m-d H:i:s');
+ }
+
+ if (\is_object($value)) {
+ if (($format & self::OBJECT_TO_STRING) && method_exists($value, '__toString')) {
+ return $value->__toString();
+ }
+
+ return 'object';
+ }
+
+ if (\is_array($value)) {
+ return 'array';
+ }
+
+ if (\is_string($value)) {
+ return '"'.$value.'"';
+ }
+
+ if (\is_resource($value)) {
+ return 'resource';
+ }
+
+ if (null === $value) {
+ return 'null';
+ }
+
+ if (false === $value) {
+ return 'false';
+ }
+
+ if (true === $value) {
+ return 'true';
+ }
+
+ return (string) $value;
+ }
+
+ /**
+ * Returns a string representation of a list of values.
+ *
+ * Each of the values is converted to a string using
+ * {@link formatValue()}. The values are then concatenated with commas.
+ *
+ * @param array $values A list of values
+ * @param int $format A bitwise combination of the format
+ * constants in this class
+ *
+ * @return string The string representation of the value list
+ *
+ * @see formatValue()
+ */
+ protected function formatValues(array $values, $format = 0)
+ {
+ foreach ($values as $key => $value) {
+ $values[$key] = $this->formatValue($value, $format);
+ }
+
+ return implode(', ', $values);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintValidatorFactory.php b/public/system/storage/vendor/symfony/validator/ConstraintValidatorFactory.php
new file mode 100644
index 0000000..cc6981b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintValidatorFactory.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+use Symfony\Component\Validator\Constraints\ExpressionValidator;
+
+/**
+ * Default implementation of the ConstraintValidatorFactoryInterface.
+ *
+ * This enforces the convention that the validatedBy() method on any
+ * Constraint will return the class name of the ConstraintValidator that
+ * should validate the Constraint.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
+{
+ protected $validators = array();
+
+ private $propertyAccessor;
+
+ public function __construct($propertyAccessor = null)
+ {
+ $this->propertyAccessor = $propertyAccessor;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getInstance(Constraint $constraint)
+ {
+ $className = $constraint->validatedBy();
+
+ if (!isset($this->validators[$className])) {
+ $this->validators[$className] = 'validator.expression' === $className
+ ? new ExpressionValidator($this->propertyAccessor)
+ : new $className();
+ }
+
+ return $this->validators[$className];
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintValidatorFactoryInterface.php b/public/system/storage/vendor/symfony/validator/ConstraintValidatorFactoryInterface.php
new file mode 100644
index 0000000..b647645
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintValidatorFactoryInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Specifies an object able to return the correct ConstraintValidatorInterface
+ * instance given a Constraint object.
+ */
+interface ConstraintValidatorFactoryInterface
+{
+ /**
+ * Given a Constraint, this returns the ConstraintValidatorInterface
+ * object that should be used to verify its validity.
+ *
+ * @return ConstraintValidatorInterface
+ */
+ public function getInstance(Constraint $constraint);
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintValidatorInterface.php b/public/system/storage/vendor/symfony/validator/ConstraintValidatorInterface.php
new file mode 100644
index 0000000..85fd451
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintValidatorInterface.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ConstraintValidatorInterface
+{
+ /**
+ * Initializes the constraint validator.
+ *
+ * @param ExecutionContextInterface $context The current validation context
+ */
+ public function initialize(ExecutionContextInterface $context);
+
+ /**
+ * Checks if the passed value is valid.
+ *
+ * @param mixed $value The value that should be validated
+ * @param Constraint $constraint The constraint for the validation
+ */
+ public function validate($value, Constraint $constraint);
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintViolation.php b/public/system/storage/vendor/symfony/validator/ConstraintViolation.php
new file mode 100644
index 0000000..804aa2c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintViolation.php
@@ -0,0 +1,204 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Default implementation of {@ConstraintViolationInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ConstraintViolation implements ConstraintViolationInterface
+{
+ private $message;
+ private $messageTemplate;
+ private $parameters;
+ private $plural;
+ private $root;
+ private $propertyPath;
+ private $invalidValue;
+ private $constraint;
+ private $code;
+ private $cause;
+
+ /**
+ * Creates a new constraint violation.
+ *
+ * @param string $message The violation message
+ * @param string $messageTemplate The raw violation message
+ * @param array $parameters The parameters to substitute in the
+ * raw violation message
+ * @param mixed $root The value originally passed to the
+ * validator
+ * @param string $propertyPath The property path from the root
+ * value to the invalid value
+ * @param mixed $invalidValue The invalid value that caused this
+ * violation
+ * @param int|null $plural The number for determining the plural
+ * form when translating the message
+ * @param mixed $code The error code of the violation
+ * @param Constraint|null $constraint The constraint whose validation
+ * caused the violation
+ * @param mixed $cause The cause of the violation
+ */
+ public function __construct($message, $messageTemplate, array $parameters, $root, $propertyPath, $invalidValue, $plural = null, $code = null, Constraint $constraint = null, $cause = null)
+ {
+ $this->message = $message;
+ $this->messageTemplate = $messageTemplate;
+ $this->parameters = $parameters;
+ $this->plural = $plural;
+ $this->root = $root;
+ $this->propertyPath = $propertyPath;
+ $this->invalidValue = $invalidValue;
+ $this->constraint = $constraint;
+ $this->code = $code;
+ $this->cause = $cause;
+ }
+
+ /**
+ * Converts the violation into a string for debugging purposes.
+ *
+ * @return string The violation as string
+ */
+ public function __toString()
+ {
+ if (\is_object($this->root)) {
+ $class = 'Object('.\get_class($this->root).')';
+ } elseif (\is_array($this->root)) {
+ $class = 'Array';
+ } else {
+ $class = (string) $this->root;
+ }
+
+ $propertyPath = (string) $this->propertyPath;
+ $code = $this->code;
+
+ if ('' !== $propertyPath && '[' !== $propertyPath[0] && '' !== $class) {
+ $class .= '.';
+ }
+
+ if (!empty($code)) {
+ $code = ' (code '.$code.')';
+ }
+
+ return $class.$propertyPath.":\n ".$this->getMessage().$code;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessageTemplate()
+ {
+ return $this->messageTemplate;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @deprecated since version 2.7, to be removed in 3.0.
+ * Use getParameters() instead
+ */
+ public function getMessageParameters()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7, to be removed in 3.0. Use the ConstraintViolation::getParameters() method instead.', E_USER_DEPRECATED);
+
+ return $this->parameters;
+ }
+
+ /**
+ * Alias of {@link getMessageParameters()}.
+ */
+ public function getParameters()
+ {
+ return $this->parameters;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @deprecated since version 2.7, to be removed in 3.0.
+ * Use getPlural() instead
+ */
+ public function getMessagePluralization()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7, to be removed in 3.0. Use the ConstraintViolation::getPlural() method instead.', E_USER_DEPRECATED);
+
+ return $this->plural;
+ }
+
+ /**
+ * Alias of {@link getMessagePluralization()}.
+ */
+ public function getPlural()
+ {
+ return $this->plural;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyPath()
+ {
+ return $this->propertyPath;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getInvalidValue()
+ {
+ return $this->invalidValue;
+ }
+
+ /**
+ * Returns the constraint whose validation caused the violation.
+ *
+ * @return Constraint|null The constraint or null if it is not known
+ */
+ public function getConstraint()
+ {
+ return $this->constraint;
+ }
+
+ /**
+ * Returns the cause of the violation.
+ *
+ * @return mixed
+ */
+ public function getCause()
+ {
+ return $this->cause;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCode()
+ {
+ return $this->code;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintViolationInterface.php b/public/system/storage/vendor/symfony/validator/ConstraintViolationInterface.php
new file mode 100644
index 0000000..0ab53b0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintViolationInterface.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * A violation of a constraint that happened during validation.
+ *
+ * For each constraint that fails during validation one or more violations are
+ * created. The violations store the violation message, the path to the failing
+ * element in the validation graph and the root element that was originally
+ * passed to the validator. For example, take the following graph:
+ *
+ * (Person)---(firstName: string)
+ * \
+ * (address: Address)---(street: string)
+ *
+ * If the <tt>Person</tt> object is validated and validation fails for the
+ * "firstName" property, the generated violation has the <tt>Person</tt>
+ * instance as root and the property path "firstName". If validation fails
+ * for the "street" property of the related <tt>Address</tt> instance, the root
+ * element is still the person, but the property path is "address.street".
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ConstraintViolationInterface
+{
+ /**
+ * Returns the violation message.
+ *
+ * @return string The violation message
+ */
+ public function getMessage();
+
+ /**
+ * Returns the raw violation message.
+ *
+ * The raw violation message contains placeholders for the parameters
+ * returned by {@link getMessageParameters}. Typically you'll pass the
+ * message template and parameters to a translation engine.
+ *
+ * @return string The raw violation message
+ */
+ public function getMessageTemplate();
+
+ /**
+ * Returns the parameters to be inserted into the raw violation message.
+ *
+ * @return array a possibly empty list of parameters indexed by the names
+ * that appear in the message template
+ *
+ * @see getMessageTemplate()
+ * @deprecated since version 2.7, to be replaced by getParameters() in 3.0.
+ */
+ public function getMessageParameters();
+
+ /**
+ * Returns a number for pluralizing the violation message.
+ *
+ * For example, the message template could have different translation based
+ * on a parameter "choices":
+ *
+ * <ul>
+ * <li>Please select exactly one entry. (choices=1)</li>
+ * <li>Please select two entries. (choices=2)</li>
+ * </ul>
+ *
+ * This method returns the value of the parameter for choosing the right
+ * pluralization form (in this case "choices").
+ *
+ * @return int|null The number to use to pluralize of the message
+ *
+ * @deprecated since version 2.7, to be replaced by getPlural() in 3.0.
+ */
+ public function getMessagePluralization();
+
+ /**
+ * Returns the root element of the validation.
+ *
+ * @return mixed The value that was passed originally to the validator when
+ * the validation was started. Because the validator traverses
+ * the object graph, the value at which the violation occurs
+ * is not necessarily the value that was originally validated.
+ */
+ public function getRoot();
+
+ /**
+ * Returns the property path from the root element to the violation.
+ *
+ * @return string The property path indicates how the validator reached
+ * the invalid value from the root element. If the root
+ * element is a <tt>Person</tt> instance with a property
+ * "address" that contains an <tt>Address</tt> instance
+ * with an invalid property "street", the generated property
+ * path is "address.street". Property access is denoted by
+ * dots, while array access is denoted by square brackets,
+ * for example "addresses[1].street".
+ */
+ public function getPropertyPath();
+
+ /**
+ * Returns the value that caused the violation.
+ *
+ * @return mixed the invalid value that caused the validated constraint to
+ * fail
+ */
+ public function getInvalidValue();
+
+ /**
+ * Returns a machine-digestible error code for the violation.
+ *
+ * @return string|null The error code
+ */
+ public function getCode();
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintViolationList.php b/public/system/storage/vendor/symfony/validator/ConstraintViolationList.php
new file mode 100644
index 0000000..feb1732
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintViolationList.php
@@ -0,0 +1,161 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Default implementation of {@ConstraintViolationListInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ConstraintViolationList implements \IteratorAggregate, ConstraintViolationListInterface
+{
+ /**
+ * @var ConstraintViolationInterface[]
+ */
+ private $violations = array();
+
+ /**
+ * Creates a new constraint violation list.
+ *
+ * @param ConstraintViolationInterface[] $violations The constraint violations to add to the list
+ */
+ public function __construct(array $violations = array())
+ {
+ foreach ($violations as $violation) {
+ $this->add($violation);
+ }
+ }
+
+ /**
+ * Converts the violation into a string for debugging purposes.
+ *
+ * @return string The violation as string
+ */
+ public function __toString()
+ {
+ $string = '';
+
+ foreach ($this->violations as $violation) {
+ $string .= $violation."\n";
+ }
+
+ return $string;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add(ConstraintViolationInterface $violation)
+ {
+ $this->violations[] = $violation;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addAll(ConstraintViolationListInterface $otherList)
+ {
+ foreach ($otherList as $violation) {
+ $this->violations[] = $violation;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($offset)
+ {
+ if (!isset($this->violations[$offset])) {
+ throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset));
+ }
+
+ return $this->violations[$offset];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($offset)
+ {
+ return isset($this->violations[$offset]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set($offset, ConstraintViolationInterface $violation)
+ {
+ $this->violations[$offset] = $violation;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function remove($offset)
+ {
+ unset($this->violations[$offset]);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return \ArrayIterator|ConstraintViolationInterface[]
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->violations);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function count()
+ {
+ return \count($this->violations);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($offset)
+ {
+ return $this->has($offset);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($offset)
+ {
+ return $this->get($offset);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetSet($offset, $violation)
+ {
+ if (null === $offset) {
+ $this->add($violation);
+ } else {
+ $this->set($offset, $violation);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetUnset($offset)
+ {
+ $this->remove($offset);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ConstraintViolationListInterface.php b/public/system/storage/vendor/symfony/validator/ConstraintViolationListInterface.php
new file mode 100644
index 0000000..0489ab5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ConstraintViolationListInterface.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * A list of constraint violations.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ConstraintViolationListInterface extends \Traversable, \Countable, \ArrayAccess
+{
+ /**
+ * Adds a constraint violation to this list.
+ */
+ public function add(ConstraintViolationInterface $violation);
+
+ /**
+ * Merges an existing violation list into this list.
+ */
+ public function addAll(ConstraintViolationListInterface $otherList);
+
+ /**
+ * Returns the violation at a given offset.
+ *
+ * @param int $offset The offset of the violation
+ *
+ * @return ConstraintViolationInterface The violation
+ *
+ * @throws \OutOfBoundsException if the offset does not exist
+ */
+ public function get($offset);
+
+ /**
+ * Returns whether the given offset exists.
+ *
+ * @param int $offset The violation offset
+ *
+ * @return bool Whether the offset exists
+ */
+ public function has($offset);
+
+ /**
+ * Sets a violation at a given offset.
+ *
+ * @param int $offset The violation offset
+ * @param ConstraintViolationInterface $violation The violation
+ */
+ public function set($offset, ConstraintViolationInterface $violation);
+
+ /**
+ * Removes a violation at a given offset.
+ *
+ * @param int $offset The offset to remove
+ */
+ public function remove($offset);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/AbstractComparison.php b/public/system/storage/vendor/symfony/validator/Constraints/AbstractComparison.php
new file mode 100644
index 0000000..15afebb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/AbstractComparison.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * Used for the comparison of values.
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class AbstractComparison extends Constraint
+{
+ public $message;
+ public $value;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($options = null)
+ {
+ if (null === $options) {
+ $options = array();
+ }
+
+ if (\is_array($options) && !isset($options['value'])) {
+ throw new ConstraintDefinitionException(sprintf('The %s constraint requires the "value" option to be set.', \get_class($this)));
+ }
+
+ parent::__construct($options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'value';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/AbstractComparisonValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/AbstractComparisonValidator.php
new file mode 100644
index 0000000..9620ead
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/AbstractComparisonValidator.php
@@ -0,0 +1,94 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Provides a base class for the validation of property comparisons.
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class AbstractComparisonValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof AbstractComparison) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\AbstractComparison');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ $comparedValue = $constraint->value;
+
+ // Convert strings to DateTimes if comparing another DateTime
+ // This allows to compare with any date/time value supported by
+ // the DateTime constructor:
+ // http://php.net/manual/en/datetime.formats.php
+ if (\is_string($comparedValue)) {
+ if ($value instanceof \DateTimeImmutable) {
+ // If $value is immutable, convert the compared value to a
+ // DateTimeImmutable too
+ $comparedValue = new \DateTimeImmutable($comparedValue);
+ } elseif ($value instanceof \DateTime || $value instanceof \DateTimeInterface) {
+ // Otherwise use DateTime
+ $comparedValue = new \DateTime($comparedValue);
+ }
+ }
+
+ if (!$this->compareValues($value, $comparedValue)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE))
+ ->setParameter('{{ compared_value }}', $this->formatValue($comparedValue, self::OBJECT_TO_STRING | self::PRETTY_DATE))
+ ->setParameter('{{ compared_value_type }}', $this->formatTypeOf($comparedValue))
+ ->setCode($this->getErrorCode())
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE))
+ ->setParameter('{{ compared_value }}', $this->formatValue($comparedValue, self::OBJECT_TO_STRING | self::PRETTY_DATE))
+ ->setParameter('{{ compared_value_type }}', $this->formatTypeOf($comparedValue))
+ ->setCode($this->getErrorCode())
+ ->addViolation();
+ }
+ }
+ }
+
+ /**
+ * Compares the two given values to find if their relationship is valid.
+ *
+ * @param mixed $value1 The first value to compare
+ * @param mixed $value2 The second value to compare
+ *
+ * @return bool true if the relationship is valid, false otherwise
+ */
+ abstract protected function compareValues($value1, $value2);
+
+ /**
+ * Returns the error code used if the comparison fails.
+ *
+ * @return string|null The error code or `null` if no code should be set
+ */
+ protected function getErrorCode()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/All.php b/public/system/storage/vendor/symfony/validator/Constraints/All.php
new file mode 100644
index 0000000..b531a1d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/All.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class All extends Composite
+{
+ public $constraints = array();
+
+ public function getDefaultOption()
+ {
+ return 'constraints';
+ }
+
+ public function getRequiredOptions()
+ {
+ return array('constraints');
+ }
+
+ protected function getCompositeOption()
+ {
+ return 'constraints';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/AllValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/AllValidator.php
new file mode 100644
index 0000000..fa763c5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/AllValidator.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class AllValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof All) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\All');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ if (!\is_array($value) && !$value instanceof \Traversable) {
+ throw new UnexpectedTypeException($value, 'array or Traversable');
+ }
+
+ $context = $this->context;
+
+ if ($context instanceof ExecutionContextInterface) {
+ $validator = $context->getValidator()->inContext($context);
+
+ foreach ($value as $key => $element) {
+ $validator->atPath('['.$key.']')->validate($element, $constraint->constraints);
+ }
+ } else {
+ // 2.4 API
+ foreach ($value as $key => $element) {
+ $context->validateValue($element, $constraint->constraints, '['.$key.']');
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Bic.php b/public/system/storage/vendor/symfony/validator/Constraints/Bic.php
new file mode 100644
index 0000000..dee5d52
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Bic.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Michael Hirschler <michael.vhirsch@gmail.com>
+ */
+class Bic extends Constraint
+{
+ const INVALID_LENGTH_ERROR = '66dad313-af0b-4214-8566-6c799be9789c';
+ const INVALID_CHARACTERS_ERROR = 'f424c529-7add-4417-8f2d-4b656e4833e2';
+ const INVALID_BANK_CODE_ERROR = '00559357-6170-4f29-aebd-d19330aa19cf';
+ const INVALID_COUNTRY_CODE_ERROR = '1ce76f8d-3c1f-451c-9e62-fe9c3ed486ae';
+ const INVALID_CASE_ERROR = '11884038-3312-4ae5-9d04-699f782130c7';
+
+ protected static $errorNames = array(
+ self::INVALID_LENGTH_ERROR => 'INVALID_LENGTH_ERROR',
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::INVALID_BANK_CODE_ERROR => 'INVALID_BANK_CODE_ERROR',
+ self::INVALID_COUNTRY_CODE_ERROR => 'INVALID_COUNTRY_CODE_ERROR',
+ self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR',
+ );
+
+ public $message = 'This is not a valid Business Identifier Code (BIC).';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/BicValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/BicValidator.php
new file mode 100644
index 0000000..2a27bef
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/BicValidator.php
@@ -0,0 +1,90 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Michael Hirschler <michael.vhirsch@gmail.com>
+ *
+ * @see https://en.wikipedia.org/wiki/ISO_9362#Structure
+ */
+class BicValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Bic) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Bic');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ $canonicalize = str_replace(' ', '', $value);
+
+ // the bic must be either 8 or 11 characters long
+ if (!\in_array(\strlen($canonicalize), array(8, 11))) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Bic::INVALID_LENGTH_ERROR)
+ ->addViolation();
+
+ return;
+ }
+
+ // must contain alphanumeric values only
+ if (!ctype_alnum($canonicalize)) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Bic::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+
+ return;
+ }
+
+ // first 4 letters must be alphabetic (bank code)
+ if (!ctype_alpha(substr($canonicalize, 0, 4))) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Bic::INVALID_BANK_CODE_ERROR)
+ ->addViolation();
+
+ return;
+ }
+
+ // next 2 letters must be alphabetic (country code)
+ if (!ctype_alpha(substr($canonicalize, 4, 2))) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Bic::INVALID_COUNTRY_CODE_ERROR)
+ ->addViolation();
+
+ return;
+ }
+
+ // should contain uppercase characters only
+ if (strtoupper($canonicalize) !== $canonicalize) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Bic::INVALID_CASE_ERROR)
+ ->addViolation();
+
+ return;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Blank.php b/public/system/storage/vendor/symfony/validator/Constraints/Blank.php
new file mode 100644
index 0000000..030b21f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Blank.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Blank extends Constraint
+{
+ const NOT_BLANK_ERROR = '183ad2de-533d-4796-a439-6d3c3852b549';
+
+ protected static $errorNames = array(
+ self::NOT_BLANK_ERROR => 'NOT_BLANK_ERROR',
+ );
+
+ public $message = 'This value should be blank.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/BlankValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/BlankValidator.php
new file mode 100644
index 0000000..7e4d738
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/BlankValidator.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class BlankValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Blank) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Blank');
+ }
+
+ if ('' !== $value && null !== $value) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Blank::NOT_BLANK_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Blank::NOT_BLANK_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Callback.php b/public/system/storage/vendor/symfony/validator/Constraints/Callback.php
new file mode 100644
index 0000000..592ae00
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Callback.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Callback extends Constraint
+{
+ /**
+ * @var string|callable
+ */
+ public $callback;
+
+ /**
+ * @var array
+ *
+ * @deprecated since version 2.4, to be removed in 3.0.
+ */
+ public $methods;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($options = null)
+ {
+ // Invocation through annotations with an array parameter only
+ if (\is_array($options) && 1 === \count($options) && isset($options['value'])) {
+ $options = $options['value'];
+ }
+
+ if (\is_array($options) && isset($options['methods'])) {
+ @trigger_error('The "methods" option of the '.__CLASS__.' class is deprecated since Symfony 2.4 and will be removed in 3.0. Use the "callback" option instead.', E_USER_DEPRECATED);
+ }
+
+ if (\is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups']) && !isset($options['payload'])) {
+ if (\is_callable($options) || !$options) {
+ $options = array('callback' => $options);
+ } else {
+ // @deprecated, to be removed in 3.0
+ $options = array('methods' => $options);
+ }
+ }
+
+ parent::__construct($options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'callback';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTargets()
+ {
+ return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CallbackValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/CallbackValidator.php
new file mode 100644
index 0000000..d4b440f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CallbackValidator.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validator for Callback constraint.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CallbackValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($object, Constraint $constraint)
+ {
+ if (!$constraint instanceof Callback) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Callback');
+ }
+
+ if (null !== $constraint->callback && null !== $constraint->methods) {
+ throw new ConstraintDefinitionException('The Callback constraint supports either the option "callback" or "methods", but not both at the same time.');
+ }
+
+ // has to be an array so that we can differentiate between callables
+ // and method names
+ if (null !== $constraint->methods && !\is_array($constraint->methods)) {
+ throw new UnexpectedTypeException($constraint->methods, 'array');
+ }
+
+ $methods = $constraint->methods ?: array($constraint->callback);
+
+ foreach ($methods as $method) {
+ if ($method instanceof \Closure) {
+ $method($object, $this->context);
+ } elseif (\is_array($method)) {
+ if (!\is_callable($method)) {
+ if (isset($method[0]) && \is_object($method[0])) {
+ $method[0] = \get_class($method[0]);
+ }
+ throw new ConstraintDefinitionException(sprintf('%s targeted by Callback constraint is not a valid callable', json_encode($method)));
+ }
+
+ \call_user_func($method, $object, $this->context);
+ } elseif (null !== $object) {
+ if (!method_exists($object, $method)) {
+ throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist in class %s', $method, \get_class($object)));
+ }
+
+ $reflMethod = new \ReflectionMethod($object, $method);
+
+ if ($reflMethod->isStatic()) {
+ $reflMethod->invoke(null, $object, $this->context);
+ } else {
+ $reflMethod->invoke($object, $this->context);
+ }
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CardScheme.php b/public/system/storage/vendor/symfony/validator/Constraints/CardScheme.php
new file mode 100644
index 0000000..40c32e8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CardScheme.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Metadata for the CardSchemeValidator.
+ *
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Tim Nagel <t.nagel@infinite.net.au>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CardScheme extends Constraint
+{
+ const NOT_NUMERIC_ERROR = 'a2ad9231-e827-485f-8a1e-ef4d9a6d5c2e';
+ const INVALID_FORMAT_ERROR = 'a8faedbf-1c2f-4695-8d22-55783be8efed';
+
+ protected static $errorNames = array(
+ self::NOT_NUMERIC_ERROR => 'NOT_NUMERIC_ERROR',
+ self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
+ );
+
+ public $message = 'Unsupported card type or invalid card number.';
+ public $schemes;
+
+ public function getDefaultOption()
+ {
+ return 'schemes';
+ }
+
+ public function getRequiredOptions()
+ {
+ return array('schemes');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CardSchemeValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/CardSchemeValidator.php
new file mode 100644
index 0000000..f667bde
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CardSchemeValidator.php
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates that a card number belongs to a specified scheme.
+ *
+ * @author Tim Nagel <t.nagel@infinite.net.au>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see http://en.wikipedia.org/wiki/Bank_card_number
+ * @see http://www.regular-expressions.info/creditcard.html
+ * @see http://www.barclaycard.co.uk/business/files/Ranges_and_Rules_September_2014.pdf
+ */
+class CardSchemeValidator extends ConstraintValidator
+{
+ protected $schemes = array(
+ // American Express card numbers start with 34 or 37 and have 15 digits.
+ 'AMEX' => array(
+ '/^3[47][0-9]{13}$/',
+ ),
+ // China UnionPay cards start with 62 and have between 16 and 19 digits.
+ // Please note that these cards do not follow Luhn Algorithm as a checksum.
+ 'CHINA_UNIONPAY' => array(
+ '/^62[0-9]{14,17}$/',
+ ),
+ // Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits.
+ // There are Diners Club cards that begin with 5 and have 16 digits.
+ // These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
+ 'DINERS' => array(
+ '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
+ ),
+ // Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65.
+ // All have 16 digits.
+ 'DISCOVER' => array(
+ '/^6011[0-9]{12}$/',
+ '/^64[4-9][0-9]{13}$/',
+ '/^65[0-9]{14}$/',
+ '/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/',
+ ),
+ // InstaPayment cards begin with 637 through 639 and have 16 digits.
+ 'INSTAPAYMENT' => array(
+ '/^63[7-9][0-9]{13}$/',
+ ),
+ // JCB cards beginning with 2131 or 1800 have 15 digits.
+ // JCB cards beginning with 35 have 16 digits.
+ 'JCB' => array(
+ '/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/',
+ ),
+ // Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits.
+ 'LASER' => array(
+ '/^(6304|670[69]|6771)[0-9]{12,15}$/',
+ ),
+ // Maestro international cards begin with 675900..675999 and have between 12 and 19 digits.
+ // Maestro UK cards begin with either 500000..509999 or 560000..699999 and have between 12 and 19 digits.
+ 'MAESTRO' => array(
+ '/^(6759[0-9]{2})[0-9]{6,13}$/',
+ '/^(50[0-9]{4})[0-9]{6,13}$/',
+ '/^5[6-9][0-9]{10,17}$/',
+ '/^6[0-9]{11,18}$/',
+ ),
+ // All MasterCard numbers start with the numbers 51 through 55. All have 16 digits.
+ // October 2016 MasterCard numbers can also start with 222100 through 272099.
+ 'MASTERCARD' => array(
+ '/^5[1-5][0-9]{14}$/',
+ '/^2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12})$/',
+ ),
+ // All Visa card numbers start with a 4 and have a length of 13, 16, or 19 digits.
+ 'VISA' => array(
+ '/^4([0-9]{12}|[0-9]{15}|[0-9]{18})$/',
+ ),
+ );
+
+ /**
+ * Validates a creditcard belongs to a specified scheme.
+ *
+ * @param mixed $value
+ * @param Constraint $constraint
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof CardScheme) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\CardScheme');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_numeric($value)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(CardScheme::NOT_NUMERIC_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(CardScheme::NOT_NUMERIC_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $schemes = array_flip((array) $constraint->schemes);
+ $schemeRegexes = array_intersect_key($this->schemes, $schemes);
+
+ foreach ($schemeRegexes as $regexes) {
+ foreach ($regexes as $regex) {
+ if (preg_match($regex, $value)) {
+ return;
+ }
+ }
+ }
+
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(CardScheme::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(CardScheme::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Choice.php b/public/system/storage/vendor/symfony/validator/Constraints/Choice.php
new file mode 100644
index 0000000..4b93c70
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Choice.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Choice extends Constraint
+{
+ const NO_SUCH_CHOICE_ERROR = '8e179f1b-97aa-4560-a02f-2a8b42e49df7';
+ const TOO_FEW_ERROR = '11edd7eb-5872-4b6e-9f12-89923999fd0e';
+ const TOO_MANY_ERROR = '9bd98e49-211c-433f-8630-fd1c2d0f08c3';
+
+ protected static $errorNames = array(
+ self::NO_SUCH_CHOICE_ERROR => 'NO_SUCH_CHOICE_ERROR',
+ self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
+ self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
+ );
+
+ public $choices;
+ public $callback;
+ public $multiple = false;
+ public $strict = false;
+ public $min;
+ public $max;
+ public $message = 'The value you selected is not a valid choice.';
+ public $multipleMessage = 'One or more of the given values is invalid.';
+ public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.';
+ public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'choices';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/ChoiceValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/ChoiceValidator.php
new file mode 100644
index 0000000..b92ba61
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/ChoiceValidator.php
@@ -0,0 +1,133 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * ChoiceValidator validates that the value is one of the expected values.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Florian Eckerstorfer <florian@eckerstorfer.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ChoiceValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Choice) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Choice');
+ }
+
+ if (!\is_array($constraint->choices) && !$constraint->callback) {
+ throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ if ($constraint->multiple && !\is_array($value)) {
+ throw new UnexpectedTypeException($value, 'array');
+ }
+
+ if ($constraint->callback) {
+ if (!\is_callable($choices = array($this->context->getClassName(), $constraint->callback))
+ && !\is_callable($choices = $constraint->callback)
+ ) {
+ throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
+ }
+ $choices = \call_user_func($choices);
+ } else {
+ $choices = $constraint->choices;
+ }
+
+ if ($constraint->multiple) {
+ foreach ($value as $_value) {
+ if (!\in_array($_value, $choices, $constraint->strict)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->multipleMessage)
+ ->setParameter('{{ value }}', $this->formatValue($_value))
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->setInvalidValue($_value)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->multipleMessage)
+ ->setParameter('{{ value }}', $this->formatValue($_value))
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->setInvalidValue($_value)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ $count = \count($value);
+
+ if (null !== $constraint->min && $count < $constraint->min) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->minMessage)
+ ->setParameter('{{ limit }}', $constraint->min)
+ ->setPlural((int) $constraint->min)
+ ->setCode(Choice::TOO_FEW_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->minMessage)
+ ->setParameter('{{ limit }}', $constraint->min)
+ ->setPlural((int) $constraint->min)
+ ->setCode(Choice::TOO_FEW_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (null !== $constraint->max && $count > $constraint->max) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->maxMessage)
+ ->setParameter('{{ limit }}', $constraint->max)
+ ->setPlural((int) $constraint->max)
+ ->setCode(Choice::TOO_MANY_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->maxMessage)
+ ->setParameter('{{ limit }}', $constraint->max)
+ ->setPlural((int) $constraint->max)
+ ->setCode(Choice::TOO_MANY_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ } elseif (!\in_array($value, $choices, $constraint->strict)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Collection.php b/public/system/storage/vendor/symfony/validator/Constraints/Collection.php
new file mode 100644
index 0000000..2b5679b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Collection.php
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Collection extends Composite
+{
+ const MISSING_FIELD_ERROR = '2fa2158c-2a7f-484b-98aa-975522539ff8';
+ const NO_SUCH_FIELD_ERROR = '7703c766-b5d5-4cef-ace7-ae0dd82304e9';
+
+ protected static $errorNames = array(
+ self::MISSING_FIELD_ERROR => 'MISSING_FIELD_ERROR',
+ self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR',
+ );
+
+ public $fields = array();
+ public $allowExtraFields = false;
+ public $allowMissingFields = false;
+ public $extraFieldsMessage = 'This field was not expected.';
+ public $missingFieldsMessage = 'This field is missing.';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($options = null)
+ {
+ // no known options set? $options is the fields array
+ if (\is_array($options)
+ && !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) {
+ $options = array('fields' => $options);
+ }
+
+ parent::__construct($options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function initializeNestedConstraints()
+ {
+ parent::initializeNestedConstraints();
+
+ if (!\is_array($this->fields)) {
+ throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__));
+ }
+
+ foreach ($this->fields as $fieldName => $field) {
+ // the XmlFileLoader and YamlFileLoader pass the field Optional
+ // and Required constraint as an array with exactly one element
+ if (\is_array($field) && 1 == \count($field)) {
+ $this->fields[$fieldName] = $field = $field[0];
+ }
+
+ if (!$field instanceof Optional && !$field instanceof Required) {
+ $this->fields[$fieldName] = $field = new Required($field);
+ }
+ }
+ }
+
+ public function getRequiredOptions()
+ {
+ return array('fields');
+ }
+
+ protected function getCompositeOption()
+ {
+ return 'fields';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Collection/Optional.php b/public/system/storage/vendor/symfony/validator/Constraints/Collection/Optional.php
new file mode 100644
index 0000000..fbd3d7a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Collection/Optional.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints\Collection;
+
+@trigger_error('The '.__NAMESPACE__.'\Optional class is deprecated since Symfony 2.3 and will be removed in 3.0. Use the Symfony\Component\Validator\Constraints\Optional class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Validator\Constraints\Optional as BaseOptional;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.3, to be removed in 3.0.
+ * Use {@link \Symfony\Component\Validator\Constraints\Optional} instead.
+ */
+class Optional extends BaseOptional
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Collection/Required.php b/public/system/storage/vendor/symfony/validator/Constraints/Collection/Required.php
new file mode 100644
index 0000000..96f9bc2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Collection/Required.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints\Collection;
+
+@trigger_error('The '.__NAMESPACE__.'\Required class is deprecated since Symfony 2.3 and will be removed in 3.0. Use the Symfony\Component\Validator\Constraints\Required class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Validator\Constraints\Required as BaseRequired;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.3, to be removed in 3.0.
+ * Use {@link \Symfony\Component\Validator\Constraints\Required} instead.
+ */
+class Required extends BaseRequired
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CollectionValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/CollectionValidator.php
new file mode 100644
index 0000000..c2aae3a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CollectionValidator.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CollectionValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Collection) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Collection');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ if (!\is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) {
+ throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess');
+ }
+
+ // We need to keep the initialized context when CollectionValidator
+ // calls itself recursively (Collection constraints can be nested).
+ // Since the context of the validator is overwritten when initialize()
+ // is called for the nested constraint, the outer validator is
+ // acting on the wrong context when the nested validation terminates.
+ //
+ // A better solution - which should be approached in Symfony 3.0 - is to
+ // remove the initialize() method and pass the context as last argument
+ // to validate() instead.
+ $context = $this->context;
+
+ foreach ($constraint->fields as $field => $fieldConstraint) {
+ // bug fix issue #2779
+ $existsInArray = \is_array($value) && array_key_exists($field, $value);
+ $existsInArrayAccess = $value instanceof \ArrayAccess && $value->offsetExists($field);
+
+ if ($existsInArray || $existsInArrayAccess) {
+ if (\count($fieldConstraint->constraints) > 0) {
+ if ($context instanceof ExecutionContextInterface) {
+ $context->getValidator()
+ ->inContext($context)
+ ->atPath('['.$field.']')
+ ->validate($value[$field], $fieldConstraint->constraints);
+ } else {
+ // 2.4 API
+ $context->validateValue($value[$field], $fieldConstraint->constraints, '['.$field.']');
+ }
+ }
+ } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
+ if ($context instanceof ExecutionContextInterface) {
+ $context->buildViolation($constraint->missingFieldsMessage)
+ ->atPath('['.$field.']')
+ ->setParameter('{{ field }}', $this->formatValue($field))
+ ->setInvalidValue(null)
+ ->setCode(Collection::MISSING_FIELD_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolationInContext($context, $constraint->missingFieldsMessage)
+ ->atPath('['.$field.']')
+ ->setParameter('{{ field }}', $this->formatValue($field))
+ ->setInvalidValue(null)
+ ->setCode(Collection::MISSING_FIELD_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ if (!$constraint->allowExtraFields) {
+ foreach ($value as $field => $fieldValue) {
+ if (!isset($constraint->fields[$field])) {
+ if ($context instanceof ExecutionContextInterface) {
+ $context->buildViolation($constraint->extraFieldsMessage)
+ ->atPath('['.$field.']')
+ ->setParameter('{{ field }}', $this->formatValue($field))
+ ->setInvalidValue($fieldValue)
+ ->setCode(Collection::NO_SUCH_FIELD_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolationInContext($context, $constraint->extraFieldsMessage)
+ ->atPath('['.$field.']')
+ ->setParameter('{{ field }}', $this->formatValue($field))
+ ->setInvalidValue($fieldValue)
+ ->setCode(Collection::NO_SUCH_FIELD_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Composite.php b/public/system/storage/vendor/symfony/validator/Constraints/Composite.php
new file mode 100644
index 0000000..d233f06
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Composite.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * A constraint that is composed of other constraints.
+ *
+ * You should never use the nested constraint instances anywhere else, because
+ * their groups are adapted when passed to the constructor of this class.
+ *
+ * If you want to create your own composite constraint, extend this class and
+ * let {@link getCompositeOption()} return the name of the property which
+ * contains the nested constraints.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class Composite extends Constraint
+{
+ /**
+ * {@inheritdoc}
+ *
+ * The groups of the composite and its nested constraints are made
+ * consistent using the following strategy:
+ *
+ * - If groups are passed explicitly to the composite constraint, but
+ * not to the nested constraints, the options of the composite
+ * constraint are copied to the nested constraints;
+ *
+ * - If groups are passed explicitly to the nested constraints, but not
+ * to the composite constraint, the groups of all nested constraints
+ * are merged and used as groups for the composite constraint;
+ *
+ * - If groups are passed explicitly to both the composite and its nested
+ * constraints, the groups of the nested constraints must be a subset
+ * of the groups of the composite constraint. If not, a
+ * {@link ConstraintDefinitionException} is thrown.
+ *
+ * All this is done in the constructor, because constraints can then be
+ * cached. When constraints are loaded from the cache, no more group
+ * checks need to be done.
+ */
+ public function __construct($options = null)
+ {
+ parent::__construct($options);
+
+ $this->initializeNestedConstraints();
+
+ /* @var Constraint[] $nestedConstraints */
+ $compositeOption = $this->getCompositeOption();
+ $nestedConstraints = $this->$compositeOption;
+
+ if (!\is_array($nestedConstraints)) {
+ $nestedConstraints = array($nestedConstraints);
+ }
+
+ foreach ($nestedConstraints as $constraint) {
+ if (!$constraint instanceof Constraint) {
+ if (\is_object($constraint)) {
+ $constraint = \get_class($constraint);
+ }
+
+ throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, \get_class($this)));
+ }
+
+ if ($constraint instanceof Valid) {
+ throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', \get_class($this)));
+ }
+ }
+
+ if (!property_exists($this, 'groups')) {
+ $mergedGroups = array();
+
+ foreach ($nestedConstraints as $constraint) {
+ foreach ($constraint->groups as $group) {
+ $mergedGroups[$group] = true;
+ }
+ }
+
+ $this->groups = array_keys($mergedGroups);
+ $this->$compositeOption = $nestedConstraints;
+
+ return;
+ }
+
+ foreach ($nestedConstraints as $constraint) {
+ if (property_exists($constraint, 'groups')) {
+ $excessGroups = array_diff($constraint->groups, $this->groups);
+
+ if (\count($excessGroups) > 0) {
+ throw new ConstraintDefinitionException(sprintf('The group(s) "%s" passed to the constraint %s should also be passed to its containing constraint %s', implode('", "', $excessGroups), \get_class($constraint), \get_class($this)));
+ }
+ } else {
+ $constraint->groups = $this->groups;
+ }
+ }
+
+ $this->$compositeOption = $nestedConstraints;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Implicit group names are forwarded to nested constraints.
+ *
+ * @param string $group
+ */
+ public function addImplicitGroupName($group)
+ {
+ parent::addImplicitGroupName($group);
+
+ /** @var Constraint[] $nestedConstraints */
+ $nestedConstraints = $this->{$this->getCompositeOption()};
+
+ foreach ($nestedConstraints as $constraint) {
+ $constraint->addImplicitGroupName($group);
+ }
+ }
+
+ /**
+ * Returns the name of the property that contains the nested constraints.
+ *
+ * @return string The property name
+ */
+ abstract protected function getCompositeOption();
+
+ /**
+ * Initializes the nested constraints.
+ *
+ * This method can be overwritten in subclasses to clean up the nested
+ * constraints passed to the constructor.
+ *
+ * @see Collection::initializeNestedConstraints()
+ */
+ protected function initializeNestedConstraints()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Count.php b/public/system/storage/vendor/symfony/validator/Constraints/Count.php
new file mode 100644
index 0000000..0a54ee7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Count.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\MissingOptionsException;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Count extends Constraint
+{
+ const TOO_FEW_ERROR = 'bef8e338-6ae5-4caf-b8e2-50e7b0579e69';
+ const TOO_MANY_ERROR = '756b1212-697c-468d-a9ad-50dd783bb169';
+
+ protected static $errorNames = array(
+ self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
+ self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
+ );
+
+ public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.';
+ public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.';
+ public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.';
+ public $min;
+ public $max;
+
+ public function __construct($options = null)
+ {
+ if (null !== $options && !\is_array($options)) {
+ $options = array(
+ 'min' => $options,
+ 'max' => $options,
+ );
+ }
+
+ parent::__construct($options);
+
+ if (null === $this->min && null === $this->max) {
+ throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CountValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/CountValidator.php
new file mode 100644
index 0000000..45be996
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CountValidator.php
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CountValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Count) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Count');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ if (!\is_array($value) && !$value instanceof \Countable) {
+ throw new UnexpectedTypeException($value, 'array or \Countable');
+ }
+
+ $count = \count($value);
+
+ if (null !== $constraint->max && $count > $constraint->max) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
+ ->setParameter('{{ count }}', $count)
+ ->setParameter('{{ limit }}', $constraint->max)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->max)
+ ->setCode(Count::TOO_MANY_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
+ ->setParameter('{{ count }}', $count)
+ ->setParameter('{{ limit }}', $constraint->max)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->max)
+ ->setCode(Count::TOO_MANY_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (null !== $constraint->min && $count < $constraint->min) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
+ ->setParameter('{{ count }}', $count)
+ ->setParameter('{{ limit }}', $constraint->min)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->min)
+ ->setCode(Count::TOO_FEW_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
+ ->setParameter('{{ count }}', $count)
+ ->setParameter('{{ limit }}', $constraint->min)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->min)
+ ->setCode(Count::TOO_FEW_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Country.php b/public/system/storage/vendor/symfony/validator/Constraints/Country.php
new file mode 100644
index 0000000..1b76570
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Country.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Country extends Constraint
+{
+ const NO_SUCH_COUNTRY_ERROR = '8f900c12-61bd-455d-9398-996cd040f7f0';
+
+ protected static $errorNames = array(
+ self::NO_SUCH_COUNTRY_ERROR => 'NO_SUCH_COUNTRY_ERROR',
+ );
+
+ public $message = 'This value is not a valid country.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CountryValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/CountryValidator.php
new file mode 100644
index 0000000..437b3d6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CountryValidator.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Intl\Intl;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value is a valid country code.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CountryValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Country) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Country');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ $countries = Intl::getRegionBundle()->getCountryNames();
+
+ if (!isset($countries[$value])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Country::NO_SUCH_COUNTRY_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Country::NO_SUCH_COUNTRY_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Currency.php b/public/system/storage/vendor/symfony/validator/Constraints/Currency.php
new file mode 100644
index 0000000..d28f94c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Currency.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Currency extends Constraint
+{
+ const NO_SUCH_CURRENCY_ERROR = '69945ac1-2db4-405f-bec7-d2772f73df52';
+
+ protected static $errorNames = array(
+ self::NO_SUCH_CURRENCY_ERROR => 'NO_SUCH_CURRENCY_ERROR',
+ );
+
+ public $message = 'This value is not a valid currency.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/CurrencyValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/CurrencyValidator.php
new file mode 100644
index 0000000..40e7920
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/CurrencyValidator.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Intl\Intl;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value is a valid currency.
+ *
+ * @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CurrencyValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Currency) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Currency');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ $currencies = Intl::getCurrencyBundle()->getCurrencyNames();
+
+ if (!isset($currencies[$value])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Currency::NO_SUCH_CURRENCY_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Currency::NO_SUCH_CURRENCY_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Date.php b/public/system/storage/vendor/symfony/validator/Constraints/Date.php
new file mode 100644
index 0000000..2563413
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Date.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Date extends Constraint
+{
+ const INVALID_FORMAT_ERROR = '69819696-02ac-4a99-9ff0-14e127c4d1bc';
+ const INVALID_DATE_ERROR = '3c184ce5-b31d-4de7-8b76-326da7b2be93';
+
+ protected static $errorNames = array(
+ self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
+ self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR',
+ );
+
+ public $message = 'This value is not a valid date.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/DateTime.php b/public/system/storage/vendor/symfony/validator/Constraints/DateTime.php
new file mode 100644
index 0000000..35e2934
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/DateTime.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class DateTime extends Constraint
+{
+ const INVALID_FORMAT_ERROR = '1a9da513-2640-4f84-9b6a-4d99dcddc628';
+ const INVALID_DATE_ERROR = 'd52afa47-620d-4d99-9f08-f4d85b36e33c';
+ const INVALID_TIME_ERROR = '5e797c9d-74f7-4098-baa3-94390c447b27';
+
+ protected static $errorNames = array(
+ self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
+ self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR',
+ self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR',
+ );
+
+ public $message = 'This value is not a valid datetime.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/DateTimeValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/DateTimeValidator.php
new file mode 100644
index 0000000..3296935
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/DateTimeValidator.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class DateTimeValidator extends DateValidator
+{
+ const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof DateTime) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\DateTime');
+ }
+
+ if (null === $value || '' === $value || $value instanceof \DateTime) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if (!preg_match(static::PATTERN, $value, $matches)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(DateTime::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(DateTime::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (!DateValidator::checkDate($matches[1], $matches[2], $matches[3])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(DateTime::INVALID_DATE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(DateTime::INVALID_DATE_ERROR)
+ ->addViolation();
+ }
+ }
+
+ if (!TimeValidator::checkTime($matches[4], $matches[5], $matches[6])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(DateTime::INVALID_TIME_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(DateTime::INVALID_TIME_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/DateValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/DateValidator.php
new file mode 100644
index 0000000..a4c95dc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/DateValidator.php
@@ -0,0 +1,91 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class DateValidator extends ConstraintValidator
+{
+ const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/';
+
+ /**
+ * Checks whether a date is valid.
+ *
+ * @param int $year The year
+ * @param int $month The month
+ * @param int $day The day
+ *
+ * @return bool Whether the date is valid
+ *
+ * @internal
+ */
+ public static function checkDate($year, $month, $day)
+ {
+ return checkdate($month, $day, $year);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Date) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Date');
+ }
+
+ if (null === $value || '' === $value || $value instanceof \DateTime) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if (!preg_match(static::PATTERN, $value, $matches)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Date::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Date::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (!self::checkDate($matches[1], $matches[2], $matches[3])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Date::INVALID_DATE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Date::INVALID_DATE_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Email.php b/public/system/storage/vendor/symfony/validator/Constraints/Email.php
new file mode 100644
index 0000000..a9d9ab1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Email.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Email extends Constraint
+{
+ const INVALID_FORMAT_ERROR = 'bd79c0ab-ddba-46cc-a703-a7a4b08de310';
+ const MX_CHECK_FAILED_ERROR = 'bf447c1c-0266-4e10-9c6c-573df282e413';
+ const HOST_CHECK_FAILED_ERROR = '7da53a8b-56f3-4288-bb3e-ee9ede4ef9a1';
+
+ protected static $errorNames = array(
+ self::INVALID_FORMAT_ERROR => 'STRICT_CHECK_FAILED_ERROR',
+ self::MX_CHECK_FAILED_ERROR => 'MX_CHECK_FAILED_ERROR',
+ self::HOST_CHECK_FAILED_ERROR => 'HOST_CHECK_FAILED_ERROR',
+ );
+
+ public $message = 'This value is not a valid email address.';
+ public $checkMX = false;
+ public $checkHost = false;
+ public $strict;
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/EmailValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/EmailValidator.php
new file mode 100644
index 0000000..2f0d25a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/EmailValidator.php
@@ -0,0 +1,155 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\RuntimeException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class EmailValidator extends ConstraintValidator
+{
+ private $isStrict;
+
+ /**
+ * @param bool $strict
+ */
+ public function __construct($strict = false)
+ {
+ $this->isStrict = $strict;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Email) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Email');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if (null === $constraint->strict) {
+ $constraint->strict = $this->isStrict;
+ }
+
+ if ($constraint->strict) {
+ if (!class_exists('\Egulias\EmailValidator\EmailValidator') || interface_exists('\Egulias\EmailValidator\Validation\EmailValidation')) {
+ throw new RuntimeException('Strict email validation requires egulias/email-validator:~1.2');
+ }
+
+ $strictValidator = new \Egulias\EmailValidator\EmailValidator();
+
+ if (!$strictValidator->isValid($value, false, true)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ } elseif (!preg_match('/^.+\@\S+\.\S+$/', $value)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $host = (string) substr($value, strrpos($value, '@') + 1);
+
+ // Check for host DNS resource records
+ if ($constraint->checkMX) {
+ if (!$this->checkMX($host)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::MX_CHECK_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::MX_CHECK_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+
+ return;
+ }
+
+ if ($constraint->checkHost && !$this->checkHost($host)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::HOST_CHECK_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Email::HOST_CHECK_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ /**
+ * Check DNS Records for MX type.
+ *
+ * @param string $host Host
+ *
+ * @return bool
+ */
+ private function checkMX($host)
+ {
+ return '' !== $host && checkdnsrr($host, 'MX');
+ }
+
+ /**
+ * Check if one of MX, A or AAAA DNS RR exists.
+ *
+ * @param string $host Host
+ *
+ * @return bool
+ */
+ private function checkHost($host)
+ {
+ return '' !== $host && ($this->checkMX($host) || (checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA')));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/EqualTo.php b/public/system/storage/vendor/symfony/validator/Constraints/EqualTo.php
new file mode 100644
index 0000000..4b22c6d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/EqualTo.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class EqualTo extends AbstractComparison
+{
+ const NOT_EQUAL_ERROR = '478618a7-95ba-473d-9101-cabd45e49115';
+
+ protected static $errorNames = array(
+ self::NOT_EQUAL_ERROR => 'NOT_EQUAL_ERROR',
+ );
+
+ public $message = 'This value should be equal to {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/EqualToValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/EqualToValidator.php
new file mode 100644
index 0000000..fe1f362
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/EqualToValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are equal (==).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class EqualToValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 == $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return EqualTo::NOT_EQUAL_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Existence.php b/public/system/storage/vendor/symfony/validator/Constraints/Existence.php
new file mode 100644
index 0000000..5ea6ffe
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Existence.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class Existence extends Composite
+{
+ public $constraints = array();
+
+ public function getDefaultOption()
+ {
+ return 'constraints';
+ }
+
+ protected function getCompositeOption()
+ {
+ return 'constraints';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Expression.php b/public/system/storage/vendor/symfony/validator/Constraints/Expression.php
new file mode 100644
index 0000000..3329bd2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Expression.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Expression extends Constraint
+{
+ const EXPRESSION_FAILED_ERROR = '6b3befbc-2f01-4ddf-be21-b57898905284';
+
+ protected static $errorNames = array(
+ self::EXPRESSION_FAILED_ERROR => 'EXPRESSION_FAILED_ERROR',
+ );
+
+ public $message = 'This value is not valid.';
+ public $expression;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'expression';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRequiredOptions()
+ {
+ return array('expression');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTargets()
+ {
+ return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validatedBy()
+ {
+ return 'validator.expression';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/ExpressionValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/ExpressionValidator.php
new file mode 100644
index 0000000..85fc466
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/ExpressionValidator.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
+use Symfony\Component\PropertyAccess\PropertyAccess;
+use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
+use Symfony\Component\PropertyAccess\PropertyPath;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\RuntimeException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@symfony.com>
+ */
+class ExpressionValidator extends ConstraintValidator
+{
+ private $propertyAccessor;
+ private $expressionLanguage;
+
+ public function __construct(PropertyAccessorInterface $propertyAccessor = null, ExpressionLanguage $expressionLanguage = null)
+ {
+ $this->propertyAccessor = $propertyAccessor;
+ $this->expressionLanguage = $expressionLanguage;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Expression) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Expression');
+ }
+
+ $variables = array();
+
+ // Symfony 2.5+
+ if ($this->context instanceof ExecutionContextInterface) {
+ $variables['value'] = $value;
+ $variables['this'] = $this->context->getObject();
+ } elseif (null === $this->context->getPropertyName()) {
+ $variables['value'] = $value;
+ $variables['this'] = $value;
+ } else {
+ $root = $this->context->getRoot();
+ $variables['value'] = $value;
+
+ if (\is_object($root)) {
+ // Extract the object that the property belongs to from the object
+ // graph
+ $path = new PropertyPath($this->context->getPropertyPath());
+ $parentPath = $path->getParent();
+ $variables['this'] = $parentPath ? $this->getPropertyAccessor()->getValue($root, $parentPath) : $root;
+ } else {
+ $variables['this'] = null;
+ }
+ }
+
+ if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING))
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING))
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ private function getExpressionLanguage()
+ {
+ if (null === $this->expressionLanguage) {
+ if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
+ throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
+ }
+ $this->expressionLanguage = new ExpressionLanguage();
+ }
+
+ return $this->expressionLanguage;
+ }
+
+ private function getPropertyAccessor()
+ {
+ if (null === $this->propertyAccessor) {
+ if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) {
+ throw new RuntimeException('Unable to use expressions as the Symfony PropertyAccess component is not installed.');
+ }
+ $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
+ }
+
+ return $this->propertyAccessor;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/False.php b/public/system/storage/vendor/symfony/validator/Constraints/False.php
new file mode 100644
index 0000000..40dcc8e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/False.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+@trigger_error('The '.__NAMESPACE__.'\False class is deprecated since Symfony 2.7 and will be removed in 3.0. Use the IsFalse class in the same namespace instead.', E_USER_DEPRECATED);
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use IsFalse instead.
+ */
+class False extends IsFalse
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/FalseValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/FalseValidator.php
new file mode 100644
index 0000000..c54a347
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/FalseValidator.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+@trigger_error('The '.__NAMESPACE__.'\FalseValidator class is deprecated since Symfony 2.7 and will be removed in 3.0. Use the IsFalseValidator class in the same namespace instead.', E_USER_DEPRECATED);
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use IsFalseValidator instead.
+ */
+class FalseValidator extends IsFalseValidator
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/File.php b/public/system/storage/vendor/symfony/validator/Constraints/File.php
new file mode 100644
index 0000000..c00ece3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/File.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @property int $maxSize
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class File extends Constraint
+{
+ // Check the Image constraint for clashes if adding new constants here
+
+ const NOT_FOUND_ERROR = 'd2a3fb6e-7ddc-4210-8fbf-2ab345ce1998';
+ const NOT_READABLE_ERROR = 'c20c92a4-5bfa-4202-9477-28e800e0f6ff';
+ const EMPTY_ERROR = '5d743385-9775-4aa5-8ff5-495fb1e60137';
+ const TOO_LARGE_ERROR = 'df8637af-d466-48c6-a59d-e7126250a654';
+ const INVALID_MIME_TYPE_ERROR = '744f00bc-4389-4c74-92de-9a43cde55534';
+
+ protected static $errorNames = array(
+ self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR',
+ self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR',
+ self::EMPTY_ERROR => 'EMPTY_ERROR',
+ self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR',
+ self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR',
+ );
+
+ public $binaryFormat;
+ public $mimeTypes = array();
+ public $notFoundMessage = 'The file could not be found.';
+ public $notReadableMessage = 'The file is not readable.';
+ public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.';
+ public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.';
+ public $disallowEmptyMessage = 'An empty file is not allowed.';
+
+ public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
+ public $uploadFormSizeErrorMessage = 'The file is too large.';
+ public $uploadPartialErrorMessage = 'The file was only partially uploaded.';
+ public $uploadNoFileErrorMessage = 'No file was uploaded.';
+ public $uploadNoTmpDirErrorMessage = 'No temporary folder was configured in php.ini.';
+ public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.';
+ public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.';
+ public $uploadErrorMessage = 'The file could not be uploaded.';
+
+ protected $maxSize;
+
+ public function __construct($options = null)
+ {
+ parent::__construct($options);
+
+ if (null !== $this->maxSize) {
+ $this->normalizeBinaryFormat($this->maxSize);
+ }
+ }
+
+ public function __set($option, $value)
+ {
+ if ('maxSize' === $option) {
+ $this->normalizeBinaryFormat($value);
+
+ return;
+ }
+
+ parent::__set($option, $value);
+ }
+
+ public function __get($option)
+ {
+ if ('maxSize' === $option) {
+ return $this->maxSize;
+ }
+
+ return parent::__get($option);
+ }
+
+ public function __isset($option)
+ {
+ if ('maxSize' === $option) {
+ return true;
+ }
+
+ return parent::__isset($option);
+ }
+
+ private function normalizeBinaryFormat($maxSize)
+ {
+ $sizeInt = (int) $maxSize;
+
+ if (ctype_digit((string) $maxSize)) {
+ $this->maxSize = $sizeInt;
+ $this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat;
+ } elseif (preg_match('/^\d++k$/i', $maxSize)) {
+ $this->maxSize = $sizeInt * 1000;
+ $this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat;
+ } elseif (preg_match('/^\d++M$/i', $maxSize)) {
+ $this->maxSize = $sizeInt * 1000000;
+ $this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat;
+ } elseif (preg_match('/^\d++Ki$/i', $maxSize)) {
+ $this->maxSize = $sizeInt << 10;
+ $this->binaryFormat = null === $this->binaryFormat ? true : $this->binaryFormat;
+ } elseif (preg_match('/^\d++Mi$/i', $maxSize)) {
+ $this->maxSize = $sizeInt << 20;
+ $this->binaryFormat = null === $this->binaryFormat ? true : $this->binaryFormat;
+ } else {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $this->maxSize));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/FileValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/FileValidator.php
new file mode 100644
index 0000000..33c784b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/FileValidator.php
@@ -0,0 +1,329 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\HttpFoundation\File\File as FileObject;
+use Symfony\Component\HttpFoundation\File\UploadedFile;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class FileValidator extends ConstraintValidator
+{
+ const KB_BYTES = 1000;
+ const MB_BYTES = 1000000;
+ const KIB_BYTES = 1024;
+ const MIB_BYTES = 1048576;
+
+ private static $suffices = array(
+ 1 => 'bytes',
+ self::KB_BYTES => 'kB',
+ self::MB_BYTES => 'MB',
+ self::KIB_BYTES => 'KiB',
+ self::MIB_BYTES => 'MiB',
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof File) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\File');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if ($value instanceof UploadedFile && !$value->isValid()) {
+ switch ($value->getError()) {
+ case UPLOAD_ERR_INI_SIZE:
+ $iniLimitSize = UploadedFile::getMaxFilesize();
+ if ($constraint->maxSize && $constraint->maxSize < $iniLimitSize) {
+ $limitInBytes = $constraint->maxSize;
+ $binaryFormat = $constraint->binaryFormat;
+ } else {
+ $limitInBytes = $iniLimitSize;
+ $binaryFormat = null === $constraint->binaryFormat ? true : $constraint->binaryFormat;
+ }
+
+ list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes(0, $limitInBytes, $binaryFormat);
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadIniSizeErrorMessage)
+ ->setParameter('{{ limit }}', $limitAsString)
+ ->setParameter('{{ suffix }}', $suffix)
+ ->setCode(UPLOAD_ERR_INI_SIZE)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadIniSizeErrorMessage)
+ ->setParameter('{{ limit }}', $limitAsString)
+ ->setParameter('{{ suffix }}', $suffix)
+ ->setCode(UPLOAD_ERR_INI_SIZE)
+ ->addViolation();
+ }
+
+ return;
+ case UPLOAD_ERR_FORM_SIZE:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadFormSizeErrorMessage)
+ ->setCode(UPLOAD_ERR_FORM_SIZE)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadFormSizeErrorMessage)
+ ->setCode(UPLOAD_ERR_FORM_SIZE)
+ ->addViolation();
+ }
+
+ return;
+ case UPLOAD_ERR_PARTIAL:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadPartialErrorMessage)
+ ->setCode(UPLOAD_ERR_PARTIAL)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadPartialErrorMessage)
+ ->setCode(UPLOAD_ERR_PARTIAL)
+ ->addViolation();
+ }
+
+ return;
+ case UPLOAD_ERR_NO_FILE:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadNoFileErrorMessage)
+ ->setCode(UPLOAD_ERR_NO_FILE)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadNoFileErrorMessage)
+ ->setCode(UPLOAD_ERR_NO_FILE)
+ ->addViolation();
+ }
+
+ return;
+ case UPLOAD_ERR_NO_TMP_DIR:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadNoTmpDirErrorMessage)
+ ->setCode(UPLOAD_ERR_NO_TMP_DIR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadNoTmpDirErrorMessage)
+ ->setCode(UPLOAD_ERR_NO_TMP_DIR)
+ ->addViolation();
+ }
+
+ return;
+ case UPLOAD_ERR_CANT_WRITE:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadCantWriteErrorMessage)
+ ->setCode(UPLOAD_ERR_CANT_WRITE)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadCantWriteErrorMessage)
+ ->setCode(UPLOAD_ERR_CANT_WRITE)
+ ->addViolation();
+ }
+
+ return;
+ case UPLOAD_ERR_EXTENSION:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadExtensionErrorMessage)
+ ->setCode(UPLOAD_ERR_EXTENSION)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadExtensionErrorMessage)
+ ->setCode(UPLOAD_ERR_EXTENSION)
+ ->addViolation();
+ }
+
+ return;
+ default:
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->uploadErrorMessage)
+ ->setCode($value->getError())
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->uploadErrorMessage)
+ ->setCode($value->getError())
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ if (!is_scalar($value) && !$value instanceof FileObject && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $path = $value instanceof FileObject ? $value->getPathname() : (string) $value;
+
+ if (!is_file($path)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->notFoundMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setCode(File::NOT_FOUND_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->notFoundMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setCode(File::NOT_FOUND_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (!is_readable($path)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->notReadableMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setCode(File::NOT_READABLE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->notReadableMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setCode(File::NOT_READABLE_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $sizeInBytes = filesize($path);
+
+ if (0 === $sizeInBytes) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->disallowEmptyMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setCode(File::EMPTY_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->disallowEmptyMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setCode(File::EMPTY_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if ($constraint->maxSize) {
+ $limitInBytes = $constraint->maxSize;
+
+ if ($sizeInBytes > $limitInBytes) {
+ list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes($sizeInBytes, $limitInBytes, $constraint->binaryFormat);
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->maxSizeMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setParameter('{{ size }}', $sizeAsString)
+ ->setParameter('{{ limit }}', $limitAsString)
+ ->setParameter('{{ suffix }}', $suffix)
+ ->setCode(File::TOO_LARGE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->maxSizeMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setParameter('{{ size }}', $sizeAsString)
+ ->setParameter('{{ limit }}', $limitAsString)
+ ->setParameter('{{ suffix }}', $suffix)
+ ->setCode(File::TOO_LARGE_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ if ($constraint->mimeTypes) {
+ if (!$value instanceof FileObject) {
+ $value = new FileObject($value);
+ }
+
+ $mimeTypes = (array) $constraint->mimeTypes;
+ $mime = $value->getMimeType();
+
+ foreach ($mimeTypes as $mimeType) {
+ if ($mimeType === $mime) {
+ return;
+ }
+
+ if ($discrete = strstr($mimeType, '/*', true)) {
+ if (strstr($mime, '/', true) === $discrete) {
+ return;
+ }
+ }
+ }
+
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->mimeTypesMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setParameter('{{ type }}', $this->formatValue($mime))
+ ->setParameter('{{ types }}', $this->formatValues($mimeTypes))
+ ->setCode(File::INVALID_MIME_TYPE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->mimeTypesMessage)
+ ->setParameter('{{ file }}', $this->formatValue($path))
+ ->setParameter('{{ type }}', $this->formatValue($mime))
+ ->setParameter('{{ types }}', $this->formatValues($mimeTypes))
+ ->setCode(File::INVALID_MIME_TYPE_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ private static function moreDecimalsThan($double, $numberOfDecimals)
+ {
+ return \strlen((string) $double) > \strlen(round($double, $numberOfDecimals));
+ }
+
+ /**
+ * Convert the limit to the smallest possible number
+ * (i.e. try "MB", then "kB", then "bytes").
+ */
+ private function factorizeSizes($size, $limit, $binaryFormat)
+ {
+ if ($binaryFormat) {
+ $coef = self::MIB_BYTES;
+ $coefFactor = self::KIB_BYTES;
+ } else {
+ $coef = self::MB_BYTES;
+ $coefFactor = self::KB_BYTES;
+ }
+
+ $limitAsString = (string) ($limit / $coef);
+
+ // Restrict the limit to 2 decimals (without rounding! we
+ // need the precise value)
+ while (self::moreDecimalsThan($limitAsString, 2)) {
+ $coef /= $coefFactor;
+ $limitAsString = (string) ($limit / $coef);
+ }
+
+ // Convert size to the same measure, but round to 2 decimals
+ $sizeAsString = (string) round($size / $coef, 2);
+
+ // If the size and limit produce the same string output
+ // (due to rounding), reduce the coefficient
+ while ($sizeAsString === $limitAsString) {
+ $coef /= $coefFactor;
+ $limitAsString = (string) ($limit / $coef);
+ $sizeAsString = (string) round($size / $coef, 2);
+ }
+
+ return array($sizeAsString, $limitAsString, self::$suffices[$coef]);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/GreaterThan.php b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThan.php
new file mode 100644
index 0000000..c2ca2dc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThan.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GreaterThan extends AbstractComparison
+{
+ const TOO_LOW_ERROR = '778b7ae0-84d3-481a-9dec-35fdb64b1d78';
+
+ protected static $errorNames = array(
+ self::TOO_LOW_ERROR => 'TOO_LOW_ERROR',
+ );
+
+ public $message = 'This value should be greater than {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqual.php b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqual.php
new file mode 100644
index 0000000..9b3743d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqual.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GreaterThanOrEqual extends AbstractComparison
+{
+ const TOO_LOW_ERROR = 'ea4e51d1-3342-48bd-87f1-9e672cd90cad';
+
+ protected static $errorNames = array(
+ self::TOO_LOW_ERROR => 'TOO_LOW_ERROR',
+ );
+
+ public $message = 'This value should be greater than or equal to {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqualValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqualValidator.php
new file mode 100644
index 0000000..e196e68
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanOrEqualValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are greater than or equal to the previous (>=).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GreaterThanOrEqualValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 >= $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return GreaterThanOrEqual::TOO_LOW_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanValidator.php
new file mode 100644
index 0000000..9029e8f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/GreaterThanValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are greater than the previous (>).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GreaterThanValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 > $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return GreaterThan::TOO_LOW_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/GroupSequence.php b/public/system/storage/vendor/symfony/validator/Constraints/GroupSequence.php
new file mode 100644
index 0000000..d2c4d4a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/GroupSequence.php
@@ -0,0 +1,208 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Exception\OutOfBoundsException;
+
+/**
+ * A sequence of validation groups.
+ *
+ * When validating a group sequence, each group will only be validated if all
+ * of the previous groups in the sequence succeeded. For example:
+ *
+ * $validator->validate($address, null, new GroupSequence(array('Basic', 'Strict')));
+ *
+ * In the first step, all constraints that belong to the group "Basic" will be
+ * validated. If none of the constraints fail, the validator will then validate
+ * the constraints in group "Strict". This is useful, for example, if "Strict"
+ * contains expensive checks that require a lot of CPU or slow, external
+ * services. You usually don't want to run expensive checks if any of the cheap
+ * checks fail.
+ *
+ * When adding metadata to a class, you can override the "Default" group of
+ * that class with a group sequence:
+ *
+ * /**
+ * * @GroupSequence({"Address", "Strict"})
+ * *\/
+ * class Address
+ * {
+ * // ...
+ * }
+ *
+ * Whenever you validate that object in the "Default" group, the group sequence
+ * will be validated:
+ *
+ * $validator->validate($address);
+ *
+ * If you want to execute the constraints of the "Default" group for a class
+ * with an overridden default group, pass the class name as group name instead:
+ *
+ * $validator->validate($address, null, "Address")
+ *
+ * @Annotation
+ * @Target({"CLASS", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * Implementing \ArrayAccess, \IteratorAggregate and \Countable is @deprecated since 2.5 and will be removed in 3.0.
+ */
+class GroupSequence implements \ArrayAccess, \IteratorAggregate, \Countable
+{
+ /**
+ * The groups in the sequence.
+ *
+ * @var string[]|GroupSequence[]
+ */
+ public $groups;
+
+ /**
+ * The group in which cascaded objects are validated when validating
+ * this sequence.
+ *
+ * By default, cascaded objects are validated in each of the groups of
+ * the sequence.
+ *
+ * If a class has a group sequence attached, that sequence replaces the
+ * "Default" group. When validating that class in the "Default" group, the
+ * group sequence is used instead, but still the "Default" group should be
+ * cascaded to other objects.
+ *
+ * @var string|GroupSequence
+ */
+ public $cascadedGroup;
+
+ /**
+ * Creates a new group sequence.
+ *
+ * @param string[] $groups The groups in the sequence
+ */
+ public function __construct(array $groups)
+ {
+ // Support for Doctrine annotations
+ $this->groups = isset($groups['value']) ? $groups['value'] : $groups;
+ }
+
+ /**
+ * Returns an iterator for this group.
+ *
+ * Implemented for backwards compatibility with Symfony < 2.5.
+ *
+ * @return \Traversable The iterator
+ *
+ * @see \IteratorAggregate::getIterator()
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function getIterator()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ return new \ArrayIterator($this->groups);
+ }
+
+ /**
+ * Returns whether the given offset exists in the sequence.
+ *
+ * Implemented for backwards compatibility with Symfony < 2.5.
+ *
+ * @param int $offset The offset
+ *
+ * @return bool Whether the offset exists
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function offsetExists($offset)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ return isset($this->groups[$offset]);
+ }
+
+ /**
+ * Returns the group at the given offset.
+ *
+ * Implemented for backwards compatibility with Symfony < 2.5.
+ *
+ * @param int $offset The offset
+ *
+ * @return string The group a the given offset
+ *
+ * @throws OutOfBoundsException If the object does not exist
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function offsetGet($offset)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ if (!isset($this->groups[$offset])) {
+ throw new OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset));
+ }
+
+ return $this->groups[$offset];
+ }
+
+ /**
+ * Sets the group at the given offset.
+ *
+ * Implemented for backwards compatibility with Symfony < 2.5.
+ *
+ * @param int $offset The offset
+ * @param string $value The group name
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function offsetSet($offset, $value)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ if (null !== $offset) {
+ $this->groups[$offset] = $value;
+
+ return;
+ }
+
+ $this->groups[] = $value;
+ }
+
+ /**
+ * Removes the group at the given offset.
+ *
+ * Implemented for backwards compatibility with Symfony < 2.5.
+ *
+ * @param int $offset The offset
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function offsetUnset($offset)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ unset($this->groups[$offset]);
+ }
+
+ /**
+ * Returns the number of groups in the sequence.
+ *
+ * Implemented for backwards compatibility with Symfony < 2.5.
+ *
+ * @return int The number of groups
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function count()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ return \count($this->groups);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/GroupSequenceProvider.php b/public/system/storage/vendor/symfony/validator/Constraints/GroupSequenceProvider.php
new file mode 100644
index 0000000..8a3fe63
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/GroupSequenceProvider.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Annotation to define a group sequence provider.
+ *
+ * @Annotation
+ * @Target({"CLASS", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GroupSequenceProvider
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Iban.php b/public/system/storage/vendor/symfony/validator/Constraints/Iban.php
new file mode 100644
index 0000000..9c4d383
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Iban.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Manuel Reinhard <manu@sprain.ch>
+ * @author Michael Schummel
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Iban extends Constraint
+{
+ /** @deprecated, to be removed in 3.0. */
+ const TOO_SHORT_ERROR = '88e5e319-0aeb-4979-a27e-3d9ce0c16166';
+ const INVALID_COUNTRY_CODE_ERROR = 'de78ee2c-bd50-44e2-aec8-3d8228aeadb9';
+ const INVALID_CHARACTERS_ERROR = '8d3d85e4-784f-4719-a5bc-d9e40d45a3a5';
+ /** @deprecated, to be removed in 3.0. */
+ const INVALID_CASE_ERROR = 'f4bf62fe-03ec-42af-a53b-68e21b1e7274';
+ const CHECKSUM_FAILED_ERROR = 'b9401321-f9bf-4dcb-83c1-f31094440795';
+ const INVALID_FORMAT_ERROR = 'c8d318f1-2ecc-41ba-b983-df70d225cf5a';
+ const NOT_SUPPORTED_COUNTRY_CODE_ERROR = 'e2c259f3-4b46-48e6-b72e-891658158ec8';
+
+ protected static $errorNames = array(
+ self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
+ self::INVALID_COUNTRY_CODE_ERROR => 'INVALID_COUNTRY_CODE_ERROR',
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR',
+ self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
+ self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
+ self::NOT_SUPPORTED_COUNTRY_CODE_ERROR => 'NOT_SUPPORTED_COUNTRY_CODE_ERROR',
+ );
+
+ public $message = 'This is not a valid International Bank Account Number (IBAN).';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IbanValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IbanValidator.php
new file mode 100644
index 0000000..d475332
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IbanValidator.php
@@ -0,0 +1,293 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Manuel Reinhard <manu@sprain.ch>
+ * @author Michael Schummel
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/
+ */
+class IbanValidator extends ConstraintValidator
+{
+ /**
+ * IBAN country specific formats.
+ *
+ * The first 2 characters from an IBAN format are the two-character ISO country code.
+ * The following 2 characters represent the check digits calculated from the rest of the IBAN characters.
+ * The rest are up to thirty alphanumeric characters for
+ * a BBAN (Basic Bank Account Number) which has a fixed length per country and,
+ * included within it, a bank identifier with a fixed position and a fixed length per country
+ *
+ * @see https://www.swift.com/sites/default/files/resources/iban_registry.pdf
+ */
+ private static $formats = array(
+ 'AD' => 'AD\d{2}\d{4}\d{4}[\dA-Z]{12}', // Andorra
+ 'AE' => 'AE\d{2}\d{3}\d{16}', // United Arab Emirates
+ 'AL' => 'AL\d{2}\d{8}[\dA-Z]{16}', // Albania
+ 'AO' => 'AO\d{2}\d{21}', // Angola
+ 'AT' => 'AT\d{2}\d{5}\d{11}', // Austria
+ 'AX' => 'FI\d{2}\d{6}\d{7}\d{1}', // Aland Islands
+ 'AZ' => 'AZ\d{2}[A-Z]{4}[\dA-Z]{20}', // Azerbaijan
+ 'BA' => 'BA\d{2}\d{3}\d{3}\d{8}\d{2}', // Bosnia and Herzegovina
+ 'BE' => 'BE\d{2}\d{3}\d{7}\d{2}', // Belgium
+ 'BF' => 'BF\d{2}\d{23}', // Burkina Faso
+ 'BG' => 'BG\d{2}[A-Z]{4}\d{4}\d{2}[\dA-Z]{8}', // Bulgaria
+ 'BH' => 'BH\d{2}[A-Z]{4}[\dA-Z]{14}', // Bahrain
+ 'BI' => 'BI\d{2}\d{12}', // Burundi
+ 'BJ' => 'BJ\d{2}[A-Z]{1}\d{23}', // Benin
+ 'BY' => 'BY\d{2}[\dA-Z]{4}\d{4}[\dA-Z]{16}', // Belarus - https://bank.codes/iban/structure/belarus/
+ 'BL' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Barthelemy
+ 'BR' => 'BR\d{2}\d{8}\d{5}\d{10}[A-Z][\dA-Z]', // Brazil
+ 'CG' => 'CG\d{2}\d{23}', // Congo
+ 'CH' => 'CH\d{2}\d{5}[\dA-Z]{12}', // Switzerland
+ 'CI' => 'CI\d{2}[A-Z]{1}\d{23}', // Ivory Coast
+ 'CM' => 'CM\d{2}\d{23}', // Cameron
+ 'CR' => 'CR\d{2}0\d{3}\d{14}', // Costa Rica
+ 'CV' => 'CV\d{2}\d{21}', // Cape Verde
+ 'CY' => 'CY\d{2}\d{3}\d{5}[\dA-Z]{16}', // Cyprus
+ 'CZ' => 'CZ\d{2}\d{20}', // Czech Republic
+ 'DE' => 'DE\d{2}\d{8}\d{10}', // Germany
+ 'DO' => 'DO\d{2}[\dA-Z]{4}\d{20}', // Dominican Republic
+ 'DK' => 'DK\d{2}\d{4}\d{10}', // Denmark
+ 'DZ' => 'DZ\d{2}\d{20}', // Algeria
+ 'EE' => 'EE\d{2}\d{2}\d{2}\d{11}\d{1}', // Estonia
+ 'ES' => 'ES\d{2}\d{4}\d{4}\d{1}\d{1}\d{10}', // Spain (also includes Canary Islands, Ceuta and Melilla)
+ 'FI' => 'FI\d{2}\d{6}\d{7}\d{1}', // Finland
+ 'FO' => 'FO\d{2}\d{4}\d{9}\d{1}', // Faroe Islands
+ 'FR' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // France
+ 'GF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Guyana
+ 'GB' => 'GB\d{2}[A-Z]{4}\d{6}\d{8}', // United Kingdom of Great Britain and Northern Ireland
+ 'GE' => 'GE\d{2}[A-Z]{2}\d{16}', // Georgia
+ 'GI' => 'GI\d{2}[A-Z]{4}[\dA-Z]{15}', // Gibraltar
+ 'GL' => 'GL\d{2}\d{4}\d{9}\d{1}', // Greenland
+ 'GP' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Guadeloupe
+ 'GR' => 'GR\d{2}\d{3}\d{4}[\dA-Z]{16}', // Greece
+ 'GT' => 'GT\d{2}[\dA-Z]{4}[\dA-Z]{20}', // Guatemala
+ 'HR' => 'HR\d{2}\d{7}\d{10}', // Croatia
+ 'HU' => 'HU\d{2}\d{3}\d{4}\d{1}\d{15}\d{1}', // Hungary
+ 'IE' => 'IE\d{2}[A-Z]{4}\d{6}\d{8}', // Ireland
+ 'IL' => 'IL\d{2}\d{3}\d{3}\d{13}', // Israel
+ 'IR' => 'IR\d{2}\d{22}', // Iran
+ 'IS' => 'IS\d{2}\d{4}\d{2}\d{6}\d{10}', // Iceland
+ 'IT' => 'IT\d{2}[A-Z]{1}\d{5}\d{5}[\dA-Z]{12}', // Italy
+ 'JO' => 'JO\d{2}[A-Z]{4}\d{4}[\dA-Z]{18}', // Jordan
+ 'KW' => 'KW\d{2}[A-Z]{4}\d{22}', // KUWAIT
+ 'KZ' => 'KZ\d{2}\d{3}[\dA-Z]{13}', // Kazakhstan
+ 'LB' => 'LB\d{2}\d{4}[\dA-Z]{20}', // LEBANON
+ 'LI' => 'LI\d{2}\d{5}[\dA-Z]{12}', // Liechtenstein (Principality of)
+ 'LT' => 'LT\d{2}\d{5}\d{11}', // Lithuania
+ 'LU' => 'LU\d{2}\d{3}[\dA-Z]{13}', // Luxembourg
+ 'LV' => 'LV\d{2}[A-Z]{4}[\dA-Z]{13}', // Latvia
+ 'MC' => 'MC\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Monaco
+ 'MD' => 'MD\d{2}[\dA-Z]{2}[\dA-Z]{18}', // Moldova
+ 'ME' => 'ME\d{2}\d{3}\d{13}\d{2}', // Montenegro
+ 'MF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Martin (French part)
+ 'MG' => 'MG\d{2}\d{23}', // Madagascar
+ 'MK' => 'MK\d{2}\d{3}[\dA-Z]{10}\d{2}', // Macedonia, Former Yugoslav Republic of
+ 'ML' => 'ML\d{2}[A-Z]{1}\d{23}', // Mali
+ 'MQ' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Martinique
+ 'MR' => 'MR13\d{5}\d{5}\d{11}\d{2}', // Mauritania
+ 'MT' => 'MT\d{2}[A-Z]{4}\d{5}[\dA-Z]{18}', // Malta
+ 'MU' => 'MU\d{2}[A-Z]{4}\d{2}\d{2}\d{12}\d{3}[A-Z]{3}', // Mauritius
+ 'MZ' => 'MZ\d{2}\d{21}', // Mozambique
+ 'NC' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // New Caledonia
+ 'NL' => 'NL\d{2}[A-Z]{4}\d{10}', // The Netherlands
+ 'NO' => 'NO\d{2}\d{4}\d{6}\d{1}', // Norway
+ 'PF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Polynesia
+ 'PK' => 'PK\d{2}[A-Z]{4}[\dA-Z]{16}', // Pakistan
+ 'PL' => 'PL\d{2}\d{8}\d{16}', // Poland
+ 'PM' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Saint Pierre et Miquelon
+ 'PS' => 'PS\d{2}[A-Z]{4}[\dA-Z]{21}', // Palestine, State of
+ 'PT' => 'PT\d{2}\d{4}\d{4}\d{11}\d{2}', // Portugal (plus Azores and Madeira)
+ 'QA' => 'QA\d{2}[A-Z]{4}[\dA-Z]{21}', // Qatar
+ 'RE' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Reunion
+ 'RO' => 'RO\d{2}[A-Z]{4}[\dA-Z]{16}', // Romania
+ 'RS' => 'RS\d{2}\d{3}\d{13}\d{2}', // Serbia
+ 'SA' => 'SA\d{2}\d{2}[\dA-Z]{18}', // Saudi Arabia
+ 'SE' => 'SE\d{2}\d{3}\d{16}\d{1}', // Sweden
+ 'SI' => 'SI\d{2}\d{5}\d{8}\d{2}', // Slovenia
+ 'SK' => 'SK\d{2}\d{4}\d{6}\d{10}', // Slovak Republic
+ 'SM' => 'SM\d{2}[A-Z]{1}\d{5}\d{5}[\dA-Z]{12}', // San Marino
+ 'SN' => 'SN\d{2}[A-Z]{1}\d{23}', // Senegal
+ 'TF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // French Southern Territories
+ 'TL' => 'TL\d{2}\d{3}\d{14}\d{2}', // Timor-Leste
+ 'TN' => 'TN59\d{2}\d{3}\d{13}\d{2}', // Tunisia
+ 'TR' => 'TR\d{2}\d{5}[\dA-Z]{1}[\dA-Z]{16}', // Turkey
+ 'UA' => 'UA\d{2}\d{6}[\dA-Z]{19}', // Ukraine
+ 'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands, British
+ 'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Wallis and Futuna Islands
+ 'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Republic of Kosovo
+ 'YT' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Mayotte
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Iban) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Iban');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ // Remove spaces and convert to uppercase
+ $canonicalized = str_replace(' ', '', strtoupper($value));
+
+ // The IBAN must contain only digits and characters...
+ if (!ctype_alnum($canonicalized)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // ...start with a two-letter country code
+ $countryCode = substr($canonicalized, 0, 2);
+
+ if (!ctype_alpha($countryCode)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::INVALID_COUNTRY_CODE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::INVALID_COUNTRY_CODE_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // ...have a format available
+ if (!array_key_exists($countryCode, self::$formats)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // ...and have a valid format
+ if (!preg_match('/^'.self::$formats[$countryCode].'$/', $canonicalized)
+ ) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // Move the first four characters to the end
+ // e.g. CH93 0076 2011 6238 5295 7
+ // -> 0076 2011 6238 5295 7 CH93
+ $canonicalized = substr($canonicalized, 4).substr($canonicalized, 0, 4);
+
+ // Convert all remaining letters to their ordinals
+ // The result is an integer, which is too large for PHP's int
+ // data type, so we store it in a string instead.
+ // e.g. 0076 2011 6238 5295 7 CH93
+ // -> 0076 2011 6238 5295 7 121893
+ $checkSum = self::toBigInt($canonicalized);
+
+ // Do a modulo-97 operation on the large integer
+ // We cannot use PHP's modulo operator, so we calculate the
+ // modulo step-wisely instead
+ if (1 !== self::bigModulo97($checkSum)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::CHECKSUM_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Iban::CHECKSUM_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ private static function toBigInt($string)
+ {
+ $chars = str_split($string);
+ $bigInt = '';
+
+ foreach ($chars as $char) {
+ // Convert uppercase characters to ordinals, starting with 10 for "A"
+ if (ctype_upper($char)) {
+ $bigInt .= (\ord($char) - 55);
+
+ continue;
+ }
+
+ // Simply append digits
+ $bigInt .= $char;
+ }
+
+ return $bigInt;
+ }
+
+ private static function bigModulo97($bigInt)
+ {
+ $parts = str_split($bigInt, 7);
+ $rest = 0;
+
+ foreach ($parts as $part) {
+ $rest = ($rest.$part) % 97;
+ }
+
+ return $rest;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IdenticalTo.php b/public/system/storage/vendor/symfony/validator/Constraints/IdenticalTo.php
new file mode 100644
index 0000000..a7dadff
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IdenticalTo.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IdenticalTo extends AbstractComparison
+{
+ const NOT_IDENTICAL_ERROR = '2a8cc50f-58a2-4536-875e-060a2ce69ed5';
+
+ protected static $errorNames = array(
+ self::NOT_IDENTICAL_ERROR => 'NOT_IDENTICAL_ERROR',
+ );
+
+ public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IdenticalToValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IdenticalToValidator.php
new file mode 100644
index 0000000..304f71f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IdenticalToValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are identical (===).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IdenticalToValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 === $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return IdenticalTo::NOT_IDENTICAL_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Image.php b/public/system/storage/vendor/symfony/validator/Constraints/Image.php
new file mode 100644
index 0000000..28803c4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Image.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Benjamin Dulau <benjamin.dulau@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Image extends File
+{
+ const SIZE_NOT_DETECTED_ERROR = '6d55c3f4-e58e-4fe3-91ee-74b492199956';
+ const TOO_WIDE_ERROR = '7f87163d-878f-47f5-99ba-a8eb723a1ab2';
+ const TOO_NARROW_ERROR = '9afbd561-4f90-4a27-be62-1780fc43604a';
+ const TOO_HIGH_ERROR = '7efae81c-4877-47ba-aa65-d01ccb0d4645';
+ const TOO_LOW_ERROR = 'aef0cb6a-c07f-4894-bc08-1781420d7b4c';
+ const RATIO_TOO_BIG_ERROR = '70cafca6-168f-41c9-8c8c-4e47a52be643';
+ const RATIO_TOO_SMALL_ERROR = '59b8c6ef-bcf2-4ceb-afff-4642ed92f12e';
+ const SQUARE_NOT_ALLOWED_ERROR = '5d41425b-facb-47f7-a55a-de9fbe45cb46';
+ const LANDSCAPE_NOT_ALLOWED_ERROR = '6f895685-7cf2-4d65-b3da-9029c5581d88';
+ const PORTRAIT_NOT_ALLOWED_ERROR = '65608156-77da-4c79-a88c-02ef6d18c782';
+
+ // Include the mapping from the base class
+
+ protected static $errorNames = array(
+ self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR',
+ self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR',
+ self::EMPTY_ERROR => 'EMPTY_ERROR',
+ self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR',
+ self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR',
+ self::SIZE_NOT_DETECTED_ERROR => 'SIZE_NOT_DETECTED_ERROR',
+ self::TOO_WIDE_ERROR => 'TOO_WIDE_ERROR',
+ self::TOO_NARROW_ERROR => 'TOO_NARROW_ERROR',
+ self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR',
+ self::TOO_LOW_ERROR => 'TOO_LOW_ERROR',
+ self::RATIO_TOO_BIG_ERROR => 'RATIO_TOO_BIG_ERROR',
+ self::RATIO_TOO_SMALL_ERROR => 'RATIO_TOO_SMALL_ERROR',
+ self::SQUARE_NOT_ALLOWED_ERROR => 'SQUARE_NOT_ALLOWED_ERROR',
+ self::LANDSCAPE_NOT_ALLOWED_ERROR => 'LANDSCAPE_NOT_ALLOWED_ERROR',
+ self::PORTRAIT_NOT_ALLOWED_ERROR => 'PORTRAIT_NOT_ALLOWED_ERROR',
+ );
+
+ public $mimeTypes = 'image/*';
+ public $minWidth;
+ public $maxWidth;
+ public $maxHeight;
+ public $minHeight;
+ public $maxRatio;
+ public $minRatio;
+ public $allowSquare = true;
+ public $allowLandscape = true;
+ public $allowPortrait = true;
+
+ // The constant for a wrong MIME type is taken from the parent class.
+ public $mimeTypesMessage = 'This file is not a valid image.';
+ public $sizeNotDetectedMessage = 'The size of the image could not be detected.';
+ public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.';
+ public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.';
+ public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.';
+ public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.';
+ public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.';
+ public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.';
+ public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.';
+ public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.';
+ public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/ImageValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/ImageValidator.php
new file mode 100644
index 0000000..35ff408
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/ImageValidator.php
@@ -0,0 +1,261 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value is a valid image file and is valid
+ * against minWidth, maxWidth, minHeight and maxHeight constraints.
+ *
+ * @author Benjamin Dulau <benjamin.dulau@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ImageValidator extends FileValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Image) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Image');
+ }
+
+ $violations = \count($this->context->getViolations());
+
+ parent::validate($value, $constraint);
+
+ $failed = \count($this->context->getViolations()) !== $violations;
+
+ if ($failed || null === $value || '' === $value) {
+ return;
+ }
+
+ if (null === $constraint->minWidth && null === $constraint->maxWidth
+ && null === $constraint->minHeight && null === $constraint->maxHeight
+ && null === $constraint->minRatio && null === $constraint->maxRatio
+ && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) {
+ return;
+ }
+
+ $size = @getimagesize($value);
+
+ if (empty($size) || (0 === $size[0]) || (0 === $size[1])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->sizeNotDetectedMessage)
+ ->setCode(Image::SIZE_NOT_DETECTED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->sizeNotDetectedMessage)
+ ->setCode(Image::SIZE_NOT_DETECTED_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $width = $size[0];
+ $height = $size[1];
+
+ if ($constraint->minWidth) {
+ if (!ctype_digit((string) $constraint->minWidth)) {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth));
+ }
+
+ if ($width < $constraint->minWidth) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->minWidthMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ min_width }}', $constraint->minWidth)
+ ->setCode(Image::TOO_NARROW_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->minWidthMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ min_width }}', $constraint->minWidth)
+ ->setCode(Image::TOO_NARROW_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ if ($constraint->maxWidth) {
+ if (!ctype_digit((string) $constraint->maxWidth)) {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth));
+ }
+
+ if ($width > $constraint->maxWidth) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->maxWidthMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ max_width }}', $constraint->maxWidth)
+ ->setCode(Image::TOO_WIDE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->maxWidthMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ max_width }}', $constraint->maxWidth)
+ ->setCode(Image::TOO_WIDE_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ if ($constraint->minHeight) {
+ if (!ctype_digit((string) $constraint->minHeight)) {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight));
+ }
+
+ if ($height < $constraint->minHeight) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->minHeightMessage)
+ ->setParameter('{{ height }}', $height)
+ ->setParameter('{{ min_height }}', $constraint->minHeight)
+ ->setCode(Image::TOO_LOW_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->minHeightMessage)
+ ->setParameter('{{ height }}', $height)
+ ->setParameter('{{ min_height }}', $constraint->minHeight)
+ ->setCode(Image::TOO_LOW_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ if ($constraint->maxHeight) {
+ if (!ctype_digit((string) $constraint->maxHeight)) {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight));
+ }
+
+ if ($height > $constraint->maxHeight) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->maxHeightMessage)
+ ->setParameter('{{ height }}', $height)
+ ->setParameter('{{ max_height }}', $constraint->maxHeight)
+ ->setCode(Image::TOO_HIGH_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->maxHeightMessage)
+ ->setParameter('{{ height }}', $height)
+ ->setParameter('{{ max_height }}', $constraint->maxHeight)
+ ->setCode(Image::TOO_HIGH_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ $ratio = round($width / $height, 2);
+
+ if (null !== $constraint->minRatio) {
+ if (!is_numeric((string) $constraint->minRatio)) {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
+ }
+
+ if ($ratio < $constraint->minRatio) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->minRatioMessage)
+ ->setParameter('{{ ratio }}', $ratio)
+ ->setParameter('{{ min_ratio }}', $constraint->minRatio)
+ ->setCode(Image::RATIO_TOO_SMALL_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->minRatioMessage)
+ ->setParameter('{{ ratio }}', $ratio)
+ ->setParameter('{{ min_ratio }}', $constraint->minRatio)
+ ->setCode(Image::RATIO_TOO_SMALL_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ if (null !== $constraint->maxRatio) {
+ if (!is_numeric((string) $constraint->maxRatio)) {
+ throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
+ }
+
+ if ($ratio > $constraint->maxRatio) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->maxRatioMessage)
+ ->setParameter('{{ ratio }}', $ratio)
+ ->setParameter('{{ max_ratio }}', $constraint->maxRatio)
+ ->setCode(Image::RATIO_TOO_BIG_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->maxRatioMessage)
+ ->setParameter('{{ ratio }}', $ratio)
+ ->setParameter('{{ max_ratio }}', $constraint->maxRatio)
+ ->setCode(Image::RATIO_TOO_BIG_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ if (!$constraint->allowSquare && $width == $height) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->allowSquareMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ height }}', $height)
+ ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->allowSquareMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ height }}', $height)
+ ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
+ ->addViolation();
+ }
+ }
+
+ if (!$constraint->allowLandscape && $width > $height) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->allowLandscapeMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ height }}', $height)
+ ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->allowLandscapeMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ height }}', $height)
+ ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
+ ->addViolation();
+ }
+ }
+
+ if (!$constraint->allowPortrait && $width < $height) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->allowPortraitMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ height }}', $height)
+ ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->allowPortraitMessage)
+ ->setParameter('{{ width }}', $width)
+ ->setParameter('{{ height }}', $height)
+ ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Ip.php b/public/system/storage/vendor/symfony/validator/Constraints/Ip.php
new file mode 100644
index 0000000..f45c4ca
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Ip.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * Validates that a value is a valid IP address.
+ *
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ * @author Joseph Bielawski <stloyd@gmail.com>
+ */
+class Ip extends Constraint
+{
+ const V4 = '4';
+ const V6 = '6';
+ const ALL = 'all';
+
+ // adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges)
+ const V4_NO_PRIV = '4_no_priv';
+ const V6_NO_PRIV = '6_no_priv';
+ const ALL_NO_PRIV = 'all_no_priv';
+
+ // adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges)
+ const V4_NO_RES = '4_no_res';
+ const V6_NO_RES = '6_no_res';
+ const ALL_NO_RES = 'all_no_res';
+
+ // adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both)
+ const V4_ONLY_PUBLIC = '4_public';
+ const V6_ONLY_PUBLIC = '6_public';
+ const ALL_ONLY_PUBLIC = 'all_public';
+
+ const INVALID_IP_ERROR = 'b1b427ae-9f6f-41b0-aa9b-84511fbb3c5b';
+
+ protected static $versions = array(
+ self::V4,
+ self::V6,
+ self::ALL,
+
+ self::V4_NO_PRIV,
+ self::V6_NO_PRIV,
+ self::ALL_NO_PRIV,
+
+ self::V4_NO_RES,
+ self::V6_NO_RES,
+ self::ALL_NO_RES,
+
+ self::V4_ONLY_PUBLIC,
+ self::V6_ONLY_PUBLIC,
+ self::ALL_ONLY_PUBLIC,
+ );
+
+ protected static $errorNames = array(
+ self::INVALID_IP_ERROR => 'INVALID_IP_ERROR',
+ );
+
+ public $version = self::V4;
+
+ public $message = 'This is not a valid IP address.';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($options = null)
+ {
+ parent::__construct($options);
+
+ if (!\in_array($this->version, self::$versions)) {
+ throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions)));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IpValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IpValidator.php
new file mode 100644
index 0000000..a27d0e0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IpValidator.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value is a valid IP address.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ * @author Joseph Bielawski <stloyd@gmail.com>
+ */
+class IpValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Ip) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Ip');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ switch ($constraint->version) {
+ case Ip::V4:
+ $flag = FILTER_FLAG_IPV4;
+ break;
+
+ case Ip::V6:
+ $flag = FILTER_FLAG_IPV6;
+ break;
+
+ case Ip::V4_NO_PRIV:
+ $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE;
+ break;
+
+ case Ip::V6_NO_PRIV:
+ $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE;
+ break;
+
+ case Ip::ALL_NO_PRIV:
+ $flag = FILTER_FLAG_NO_PRIV_RANGE;
+ break;
+
+ case Ip::V4_NO_RES:
+ $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE;
+ break;
+
+ case Ip::V6_NO_RES:
+ $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE;
+ break;
+
+ case Ip::ALL_NO_RES:
+ $flag = FILTER_FLAG_NO_RES_RANGE;
+ break;
+
+ case Ip::V4_ONLY_PUBLIC:
+ $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
+ break;
+
+ case Ip::V6_ONLY_PUBLIC:
+ $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
+ break;
+
+ case Ip::ALL_ONLY_PUBLIC:
+ $flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
+ break;
+
+ default:
+ $flag = null;
+ break;
+ }
+
+ if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsFalse.php b/public/system/storage/vendor/symfony/validator/Constraints/IsFalse.php
new file mode 100644
index 0000000..8332e18
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsFalse.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IsFalse extends Constraint
+{
+ const NOT_FALSE_ERROR = 'd53a91b0-def3-426a-83d7-269da7ab4200';
+
+ protected static $errorNames = array(
+ self::NOT_FALSE_ERROR => 'NOT_FALSE_ERROR',
+ );
+
+ public $message = 'This value should be false.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsFalseValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IsFalseValidator.php
new file mode 100644
index 0000000..ff8e17e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsFalseValidator.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IsFalseValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof IsFalse) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsFalse');
+ }
+
+ if (null === $value || false === $value || 0 === $value || '0' === $value) {
+ return;
+ }
+
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(IsFalse::NOT_FALSE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(IsFalse::NOT_FALSE_ERROR)
+ ->addViolation();
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsNull.php b/public/system/storage/vendor/symfony/validator/Constraints/IsNull.php
new file mode 100644
index 0000000..fdd2930
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsNull.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IsNull extends Constraint
+{
+ const NOT_NULL_ERROR = '60d2f30b-8cfa-4372-b155-9656634de120';
+
+ protected static $errorNames = array(
+ self::NOT_NULL_ERROR => 'NOT_NULL_ERROR',
+ );
+
+ public $message = 'This value should be null.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsNullValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IsNullValidator.php
new file mode 100644
index 0000000..6e132c2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsNullValidator.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IsNullValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof IsNull) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsNull');
+ }
+
+ if (null !== $value) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(IsNull::NOT_NULL_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(IsNull::NOT_NULL_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsTrue.php b/public/system/storage/vendor/symfony/validator/Constraints/IsTrue.php
new file mode 100644
index 0000000..405a96a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsTrue.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IsTrue extends Constraint
+{
+ const NOT_TRUE_ERROR = '2beabf1c-54c0-4882-a928-05249b26e23b';
+
+ protected static $errorNames = array(
+ self::NOT_TRUE_ERROR => 'NOT_TRUE_ERROR',
+ );
+
+ public $message = 'This value should be true.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsTrueValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IsTrueValidator.php
new file mode 100644
index 0000000..5fd5793
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsTrueValidator.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class IsTrueValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof IsTrue) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsTrue');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ if (true !== $value && 1 !== $value && '1' !== $value) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(IsTrue::NOT_TRUE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(IsTrue::NOT_TRUE_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Isbn.php b/public/system/storage/vendor/symfony/validator/Constraints/Isbn.php
new file mode 100644
index 0000000..f1e83b9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Isbn.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
+ * @author Manuel Reinhard <manu@sprain.ch>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Isbn extends Constraint
+{
+ const TOO_SHORT_ERROR = '949acbb0-8ef5-43ed-a0e9-032dfd08ae45';
+ const TOO_LONG_ERROR = '3171387d-f80a-47b3-bd6e-60598545316a';
+ const INVALID_CHARACTERS_ERROR = '23d21cea-da99-453d-98b1-a7d916fbb339';
+ const CHECKSUM_FAILED_ERROR = '2881c032-660f-46b6-8153-d352d9706640';
+ const TYPE_NOT_RECOGNIZED_ERROR = 'fa54a457-f042-441f-89c4-066ee5bdd3e1';
+
+ protected static $errorNames = array(
+ self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
+ self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
+ self::TYPE_NOT_RECOGNIZED_ERROR => 'TYPE_NOT_RECOGNIZED_ERROR',
+ );
+
+ public $isbn10Message = 'This value is not a valid ISBN-10.';
+ public $isbn13Message = 'This value is not a valid ISBN-13.';
+ public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.';
+ public $type;
+ public $message;
+
+ /**
+ * @deprecated since version 2.5, to be removed in 3.0. Use option "type" instead.
+ *
+ * @var bool
+ */
+ public $isbn10 = false;
+
+ /**
+ * @deprecated since version 2.5, to be removed in 3.0. Use option "type" instead.
+ *
+ * @var bool
+ */
+ public $isbn13 = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'type';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IsbnValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IsbnValidator.php
new file mode 100644
index 0000000..838f672
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IsbnValidator.php
@@ -0,0 +1,216 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether the value is a valid ISBN-10 or ISBN-13.
+ *
+ * @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
+ * @author Manuel Reinhard <manu@sprain.ch>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see https://en.wikipedia.org/wiki/Isbn
+ */
+class IsbnValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Isbn) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Isbn');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ $canonical = str_replace('-', '', $value);
+
+ if (null === $constraint->type) {
+ if ($constraint->isbn10 && !$constraint->isbn13) {
+ @trigger_error('The "isbn10" option of the Isbn constraint is deprecated since Symfony 2.5 and will be removed in 3.0. Use the "type" option instead.', E_USER_DEPRECATED);
+ $constraint->type = 'isbn10';
+ } elseif ($constraint->isbn13 && !$constraint->isbn10) {
+ @trigger_error('The "isbn13" option of the Isbn constraint is deprecated since Symfony 2.5 and will be removed in 3.0. Use the "type" option instead.', E_USER_DEPRECATED);
+ $constraint->type = 'isbn13';
+ }
+ }
+
+ // Explicitly validate against ISBN-10
+ if ('isbn10' === $constraint->type) {
+ if (true !== ($code = $this->validateIsbn10($canonical))) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($this->getMessage($constraint, $constraint->type))
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode($code)
+ ->addViolation();
+ } else {
+ $this->buildViolation($this->getMessage($constraint, $constraint->type))
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode($code)
+ ->addViolation();
+ }
+ }
+
+ return;
+ }
+
+ // Explicitly validate against ISBN-13
+ if ('isbn13' === $constraint->type) {
+ if (true !== ($code = $this->validateIsbn13($canonical))) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($this->getMessage($constraint, $constraint->type))
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode($code)
+ ->addViolation();
+ } else {
+ $this->buildViolation($this->getMessage($constraint, $constraint->type))
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode($code)
+ ->addViolation();
+ }
+ }
+
+ return;
+ }
+
+ // Try both ISBNs
+
+ // First, try ISBN-10
+ $code = $this->validateIsbn10($canonical);
+
+ // The ISBN can only be an ISBN-13 if the value was too long for ISBN-10
+ if (Isbn::TOO_LONG_ERROR === $code) {
+ // Try ISBN-13 now
+ $code = $this->validateIsbn13($canonical);
+
+ // If too short, this means we have 11 or 12 digits
+ if (Isbn::TOO_SHORT_ERROR === $code) {
+ $code = Isbn::TYPE_NOT_RECOGNIZED_ERROR;
+ }
+ }
+
+ if (true !== $code) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($this->getMessage($constraint))
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode($code)
+ ->addViolation();
+ } else {
+ $this->buildViolation($this->getMessage($constraint))
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode($code)
+ ->addViolation();
+ }
+ }
+ }
+
+ protected function validateIsbn10($isbn)
+ {
+ // Choose an algorithm so that ERROR_INVALID_CHARACTERS is preferred
+ // over ERROR_TOO_SHORT/ERROR_TOO_LONG
+ // Otherwise "0-45122-5244" passes, but "0-45122_5244" reports
+ // "too long"
+
+ // Error priority:
+ // 1. ERROR_INVALID_CHARACTERS
+ // 2. ERROR_TOO_SHORT/ERROR_TOO_LONG
+ // 3. ERROR_CHECKSUM_FAILED
+
+ $checkSum = 0;
+
+ for ($i = 0; $i < 10; ++$i) {
+ // If we test the length before the loop, we get an ERROR_TOO_SHORT
+ // when actually an ERROR_INVALID_CHARACTERS is wanted, e.g. for
+ // "0-45122_5244" (typo)
+ if (!isset($isbn[$i])) {
+ return Isbn::TOO_SHORT_ERROR;
+ }
+
+ if ('X' === $isbn[$i]) {
+ $digit = 10;
+ } elseif (ctype_digit($isbn[$i])) {
+ $digit = $isbn[$i];
+ } else {
+ return Isbn::INVALID_CHARACTERS_ERROR;
+ }
+
+ $checkSum += $digit * (10 - $i);
+ }
+
+ if (isset($isbn[$i])) {
+ return Isbn::TOO_LONG_ERROR;
+ }
+
+ return 0 === $checkSum % 11 ? true : Isbn::CHECKSUM_FAILED_ERROR;
+ }
+
+ protected function validateIsbn13($isbn)
+ {
+ // Error priority:
+ // 1. ERROR_INVALID_CHARACTERS
+ // 2. ERROR_TOO_SHORT/ERROR_TOO_LONG
+ // 3. ERROR_CHECKSUM_FAILED
+
+ if (!ctype_digit($isbn)) {
+ return Isbn::INVALID_CHARACTERS_ERROR;
+ }
+
+ $length = \strlen($isbn);
+
+ if ($length < 13) {
+ return Isbn::TOO_SHORT_ERROR;
+ }
+
+ if ($length > 13) {
+ return Isbn::TOO_LONG_ERROR;
+ }
+
+ $checkSum = 0;
+
+ for ($i = 0; $i < 13; $i += 2) {
+ $checkSum += $isbn[$i];
+ }
+
+ for ($i = 1; $i < 12; $i += 2) {
+ $checkSum += $isbn[$i]
+ * 3;
+ }
+
+ return 0 === $checkSum % 10 ? true : Isbn::CHECKSUM_FAILED_ERROR;
+ }
+
+ protected function getMessage($constraint, $type = null)
+ {
+ if (null !== $constraint->message) {
+ return $constraint->message;
+ } elseif ('isbn10' === $type) {
+ return $constraint->isbn10Message;
+ } elseif ('isbn13' === $type) {
+ return $constraint->isbn13Message;
+ }
+
+ return $constraint->bothIsbnMessage;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Issn.php b/public/system/storage/vendor/symfony/validator/Constraints/Issn.php
new file mode 100644
index 0000000..a2fecdd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Issn.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Antonio J. García Lagar <aj@garcialagar.es>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Issn extends Constraint
+{
+ const TOO_SHORT_ERROR = '6a20dd3d-f463-4460-8e7b-18a1b98abbfb';
+ const TOO_LONG_ERROR = '37cef893-5871-464e-8b12-7fb79324833c';
+ const MISSING_HYPHEN_ERROR = '2983286f-8134-4693-957a-1ec4ef887b15';
+ const INVALID_CHARACTERS_ERROR = 'a663d266-37c2-4ece-a914-ae891940c588';
+ const INVALID_CASE_ERROR = '7b6dd393-7523-4a6c-b84d-72b91bba5e1a';
+ const CHECKSUM_FAILED_ERROR = 'b0f92dbc-667c-48de-b526-ad9586d43e85';
+
+ protected static $errorNames = array(
+ self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
+ self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
+ self::MISSING_HYPHEN_ERROR => 'MISSING_HYPHEN_ERROR',
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR',
+ self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
+ );
+
+ public $message = 'This value is not a valid ISSN.';
+ public $caseSensitive = false;
+ public $requireHyphen = false;
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/IssnValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/IssnValidator.php
new file mode 100644
index 0000000..4413f45
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/IssnValidator.php
@@ -0,0 +1,183 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether the value is a valid ISSN.
+ *
+ * @author Antonio J. García Lagar <aj@garcialagar.es>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see https://en.wikipedia.org/wiki/Issn
+ */
+class IssnValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Issn) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Issn');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ $canonical = $value;
+
+ // 1234-567X
+ // ^
+ if (isset($canonical[4]) && '-' === $canonical[4]) {
+ // remove hyphen
+ $canonical = substr($canonical, 0, 4).substr($canonical, 5);
+ } elseif ($constraint->requireHyphen) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::MISSING_HYPHEN_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::MISSING_HYPHEN_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $length = \strlen($canonical);
+
+ if ($length < 8) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::TOO_SHORT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::TOO_SHORT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if ($length > 8) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::TOO_LONG_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::TOO_LONG_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // 1234567X
+ // ^^^^^^^ digits only
+ if (!ctype_digit(substr($canonical, 0, 7))) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // 1234567X
+ // ^ digit, x or X
+ if (!ctype_digit($canonical[7]) && 'x' !== $canonical[7] && 'X' !== $canonical[7]) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // 1234567X
+ // ^ case-sensitive?
+ if ($constraint->caseSensitive && 'x' === $canonical[7]) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::INVALID_CASE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::INVALID_CASE_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // Calculate a checksum. "X" equals 10.
+ $checkSum = 'X' === $canonical[7]
+ || 'x' === $canonical[7]
+ ? 10
+ : $canonical[7];
+
+ for ($i = 0; $i < 7; ++$i) {
+ // Multiply the first digit by 8, the second by 7, etc.
+ $checkSum += (8 - $i) * $canonical[$i];
+ }
+
+ if (0 !== $checkSum % 11) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::CHECKSUM_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Issn::CHECKSUM_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Language.php b/public/system/storage/vendor/symfony/validator/Constraints/Language.php
new file mode 100644
index 0000000..0e676b7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Language.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Language extends Constraint
+{
+ const NO_SUCH_LANGUAGE_ERROR = 'ee65fec4-9a20-4202-9f39-ca558cd7bdf7';
+
+ protected static $errorNames = array(
+ self::NO_SUCH_LANGUAGE_ERROR => 'NO_SUCH_LANGUAGE_ERROR',
+ );
+
+ public $message = 'This value is not a valid language.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LanguageValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/LanguageValidator.php
new file mode 100644
index 0000000..fa06438
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LanguageValidator.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Intl\Intl;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value is a valid language code.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LanguageValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Language) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Language');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ $languages = Intl::getLanguageBundle()->getLanguageNames();
+
+ if (!isset($languages[$value])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Language::NO_SUCH_LANGUAGE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Language::NO_SUCH_LANGUAGE_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Length.php b/public/system/storage/vendor/symfony/validator/Constraints/Length.php
new file mode 100644
index 0000000..20a17fa
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Length.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\MissingOptionsException;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Length extends Constraint
+{
+ const TOO_SHORT_ERROR = '9ff3fdc4-b214-49db-8718-39c315e33d45';
+ const TOO_LONG_ERROR = 'd94b19cc-114f-4f44-9cc4-4138e80a87b9';
+ const INVALID_CHARACTERS_ERROR = '35e6a710-aa2e-4719-b58e-24b35749b767';
+
+ protected static $errorNames = array(
+ self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
+ self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ );
+
+ public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.';
+ public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.';
+ public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.';
+ public $charsetMessage = 'This value does not match the expected {{ charset }} charset.';
+ public $max;
+ public $min;
+ public $charset = 'UTF-8';
+
+ public function __construct($options = null)
+ {
+ if (null !== $options && !\is_array($options)) {
+ $options = array(
+ 'min' => $options,
+ 'max' => $options,
+ );
+ }
+
+ parent::__construct($options);
+
+ if (null === $this->min && null === $this->max) {
+ throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LengthValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/LengthValidator.php
new file mode 100644
index 0000000..68e9428
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LengthValidator.php
@@ -0,0 +1,109 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LengthValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Length) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Length');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $stringValue = (string) $value;
+
+ if (!$invalidCharset = !@mb_check_encoding($stringValue, $constraint->charset)) {
+ $length = mb_strlen($stringValue, $constraint->charset);
+ }
+
+ if ($invalidCharset) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->charsetMessage)
+ ->setParameter('{{ value }}', $this->formatValue($stringValue))
+ ->setParameter('{{ charset }}', $constraint->charset)
+ ->setInvalidValue($value)
+ ->setCode(Length::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->charsetMessage)
+ ->setParameter('{{ value }}', $this->formatValue($stringValue))
+ ->setParameter('{{ charset }}', $constraint->charset)
+ ->setInvalidValue($value)
+ ->setCode(Length::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (null !== $constraint->max && $length > $constraint->max) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
+ ->setParameter('{{ value }}', $this->formatValue($stringValue))
+ ->setParameter('{{ limit }}', $constraint->max)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->max)
+ ->setCode(Length::TOO_LONG_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
+ ->setParameter('{{ value }}', $this->formatValue($stringValue))
+ ->setParameter('{{ limit }}', $constraint->max)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->max)
+ ->setCode(Length::TOO_LONG_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (null !== $constraint->min && $length < $constraint->min) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
+ ->setParameter('{{ value }}', $this->formatValue($stringValue))
+ ->setParameter('{{ limit }}', $constraint->min)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->min)
+ ->setCode(Length::TOO_SHORT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
+ ->setParameter('{{ value }}', $this->formatValue($stringValue))
+ ->setParameter('{{ limit }}', $constraint->min)
+ ->setInvalidValue($value)
+ ->setPlural((int) $constraint->min)
+ ->setCode(Length::TOO_SHORT_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LessThan.php b/public/system/storage/vendor/symfony/validator/Constraints/LessThan.php
new file mode 100644
index 0000000..1bbb508
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LessThan.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LessThan extends AbstractComparison
+{
+ const TOO_HIGH_ERROR = '079d7420-2d13-460c-8756-de810eeb37d2';
+
+ protected static $errorNames = array(
+ self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR',
+ );
+
+ public $message = 'This value should be less than {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqual.php b/public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqual.php
new file mode 100644
index 0000000..d118942
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqual.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LessThanOrEqual extends AbstractComparison
+{
+ const TOO_HIGH_ERROR = '079d7420-2d13-460c-8756-de810eeb37d2';
+
+ protected static $errorNames = array(
+ self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR',
+ );
+
+ public $message = 'This value should be less than or equal to {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqualValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqualValidator.php
new file mode 100644
index 0000000..54281ee
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LessThanOrEqualValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are less than or equal to the previous (<=).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LessThanOrEqualValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 <= $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return LessThanOrEqual::TOO_HIGH_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LessThanValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/LessThanValidator.php
new file mode 100644
index 0000000..ef7535f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LessThanValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are less than the previous (<).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LessThanValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 < $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return LessThan::TOO_HIGH_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Locale.php b/public/system/storage/vendor/symfony/validator/Constraints/Locale.php
new file mode 100644
index 0000000..5aa7070
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Locale.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Locale extends Constraint
+{
+ const NO_SUCH_LOCALE_ERROR = 'a0af4293-1f1a-4a1c-a328-979cba6182a2';
+
+ protected static $errorNames = array(
+ self::NO_SUCH_LOCALE_ERROR => 'NO_SUCH_LOCALE_ERROR',
+ );
+
+ public $message = 'This value is not a valid locale.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LocaleValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/LocaleValidator.php
new file mode 100644
index 0000000..c9763a5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LocaleValidator.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Intl\Intl;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value is a valid locale code.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LocaleValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Locale) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Locale');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ $locales = Intl::getLocaleBundle()->getLocaleNames();
+ $aliases = Intl::getLocaleBundle()->getAliases();
+
+ if (!isset($locales[$value]) && !\in_array($value, $aliases)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Locale::NO_SUCH_LOCALE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Locale::NO_SUCH_LOCALE_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Luhn.php b/public/system/storage/vendor/symfony/validator/Constraints/Luhn.php
new file mode 100644
index 0000000..67f152d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Luhn.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Metadata for the LuhnValidator.
+ *
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Tim Nagel <t.nagel@infinite.net.au>
+ * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Luhn extends Constraint
+{
+ const INVALID_CHARACTERS_ERROR = 'dfad6d23-1b74-4374-929b-5cbb56fc0d9e';
+ const CHECKSUM_FAILED_ERROR = '4d760774-3f50-4cd5-a6d5-b10a3299d8d3';
+
+ protected static $errorNames = array(
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR',
+ );
+
+ public $message = 'Invalid card number.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/LuhnValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/LuhnValidator.php
new file mode 100644
index 0000000..c3fb93d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/LuhnValidator.php
@@ -0,0 +1,111 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates a PAN using the LUHN Algorithm.
+ *
+ * For a list of example card numbers that are used to test this
+ * class, please see the LuhnValidatorTest class.
+ *
+ * @see http://en.wikipedia.org/wiki/Luhn_algorithm
+ *
+ * @author Tim Nagel <t.nagel@infinite.net.au>
+ * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LuhnValidator extends ConstraintValidator
+{
+ /**
+ * Validates a credit card number with the Luhn algorithm.
+ *
+ * @param mixed $value
+ * @param Constraint $constraint
+ *
+ * @throws UnexpectedTypeException when the given credit card number is no string
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Luhn) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Luhn');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ // Work with strings only, because long numbers are represented as floats
+ // internally and don't work with strlen()
+ if (!\is_string($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if (!ctype_digit($value)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Luhn::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Luhn::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $checkSum = 0;
+ $length = \strlen($value);
+
+ // Starting with the last digit and walking left, add every second
+ // digit to the check sum
+ // e.g. 7 9 9 2 7 3 9 8 7 1 3
+ // ^ ^ ^ ^ ^ ^
+ // = 7 + 9 + 7 + 9 + 7 + 3
+ for ($i = $length - 1; $i >= 0; $i -= 2) {
+ $checkSum += $value[$i];
+ }
+
+ // Starting with the second last digit and walking left, double every
+ // second digit and add it to the check sum
+ // For doubles greater than 9, sum the individual digits
+ // e.g. 7 9 9 2 7 3 9 8 7 1 3
+ // ^ ^ ^ ^ ^
+ // = 1+8 + 4 + 6 + 1+6 + 2
+ for ($i = $length - 2; $i >= 0; $i -= 2) {
+ $checkSum += array_sum(str_split($value[$i] * 2));
+ }
+
+ if (0 === $checkSum || 0 !== $checkSum % 10) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Luhn::CHECKSUM_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Luhn::CHECKSUM_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotBlank.php b/public/system/storage/vendor/symfony/validator/Constraints/NotBlank.php
new file mode 100644
index 0000000..e059f10
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotBlank.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotBlank extends Constraint
+{
+ const IS_BLANK_ERROR = 'c1051bb4-d103-4f74-8988-acbcafc7fdc3';
+
+ protected static $errorNames = array(
+ self::IS_BLANK_ERROR => 'IS_BLANK_ERROR',
+ );
+
+ public $message = 'This value should not be blank.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotBlankValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/NotBlankValidator.php
new file mode 100644
index 0000000..6655012
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotBlankValidator.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotBlankValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof NotBlank) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotBlank');
+ }
+
+ if (false === $value || (empty($value) && '0' != $value)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(NotBlank::IS_BLANK_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(NotBlank::IS_BLANK_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotEqualTo.php b/public/system/storage/vendor/symfony/validator/Constraints/NotEqualTo.php
new file mode 100644
index 0000000..8c5abdd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotEqualTo.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotEqualTo extends AbstractComparison
+{
+ const IS_EQUAL_ERROR = 'aa2e33da-25c8-4d76-8c6c-812f02ea89dd';
+
+ protected static $errorNames = array(
+ self::IS_EQUAL_ERROR => 'IS_EQUAL_ERROR',
+ );
+
+ public $message = 'This value should not be equal to {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotEqualToValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/NotEqualToValidator.php
new file mode 100644
index 0000000..b80c5ea
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotEqualToValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values are all unequal (!=).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotEqualToValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 != $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return NotEqualTo::IS_EQUAL_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalTo.php b/public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalTo.php
new file mode 100644
index 0000000..4c9c63e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalTo.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotIdenticalTo extends AbstractComparison
+{
+ const IS_IDENTICAL_ERROR = '4aaac518-0dda-4129-a6d9-e216b9b454a0';
+
+ protected static $errorNames = array(
+ self::IS_IDENTICAL_ERROR => 'IS_IDENTICAL_ERROR',
+ );
+
+ public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalToValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalToValidator.php
new file mode 100644
index 0000000..3ea8b5a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotIdenticalToValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * Validates values aren't identical (!==).
+ *
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotIdenticalToValidator extends AbstractComparisonValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function compareValues($value1, $value2)
+ {
+ return $value1 !== $value2;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getErrorCode()
+ {
+ return NotIdenticalTo::IS_IDENTICAL_ERROR;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotNull.php b/public/system/storage/vendor/symfony/validator/Constraints/NotNull.php
new file mode 100644
index 0000000..1cfc1c8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotNull.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotNull extends Constraint
+{
+ const IS_NULL_ERROR = 'ad32d13f-c3d4-423b-909a-857b961eb720';
+
+ protected static $errorNames = array(
+ self::IS_NULL_ERROR => 'IS_NULL_ERROR',
+ );
+
+ public $message = 'This value should not be null.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NotNullValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/NotNullValidator.php
new file mode 100644
index 0000000..0402b3d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NotNullValidator.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NotNullValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof NotNull) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotNull');
+ }
+
+ if (null === $value) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(NotNull::IS_NULL_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(NotNull::IS_NULL_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Null.php b/public/system/storage/vendor/symfony/validator/Constraints/Null.php
new file mode 100644
index 0000000..eef0826
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Null.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+@trigger_error('The '.__NAMESPACE__.'\Null class is deprecated since Symfony 2.7 and will be removed in 3.0. Use the IsNull class in the same namespace instead.', E_USER_DEPRECATED);
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use IsNull instead.
+ */
+class Null extends IsNull
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/NullValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/NullValidator.php
new file mode 100644
index 0000000..61b6521
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/NullValidator.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+@trigger_error('The '.__NAMESPACE__.'\NullValidator class is deprecated since Symfony 2.7 and will be removed in 3.0. Use the IsNullValidator class in the same namespace instead.', E_USER_DEPRECATED);
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use IsNullValidator instead.
+ */
+class NullValidator extends IsNullValidator
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Optional.php b/public/system/storage/vendor/symfony/validator/Constraints/Optional.php
new file mode 100644
index 0000000..dab8b43
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Optional.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Optional extends Existence
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Range.php b/public/system/storage/vendor/symfony/validator/Constraints/Range.php
new file mode 100644
index 0000000..bf050ac
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Range.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\MissingOptionsException;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Range extends Constraint
+{
+ const INVALID_CHARACTERS_ERROR = 'ad9a9798-7a99-4df7-8ce9-46e416a1e60b';
+ const TOO_HIGH_ERROR = '2d28afcb-e32e-45fb-a815-01c431a86a69';
+ const TOO_LOW_ERROR = '76454e69-502c-46c5-9643-f447d837c4d5';
+
+ /**
+ * @deprecated Deprecated since version 2.8, to be removed in 3.0. Use
+ * {@link INVALID_CHARACTERS_ERROR} instead.
+ */
+ const INVALID_VALUE_ERROR = self::INVALID_CHARACTERS_ERROR;
+
+ /**
+ * @deprecated Deprecated since version 2.8, to be removed in 3.0. Use
+ * {@link TOO_HIGH_ERROR} instead.
+ */
+ const BEYOND_RANGE_ERROR = self::TOO_HIGH_ERROR;
+
+ /**
+ * @deprecated Deprecated since version 2.8, to be removed in 3.0. Use
+ * {@link TOO_LOW_ERROR} instead.
+ */
+ const BELOW_RANGE_ERROR = self::TOO_LOW_ERROR;
+
+ protected static $errorNames = array(
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR',
+ self::TOO_LOW_ERROR => 'TOO_LOW_ERROR',
+ );
+
+ public $minMessage = 'This value should be {{ limit }} or more.';
+ public $maxMessage = 'This value should be {{ limit }} or less.';
+ public $invalidMessage = 'This value should be a valid number.';
+ public $min;
+ public $max;
+
+ public function __construct($options = null)
+ {
+ parent::__construct($options);
+
+ if (null === $this->min && null === $this->max) {
+ throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/RangeValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/RangeValidator.php
new file mode 100644
index 0000000..924550a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/RangeValidator.php
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class RangeValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Range) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Range');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ if (!is_numeric($value) && !$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->invalidMessage)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
+ ->setCode(Range::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->invalidMessage)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
+ ->setCode(Range::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $min = $constraint->min;
+ $max = $constraint->max;
+
+ // Convert strings to DateTimes if comparing another DateTime
+ // This allows to compare with any date/time value supported by
+ // the DateTime constructor:
+ // http://php.net/manual/en/datetime.formats.php
+ if ($value instanceof \DateTime || $value instanceof \DateTimeInterface) {
+ if (\is_string($min)) {
+ $min = new \DateTime($min);
+ }
+
+ if (\is_string($max)) {
+ $max = new \DateTime($max);
+ }
+ }
+
+ if (null !== $constraint->max && $value > $max) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->maxMessage)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
+ ->setParameter('{{ limit }}', $this->formatValue($max, self::PRETTY_DATE))
+ ->setCode(Range::TOO_HIGH_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->maxMessage)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
+ ->setParameter('{{ limit }}', $this->formatValue($max, self::PRETTY_DATE))
+ ->setCode(Range::TOO_HIGH_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (null !== $constraint->min && $value < $min) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->minMessage)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
+ ->setParameter('{{ limit }}', $this->formatValue($min, self::PRETTY_DATE))
+ ->setCode(Range::TOO_LOW_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->minMessage)
+ ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
+ ->setParameter('{{ limit }}', $this->formatValue($min, self::PRETTY_DATE))
+ ->setCode(Range::TOO_LOW_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Regex.php b/public/system/storage/vendor/symfony/validator/Constraints/Regex.php
new file mode 100644
index 0000000..cb12210
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Regex.php
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Regex extends Constraint
+{
+ const REGEX_FAILED_ERROR = 'de1e3db3-5ed4-4941-aae4-59f3667cc3a3';
+
+ protected static $errorNames = array(
+ self::REGEX_FAILED_ERROR => 'REGEX_FAILED_ERROR',
+ );
+
+ public $message = 'This value is not valid.';
+ public $pattern;
+ public $htmlPattern;
+ public $match = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'pattern';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRequiredOptions()
+ {
+ return array('pattern');
+ }
+
+ /**
+ * Converts the htmlPattern to a suitable format for HTML5 pattern.
+ * Example: /^[a-z]+$/ would be converted to [a-z]+
+ * However, if options are specified, it cannot be converted.
+ *
+ * Pattern is also ignored if match=false since the pattern should
+ * then be reversed before application.
+ *
+ * @see http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute
+ *
+ * @return string|null
+ */
+ public function getHtmlPattern()
+ {
+ // If htmlPattern is specified, use it
+ if (null !== $this->htmlPattern) {
+ return empty($this->htmlPattern)
+ ? null
+ : $this->htmlPattern;
+ }
+
+ // Quit if delimiters not at very beginning/end (e.g. when options are passed)
+ if ($this->pattern[0] !== $this->pattern[\strlen($this->pattern) - 1]) {
+ return;
+ }
+
+ $delimiter = $this->pattern[0];
+
+ // Unescape the delimiter
+ $pattern = str_replace('\\'.$delimiter, $delimiter, substr($this->pattern, 1, -1));
+
+ // If the pattern is inverted, we can simply wrap it in
+ // ((?!pattern).)*
+ if (!$this->match) {
+ return '((?!'.$pattern.').)*';
+ }
+
+ // If the pattern contains an or statement, wrap the pattern in
+ // .*(pattern).* and quit. Otherwise we'd need to parse the pattern
+ if (false !== strpos($pattern, '|')) {
+ return '.*('.$pattern.').*';
+ }
+
+ // Trim leading ^, otherwise prepend .*
+ $pattern = '^' === $pattern[0] ? substr($pattern, 1) : '.*'.$pattern;
+
+ // Trim trailing $, otherwise append .*
+ $pattern = '$' === $pattern[\strlen($pattern) - 1] ? substr($pattern, 0, -1) : $pattern.'.*';
+
+ return $pattern;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/RegexValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/RegexValidator.php
new file mode 100644
index 0000000..07f1c5a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/RegexValidator.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether a value match or not given regexp pattern.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ * @author Joseph Bielawski <stloyd@gmail.com>
+ */
+class RegexValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Regex) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Regex');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if ($constraint->match xor preg_match($constraint->pattern, $value)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Regex::REGEX_FAILED_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Regex::REGEX_FAILED_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Required.php b/public/system/storage/vendor/symfony/validator/Constraints/Required.php
new file mode 100644
index 0000000..bd77a90
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Required.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+/**
+ * @Annotation
+ * @Target({"ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Required extends Existence
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Time.php b/public/system/storage/vendor/symfony/validator/Constraints/Time.php
new file mode 100644
index 0000000..6bd8dbd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Time.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Time extends Constraint
+{
+ const INVALID_FORMAT_ERROR = '9d27b2bb-f755-4fbf-b725-39b1edbdebdf';
+ const INVALID_TIME_ERROR = '8532f9e1-84b2-4d67-8989-0818bc38533b';
+
+ protected static $errorNames = array(
+ self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
+ self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR',
+ );
+
+ public $message = 'This value is not a valid time.';
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/TimeValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/TimeValidator.php
new file mode 100644
index 0000000..97f188d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/TimeValidator.php
@@ -0,0 +1,91 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class TimeValidator extends ConstraintValidator
+{
+ const PATTERN = '/^(\d{2}):(\d{2}):(\d{2})$/';
+
+ /**
+ * Checks whether a time is valid.
+ *
+ * @param int $hour The hour
+ * @param int $minute The minute
+ * @param int $second The second
+ *
+ * @return bool Whether the time is valid
+ *
+ * @internal
+ */
+ public static function checkTime($hour, $minute, $second)
+ {
+ return $hour >= 0 && $hour < 24 && $minute >= 0 && $minute < 60 && $second >= 0 && $second < 60;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Time) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Time');
+ }
+
+ if (null === $value || '' === $value || $value instanceof \DateTime) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if (!preg_match(static::PATTERN, $value, $matches)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Time::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Time::INVALID_FORMAT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if (!self::checkTime($matches[1], $matches[2], $matches[3])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Time::INVALID_TIME_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Time::INVALID_TIME_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Traverse.php b/public/system/storage/vendor/symfony/validator/Constraints/Traverse.php
new file mode 100644
index 0000000..4572c9b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Traverse.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * @Annotation
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Traverse extends Constraint
+{
+ public $traverse = true;
+
+ public function __construct($options = null)
+ {
+ if (\is_array($options) && array_key_exists('groups', $options)) {
+ throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__));
+ }
+
+ parent::__construct($options);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'traverse';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTargets()
+ {
+ return self::CLASS_CONSTRAINT;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/True.php b/public/system/storage/vendor/symfony/validator/Constraints/True.php
new file mode 100644
index 0000000..9dbf403
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/True.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+@trigger_error('The '.__NAMESPACE__.'\True class is deprecated since Symfony 2.7 and will be removed in 3.0. Use the IsTrue class in the same namespace instead.', E_USER_DEPRECATED);
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use IsTrue instead.
+ */
+class True extends IsTrue
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/TrueValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/TrueValidator.php
new file mode 100644
index 0000000..c4a886b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/TrueValidator.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+@trigger_error('The '.__NAMESPACE__.'\TrueValidator class is deprecated since Symfony 2.7 and will be removed in 3.0. Use the IsTrueValidator class in the same namespace instead.', E_USER_DEPRECATED);
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use IsTrueValidator instead.
+ */
+class TrueValidator extends IsTrueValidator
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Type.php b/public/system/storage/vendor/symfony/validator/Constraints/Type.php
new file mode 100644
index 0000000..e40b478
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Type.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Type extends Constraint
+{
+ const INVALID_TYPE_ERROR = 'ba785a8c-82cb-4283-967c-3cf342181b40';
+
+ protected static $errorNames = array(
+ self::INVALID_TYPE_ERROR => 'INVALID_TYPE_ERROR',
+ );
+
+ public $message = 'This value should be of type {{ type }}.';
+ public $type;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultOption()
+ {
+ return 'type';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRequiredOptions()
+ {
+ return array('type');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/TypeValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/TypeValidator.php
new file mode 100644
index 0000000..d69c5d3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/TypeValidator.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class TypeValidator extends ConstraintValidator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Type) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Type');
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ $type = strtolower($constraint->type);
+ $type = 'boolean' == $type ? 'bool' : $constraint->type;
+ $isFunction = 'is_'.$type;
+ $ctypeFunction = 'ctype_'.$type;
+
+ if (\function_exists($isFunction) && $isFunction($value)) {
+ return;
+ } elseif (\function_exists($ctypeFunction) && $ctypeFunction($value)) {
+ return;
+ } elseif ($value instanceof $constraint->type) {
+ return;
+ }
+
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setParameter('{{ type }}', $constraint->type)
+ ->setCode(Type::INVALID_TYPE_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setParameter('{{ type }}', $constraint->type)
+ ->setCode(Type::INVALID_TYPE_ERROR)
+ ->addViolation();
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Url.php b/public/system/storage/vendor/symfony/validator/Constraints/Url.php
new file mode 100644
index 0000000..8453a90
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Url.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Url extends Constraint
+{
+ const INVALID_URL_ERROR = '57c2f299-1154-4870-89bb-ef3b1f5ad229';
+
+ protected static $errorNames = array(
+ self::INVALID_URL_ERROR => 'INVALID_URL_ERROR',
+ );
+
+ public $message = 'This value is not a valid URL.';
+ public $dnsMessage = 'The host could not be resolved.';
+ public $protocols = array('http', 'https');
+ public $checkDNS = false;
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/UrlValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/UrlValidator.php
new file mode 100644
index 0000000..4527ab2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/UrlValidator.php
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class UrlValidator extends ConstraintValidator
+{
+ const PATTERN = '~^
+ (%s):// # protocol
+ (([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth
+ (
+ ([\pL\pN\pS\-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
+ | # or
+ \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address
+ | # or
+ \[
+ (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
+ \] # an IPv6 address
+ )
+ (:[0-9]+)? # a port (optional)
+ (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path
+ (?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional)
+ (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
+ $~ixu';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Url) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+ if ('' === $value) {
+ return;
+ }
+
+ $pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols));
+
+ if (!preg_match($pattern, $value)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Url::INVALID_URL_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Url::INVALID_URL_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ if ($constraint->checkDNS) {
+ $host = parse_url($value, PHP_URL_HOST);
+
+ if (!\is_string($host) || !checkdnsrr($host, 'ANY')) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->dnsMessage)
+ ->setParameter('{{ value }}', $this->formatValue($host))
+ ->setCode(Url::INVALID_URL_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->dnsMessage)
+ ->setParameter('{{ value }}', $this->formatValue($host))
+ ->setCode(Url::INVALID_URL_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Uuid.php b/public/system/storage/vendor/symfony/validator/Constraints/Uuid.php
new file mode 100644
index 0000000..2deecba
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Uuid.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * @Annotation
+ *
+ * @author Colin O'Dell <colinodell@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Uuid extends Constraint
+{
+ const TOO_SHORT_ERROR = 'aa314679-dac9-4f54-bf97-b2049df8f2a3';
+ const TOO_LONG_ERROR = '494897dd-36f8-4d31-8923-71a8d5f3000d';
+ const INVALID_CHARACTERS_ERROR = '51120b12-a2bc-41bf-aa53-cd73daf330d0';
+ const INVALID_HYPHEN_PLACEMENT_ERROR = '98469c83-0309-4f5d-bf95-a496dcaa869c';
+ const INVALID_VERSION_ERROR = '21ba13b4-b185-4882-ac6f-d147355987eb';
+ const INVALID_VARIANT_ERROR = '164ef693-2b9d-46de-ad7f-836201f0c2db';
+
+ protected static $errorNames = array(
+ self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR',
+ self::TOO_LONG_ERROR => 'TOO_LONG_ERROR',
+ self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR',
+ self::INVALID_HYPHEN_PLACEMENT_ERROR => 'INVALID_HYPHEN_PLACEMENT_ERROR',
+ self::INVALID_VERSION_ERROR => 'INVALID_VERSION_ERROR',
+ self::INVALID_VARIANT_ERROR => 'INVALID_VARIANT_ERROR',
+ );
+
+ // Possible versions defined by RFC 4122
+ const V1_MAC = 1;
+ const V2_DCE = 2;
+ const V3_MD5 = 3;
+ const V4_RANDOM = 4;
+ const V5_SHA1 = 5;
+
+ /**
+ * Message to display when validation fails.
+ *
+ * @var string
+ */
+ public $message = 'This is not a valid UUID.';
+
+ /**
+ * Strict mode only allows UUIDs that meet the formal definition and formatting per RFC 4122.
+ *
+ * Set this to `false` to allow legacy formats with different dash positioning or wrapping characters
+ *
+ * @var bool
+ */
+ public $strict = true;
+
+ /**
+ * Array of allowed versions (see version constants above).
+ *
+ * All UUID versions are allowed by default
+ *
+ * @var int[]
+ */
+ public $versions = array(
+ self::V1_MAC,
+ self::V2_DCE,
+ self::V3_MD5,
+ self::V4_RANDOM,
+ self::V5_SHA1,
+ );
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/UuidValidator.php b/public/system/storage/vendor/symfony/validator/Constraints/UuidValidator.php
new file mode 100644
index 0000000..8e2e5da
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/UuidValidator.php
@@ -0,0 +1,350 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\Deprecated\UuidValidator as Deprecated;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates whether the value is a valid UUID (also known as GUID).
+ *
+ * Strict validation will allow a UUID as specified per RFC 4122.
+ * Loose validation will allow any type of UUID.
+ *
+ * For better compatibility, both loose and strict, you should consider using a specialized UUID library like "ramsey/uuid" instead.
+ *
+ * @author Colin O'Dell <colinodell@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see http://tools.ietf.org/html/rfc4122
+ * @see https://en.wikipedia.org/wiki/Universally_unique_identifier
+ * @see https://github.com/ramsey/uuid
+ */
+class UuidValidator extends ConstraintValidator
+{
+ // The strict pattern matches UUIDs like this:
+ // xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
+
+ // Roughly speaking:
+ // x = any hexadecimal character
+ // M = any allowed version {1..5}
+ // N = any allowed variant {8, 9, a, b}
+
+ const STRICT_LENGTH = 36;
+ const STRICT_FIRST_HYPHEN_POSITION = 8;
+ const STRICT_LAST_HYPHEN_POSITION = 23;
+ const STRICT_VERSION_POSITION = 14;
+ const STRICT_VARIANT_POSITION = 19;
+
+ // The loose pattern validates similar yet non-compliant UUIDs.
+ // Hyphens are completely optional. If present, they should only appear
+ // between every fourth character:
+ // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
+ // xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx
+ // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+ // The value can also be wrapped with characters like []{}:
+ // {xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx}
+
+ // Neither the version nor the variant is validated by this pattern.
+
+ const LOOSE_MAX_LENGTH = 39;
+ const LOOSE_FIRST_HYPHEN_POSITION = 4;
+
+ /**
+ * @deprecated since version 2.6, to be removed in 3.0
+ */
+ const STRICT_PATTERN = '/^[a-f0-9]{8}-[a-f0-9]{4}-[%s][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i';
+
+ /**
+ * @deprecated since version 2.6, to be removed in 3.0
+ */
+ const LOOSE_PATTERN = '/^[a-f0-9]{4}(?:-?[a-f0-9]{4}){7}$/i';
+
+ /**
+ * @deprecated since version 2.6, to be removed in 3.0
+ */
+ const STRICT_UUID_LENGTH = 36;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, Constraint $constraint)
+ {
+ if (!$constraint instanceof Uuid) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Uuid');
+ }
+
+ if (null === $value || '' === $value) {
+ return;
+ }
+
+ if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ throw new UnexpectedTypeException($value, 'string');
+ }
+
+ $value = (string) $value;
+
+ if ($constraint->strict) {
+ $this->validateStrict($value, $constraint);
+
+ return;
+ }
+
+ $this->validateLoose($value, $constraint);
+ }
+
+ private function validateLoose($value, Uuid $constraint)
+ {
+ // Error priority:
+ // 1. ERROR_INVALID_CHARACTERS
+ // 2. ERROR_INVALID_HYPHEN_PLACEMENT
+ // 3. ERROR_TOO_SHORT/ERROR_TOO_LONG
+
+ // Trim any wrapping characters like [] or {} used by some legacy systems
+ $trimmed = trim($value, '[]{}');
+
+ // Position of the next expected hyphen
+ $h = self::LOOSE_FIRST_HYPHEN_POSITION;
+
+ // Expected length
+ $l = self::LOOSE_MAX_LENGTH;
+
+ for ($i = 0; $i < $l; ++$i) {
+ // Check length
+ if (!isset($trimmed[$i])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_SHORT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_SHORT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // Hyphens must occur every fifth position
+ // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
+ // ^ ^ ^ ^ ^ ^ ^
+ if ('-' === $trimmed[$i]) {
+ if ($i !== $h) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ $h += 5;
+
+ continue;
+ }
+
+ // Missing hyphens are ignored
+ if ($i === $h) {
+ $h += 4;
+ --$l;
+ }
+
+ // Check characters
+ if (!ctype_xdigit($trimmed[$i])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ // Check length again
+ if (isset($trimmed[$i])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_LONG_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_LONG_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+
+ private function validateStrict($value, Uuid $constraint)
+ {
+ // Error priority:
+ // 1. ERROR_INVALID_CHARACTERS
+ // 2. ERROR_INVALID_HYPHEN_PLACEMENT
+ // 3. ERROR_TOO_SHORT/ERROR_TOO_LONG
+ // 4. ERROR_INVALID_VERSION
+ // 5. ERROR_INVALID_VARIANT
+
+ // Position of the next expected hyphen
+ $h = self::STRICT_FIRST_HYPHEN_POSITION;
+
+ for ($i = 0; $i < self::STRICT_LENGTH; ++$i) {
+ // Check length
+ if (!isset($value[$i])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_SHORT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_SHORT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // Check hyphen placement
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ // ^ ^ ^ ^
+ if ('-' === $value[$i]) {
+ if ($i !== $h) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ // ^
+ if ($h < self::STRICT_LAST_HYPHEN_POSITION) {
+ $h += 5;
+ }
+
+ continue;
+ }
+
+ // Check characters
+ if (!ctype_xdigit($value[$i])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_CHARACTERS_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+
+ // Missing hyphen
+ if ($i === $h) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
+ ->addViolation();
+ }
+
+ return;
+ }
+ }
+
+ // Check length again
+ if (isset($value[$i])) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_LONG_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::TOO_LONG_ERROR)
+ ->addViolation();
+ }
+ }
+
+ // Check version
+ if (!\in_array($value[self::STRICT_VERSION_POSITION], $constraint->versions)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_VERSION_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_VERSION_ERROR)
+ ->addViolation();
+ }
+ }
+
+ // Check variant - first two bits must equal "10"
+ // 0b10xx
+ // & 0b1100 (12)
+ // = 0b1000 (8)
+ if (8 !== (hexdec($value[self::STRICT_VARIANT_POSITION]) & 12)) {
+ if ($this->context instanceof ExecutionContextInterface) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_VARIANT_ERROR)
+ ->addViolation();
+ } else {
+ $this->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $this->formatValue($value))
+ ->setCode(Uuid::INVALID_VARIANT_ERROR)
+ ->addViolation();
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Constraints/Valid.php b/public/system/storage/vendor/symfony/validator/Constraints/Valid.php
new file mode 100644
index 0000000..35a8edc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Constraints/Valid.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+/**
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Valid extends Constraint
+{
+ public $traverse = true;
+
+ /**
+ * @deprecated since version 2.5, to be removed in Symfony 3.0.
+ */
+ public $deep = true;
+
+ public function __construct($options = null)
+ {
+ if (\is_array($options) && array_key_exists('groups', $options)) {
+ throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__));
+ }
+
+ if (\is_array($options) && array_key_exists('deep', $options)) {
+ @trigger_error('The "deep" option for the Valid constraint is deprecated since Symfony 2.5 and will be removed in 3.0. When traversing arrays, nested arrays are always traversed. When traversing nested objects, their traversal strategy is used.', E_USER_DEPRECATED);
+ }
+
+ parent::__construct($options);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Context/ExecutionContext.php b/public/system/storage/vendor/symfony/validator/Context/ExecutionContext.php
new file mode 100644
index 0000000..165c572
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Context/ExecutionContext.php
@@ -0,0 +1,467 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Context;
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\ClassBasedInterface;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\ConstraintViolation;
+use Symfony\Component\Validator\ConstraintViolationList;
+use Symfony\Component\Validator\Mapping\MetadataInterface;
+use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
+use Symfony\Component\Validator\Util\PropertyPath;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface;
+use Symfony\Component\Validator\Violation\ConstraintViolationBuilder;
+
+/**
+ * The context used and created by {@link ExecutionContextFactory}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see ExecutionContextInterface
+ *
+ * @internal You should not instantiate or use this class. Code against
+ * {@link ExecutionContextInterface} instead.
+ */
+class ExecutionContext implements ExecutionContextInterface
+{
+ /**
+ * @var ValidatorInterface
+ */
+ private $validator;
+
+ /**
+ * The root value of the validated object graph.
+ *
+ * @var mixed
+ */
+ private $root;
+
+ /**
+ * @var TranslatorInterface
+ */
+ private $translator;
+
+ /**
+ * @var string
+ */
+ private $translationDomain;
+
+ /**
+ * The violations generated in the current context.
+ *
+ * @var ConstraintViolationList
+ */
+ private $violations;
+
+ /**
+ * The currently validated value.
+ *
+ * @var mixed
+ */
+ private $value;
+
+ /**
+ * The currently validated object.
+ *
+ * @var object|null
+ */
+ private $object;
+
+ /**
+ * The property path leading to the current value.
+ *
+ * @var string
+ */
+ private $propertyPath = '';
+
+ /**
+ * The current validation metadata.
+ *
+ * @var MetadataInterface|null
+ */
+ private $metadata;
+
+ /**
+ * The currently validated group.
+ *
+ * @var string|null
+ */
+ private $group;
+
+ /**
+ * The currently validated constraint.
+ *
+ * @var Constraint|null
+ */
+ private $constraint;
+
+ /**
+ * Stores which objects have been validated in which group.
+ *
+ * @var array
+ */
+ private $validatedObjects = array();
+
+ /**
+ * Stores which class constraint has been validated for which object.
+ *
+ * @var array
+ */
+ private $validatedConstraints = array();
+
+ /**
+ * Stores which objects have been initialized.
+ *
+ * @var array
+ */
+ private $initializedObjects;
+
+ /**
+ * Creates a new execution context.
+ *
+ * @param ValidatorInterface $validator The validator
+ * @param mixed $root The root value of the
+ * validated object graph
+ * @param TranslatorInterface $translator The translator
+ * @param string|null $translationDomain The translation domain to
+ * use for translating
+ * violation messages
+ *
+ * @internal Called by {@link ExecutionContextFactory}. Should not be used
+ * in user code.
+ */
+ public function __construct(ValidatorInterface $validator, $root, TranslatorInterface $translator, $translationDomain = null)
+ {
+ $this->validator = $validator;
+ $this->root = $root;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ $this->violations = new ConstraintViolationList();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setNode($value, $object, MetadataInterface $metadata = null, $propertyPath)
+ {
+ $this->value = $value;
+ $this->object = $object;
+ $this->metadata = $metadata;
+ $this->propertyPath = (string) $propertyPath;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setGroup($group)
+ {
+ $this->group = $group;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConstraint(Constraint $constraint)
+ {
+ $this->constraint = $constraint;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addViolation($message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null)
+ {
+ // The parameters $invalidValue and following are ignored by the new
+ // API, as they are not present in the new interface anymore.
+ // You should use buildViolation() instead.
+ if (\func_num_args() > 2) {
+ @trigger_error('The parameters $invalidValue, $plural and $code in method '.__METHOD__.' are deprecated since Symfony 2.5 and will be removed in 3.0. Use the '.__CLASS__.'::buildViolation method instead.', E_USER_DEPRECATED);
+
+ $this
+ ->buildViolation($message, $parameters)
+ ->setInvalidValue($invalidValue)
+ ->setPlural($plural)
+ ->setCode($code)
+ ->addViolation()
+ ;
+
+ return;
+ }
+
+ $this->violations->add(new ConstraintViolation(
+ $this->translator->trans($message, $parameters, $this->translationDomain),
+ $message,
+ $parameters,
+ $this->root,
+ $this->propertyPath,
+ $this->value,
+ null,
+ null,
+ $this->constraint
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildViolation($message, array $parameters = array())
+ {
+ return new ConstraintViolationBuilder(
+ $this->violations,
+ $this->constraint,
+ $message,
+ $parameters,
+ $this->root,
+ $this->propertyPath,
+ $this->value,
+ $this->translator,
+ $this->translationDomain
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getViolations()
+ {
+ return $this->violations;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValidator()
+ {
+ return $this->validator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getObject()
+ {
+ return $this->object;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata()
+ {
+ return $this->metadata;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroup()
+ {
+ return $this->group;
+ }
+
+ public function getConstraint()
+ {
+ return $this->constraint;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getClassName()
+ {
+ return $this->metadata instanceof ClassBasedInterface ? $this->metadata->getClassName() : null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyName()
+ {
+ return $this->metadata instanceof PropertyMetadataInterface ? $this->metadata->getPropertyName() : null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyPath($subPath = '')
+ {
+ return PropertyPath::append($this->propertyPath, $subPath);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the '.__CLASS__.'::buildViolation method instead.', E_USER_DEPRECATED);
+
+ if (\func_num_args() > 2) {
+ $this
+ ->buildViolation($message, $parameters)
+ ->atPath($subPath)
+ ->setInvalidValue($invalidValue)
+ ->setPlural($plural)
+ ->setCode($code)
+ ->addViolation()
+ ;
+
+ return;
+ }
+
+ $this
+ ->buildViolation($message, $parameters)
+ ->atPath($subPath)
+ ->addViolation()
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the '.__CLASS__.'::getValidator() method instead.', E_USER_DEPRECATED);
+
+ if (\is_array($value)) {
+ // The $traverse flag is ignored for arrays
+ $constraint = new Valid(array('traverse' => true, 'deep' => $deep));
+
+ return $this
+ ->getValidator()
+ ->inContext($this)
+ ->atPath($subPath)
+ ->validate($value, $constraint, $groups)
+ ;
+ }
+
+ if ($traverse && $value instanceof \Traversable) {
+ $constraint = new Valid(array('traverse' => true, 'deep' => $deep));
+
+ return $this
+ ->getValidator()
+ ->inContext($this)
+ ->atPath($subPath)
+ ->validate($value, $constraint, $groups)
+ ;
+ }
+
+ return $this
+ ->getValidator()
+ ->inContext($this)
+ ->atPath($subPath)
+ ->validate($value, null, $groups)
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateValue($value, $constraints, $subPath = '', $groups = null)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the '.__CLASS__.'::getValidator() method instead.', E_USER_DEPRECATED);
+
+ return $this
+ ->getValidator()
+ ->inContext($this)
+ ->atPath($subPath)
+ ->validate($value, $constraints, $groups)
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFactory()
+ {
+ @trigger_error('The '.__METHOD__.' is deprecated since Symfony 2.5 and will be removed in 3.0. Use the new Symfony\Component\Validator\Context\ExecutionContext::getValidator method in combination with Symfony\Component\Validator\Validator\ValidatorInterface::getMetadataFor or Symfony\Component\Validator\Validator\ValidatorInterface::hasMetadataFor method instead.', E_USER_DEPRECATED);
+
+ $validator = $this->getValidator();
+
+ if ($validator instanceof LegacyValidatorInterface) {
+ return $validator->getMetadataFactory();
+ }
+
+ // The ValidatorInterface extends from the deprecated MetadataFactoryInterface, so return it when we don't have the factory instance itself
+ return $validator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function markGroupAsValidated($cacheKey, $groupHash)
+ {
+ if (!isset($this->validatedObjects[$cacheKey])) {
+ $this->validatedObjects[$cacheKey] = array();
+ }
+
+ $this->validatedObjects[$cacheKey][$groupHash] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isGroupValidated($cacheKey, $groupHash)
+ {
+ return isset($this->validatedObjects[$cacheKey][$groupHash]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function markConstraintAsValidated($cacheKey, $constraintHash)
+ {
+ $this->validatedConstraints[$cacheKey.':'.$constraintHash] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isConstraintValidated($cacheKey, $constraintHash)
+ {
+ return isset($this->validatedConstraints[$cacheKey.':'.$constraintHash]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function markObjectAsInitialized($cacheKey)
+ {
+ $this->initializedObjects[$cacheKey] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isObjectInitialized($cacheKey)
+ {
+ return isset($this->initializedObjects[$cacheKey]);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactory.php b/public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactory.php
new file mode 100644
index 0000000..cbd9935
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactory.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Context;
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * Creates new {@link ExecutionContext} instances.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @internal You should not instantiate or use this class. Code against
+ * {@link ExecutionContextFactoryInterface} instead.
+ */
+class ExecutionContextFactory implements ExecutionContextFactoryInterface
+{
+ private $translator;
+ private $translationDomain;
+
+ /**
+ * Creates a new context factory.
+ *
+ * @param TranslatorInterface $translator The translator
+ * @param string|null $translationDomain The translation domain to
+ * use for translating
+ * violation messages
+ */
+ public function __construct(TranslatorInterface $translator, $translationDomain = null)
+ {
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createContext(ValidatorInterface $validator, $root)
+ {
+ return new ExecutionContext(
+ $validator,
+ $root,
+ $this->translator,
+ $this->translationDomain
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactoryInterface.php b/public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactoryInterface.php
new file mode 100644
index 0000000..f3ab3dd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Context/ExecutionContextFactoryInterface.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Context;
+
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * Creates instances of {@link ExecutionContextInterface}.
+ *
+ * You can use a custom factory if you want to customize the execution context
+ * that is passed through the validation run.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ExecutionContextFactoryInterface
+{
+ /**
+ * Creates a new execution context.
+ *
+ * @param ValidatorInterface $validator The validator
+ * @param mixed $root The root value of the validated
+ * object graph
+ *
+ * @return ExecutionContextInterface The new execution context
+ */
+ public function createContext(ValidatorInterface $validator, $root);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Context/ExecutionContextInterface.php b/public/system/storage/vendor/symfony/validator/Context/ExecutionContextInterface.php
new file mode 100644
index 0000000..548a4db
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Context/ExecutionContextInterface.php
@@ -0,0 +1,225 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Context;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;
+use Symfony\Component\Validator\Mapping\MetadataInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
+
+/**
+ * The context of a validation run.
+ *
+ * The context collects all violations generated during the validation. By
+ * default, validators execute all validations in a new context:
+ *
+ * $violations = $validator->validate($object);
+ *
+ * When you make another call to the validator, while the validation is in
+ * progress, the violations will be isolated from each other:
+ *
+ * public function validate($value, Constraint $constraint)
+ * {
+ * $validator = $this->context->getValidator();
+ *
+ * // The violations are not added to $this->context
+ * $violations = $validator->validate($value);
+ * }
+ *
+ * However, if you want to add the violations to the current context, use the
+ * {@link ValidatorInterface::inContext()} method:
+ *
+ * public function validate($value, Constraint $constraint)
+ * {
+ * $validator = $this->context->getValidator();
+ *
+ * // The violations are added to $this->context
+ * $validator
+ * ->inContext($this->context)
+ * ->validate($value)
+ * ;
+ * }
+ *
+ * Additionally, the context provides information about the current state of
+ * the validator, such as the currently validated class, the name of the
+ * currently validated property and more. These values change over time, so you
+ * cannot store a context and expect that the methods still return the same
+ * results later on.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ExecutionContextInterface extends LegacyExecutionContextInterface
+{
+ /**
+ * Returns a builder for adding a violation with extended information.
+ *
+ * Call {@link ConstraintViolationBuilderInterface::addViolation()} to
+ * add the violation when you're done with the configuration:
+ *
+ * $context->buildViolation('Please enter a number between %min% and %max%.')
+ * ->setParameter('%min%', 3)
+ * ->setParameter('%max%', 10)
+ * ->setTranslationDomain('number_validation')
+ * ->addViolation();
+ *
+ * @param string $message The error message
+ * @param array $parameters The parameters substituted in the error message
+ *
+ * @return ConstraintViolationBuilderInterface The violation builder
+ */
+ public function buildViolation($message, array $parameters = array());
+
+ /**
+ * Returns the validator.
+ *
+ * Useful if you want to validate additional constraints:
+ *
+ * public function validate($value, Constraint $constraint)
+ * {
+ * $validator = $this->context->getValidator();
+ *
+ * $violations = $validator->validate($value, new Length(array('min' => 3)));
+ *
+ * if (count($violations) > 0) {
+ * // ...
+ * }
+ * }
+ *
+ * @return ValidatorInterface
+ */
+ public function getValidator();
+
+ /**
+ * Returns the currently validated object.
+ *
+ * If the validator is currently validating a class constraint, the
+ * object of that class is returned. If it is a validating a property or
+ * getter constraint, the object that the property/getter belongs to is
+ * returned.
+ *
+ * In other cases, null is returned.
+ *
+ * @return object|null The currently validated object or null
+ */
+ public function getObject();
+
+ /**
+ * Sets the currently validated value.
+ *
+ * @param mixed $value The validated value
+ * @param object|null $object The currently validated object
+ * @param MetadataInterface|null $metadata The validation metadata
+ * @param string $propertyPath The property path to the current value
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function setNode($value, $object, MetadataInterface $metadata = null, $propertyPath);
+
+ /**
+ * Sets the currently validated group.
+ *
+ * @param string|null $group The validated group
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function setGroup($group);
+
+ /**
+ * Sets the currently validated constraint.
+ *
+ * @param Constraint $constraint The validated constraint
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function setConstraint(Constraint $constraint);
+
+ /**
+ * Marks an object as validated in a specific validation group.
+ *
+ * @param string $cacheKey The hash of the object
+ * @param string $groupHash The group's name or hash, if it is group
+ * sequence
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function markGroupAsValidated($cacheKey, $groupHash);
+
+ /**
+ * Returns whether an object was validated in a specific validation group.
+ *
+ * @param string $cacheKey The hash of the object
+ * @param string $groupHash The group's name or hash, if it is group
+ * sequence
+ *
+ * @return bool Whether the object was already validated for that
+ * group
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function isGroupValidated($cacheKey, $groupHash);
+
+ /**
+ * Marks a constraint as validated for an object.
+ *
+ * @param string $cacheKey The hash of the object
+ * @param string $constraintHash The hash of the constraint
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function markConstraintAsValidated($cacheKey, $constraintHash);
+
+ /**
+ * Returns whether a constraint was validated for an object.
+ *
+ * @param string $cacheKey The hash of the object
+ * @param string $constraintHash The hash of the constraint
+ *
+ * @return bool Whether the constraint was already validated
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ */
+ public function isConstraintValidated($cacheKey, $constraintHash);
+
+ /**
+ * Marks that an object was initialized.
+ *
+ * @param string $cacheKey The hash of the object
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ *
+ * @see ObjectInitializerInterface
+ */
+ public function markObjectAsInitialized($cacheKey);
+
+ /**
+ * Returns whether an object was initialized.
+ *
+ * @param string $cacheKey The hash of the object
+ *
+ * @return bool Whether the object was already initialized
+ *
+ * @internal Used by the validator engine. Should not be called by user
+ * code.
+ *
+ * @see ObjectInitializerInterface
+ */
+ public function isObjectInitialized($cacheKey);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContext.php b/public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContext.php
new file mode 100644
index 0000000..8c49c70
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContext.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Context;
+
+@trigger_error('The '.__NAMESPACE__.'\LegacyExecutionContext class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * An execution context that is compatible with the legacy API (< 2.5).
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+class LegacyExecutionContext extends ExecutionContext
+{
+ /**
+ * Creates a new context.
+ *
+ * @see ExecutionContext::__construct()
+ *
+ * @internal Called by {@link LegacyExecutionContextFactory}. Should not be used
+ * in user code.
+ */
+ public function __construct(ValidatorInterface $validator, $root, MetadataFactoryInterface $metadataFactory, TranslatorInterface $translator, $translationDomain = null)
+ {
+ parent::__construct(
+ $validator,
+ $root,
+ $translator,
+ $translationDomain
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContextFactory.php b/public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContextFactory.php
new file mode 100644
index 0000000..3cd4f79
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Context/LegacyExecutionContextFactory.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Context;
+
+@trigger_error('The '.__NAMESPACE__.'\LegacyExecutionContextFactory class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * Creates new {@link LegacyExecutionContext} instances.
+ *
+ * Implemented for backward compatibility with Symfony < 2.5.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+class LegacyExecutionContextFactory implements ExecutionContextFactoryInterface
+{
+ private $metadataFactory;
+ private $translator;
+ private $translationDomain;
+
+ /**
+ * Creates a new context factory.
+ *
+ * @param MetadataFactoryInterface $metadataFactory The metadata factory
+ * @param TranslatorInterface $translator The translator
+ * @param string|null $translationDomain The translation domain
+ * to use for translating
+ * violation messages
+ */
+ public function __construct(MetadataFactoryInterface $metadataFactory, TranslatorInterface $translator, $translationDomain = null)
+ {
+ $this->metadataFactory = $metadataFactory;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createContext(ValidatorInterface $validator, $root)
+ {
+ return new LegacyExecutionContext(
+ $validator,
+ $root,
+ $this->metadataFactory,
+ $this->translator,
+ $this->translationDomain
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/DefaultTranslator.php b/public/system/storage/vendor/symfony/validator/DefaultTranslator.php
new file mode 100644
index 0000000..cd9b5d8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/DefaultTranslator.php
@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+@trigger_error('The class '.__NAMESPACE__.'\DefaultTranslator is deprecated since Symfony 2.7 and will be removed in 3.0. Use Symfony\Component\Translation\IdentityTranslator instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Exception\BadMethodCallException;
+use Symfony\Component\Validator\Exception\InvalidArgumentException;
+
+/**
+ * Simple translator implementation that simply replaces the parameters in
+ * the message IDs.
+ *
+ * Example usage:
+ *
+ * $translator = new DefaultTranslator();
+ *
+ * echo $translator->trans(
+ * 'This is a {{ var }}.',
+ * array('{{ var }}' => 'donkey')
+ * );
+ *
+ * // -> This is a donkey.
+ *
+ * echo $translator->transChoice(
+ * 'This is {{ count }} donkey.|These are {{ count }} donkeys.',
+ * 3,
+ * array('{{ count }}' => 'three')
+ * );
+ *
+ * // -> These are three donkeys.
+ *
+ * This translator does not support message catalogs, translation domains or
+ * locales. Instead, it implements a subset of the capabilities of
+ * {@link \Symfony\Component\Translation\Translator} and can be used in places
+ * where translation is not required by default but should be optional.
+ *
+ * @deprecated since version 2.7, to be removed in 3.0. Use Symfony\Component\Translation\IdentityTranslator instead.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class DefaultTranslator implements TranslatorInterface
+{
+ /**
+ * Interpolates the given message.
+ *
+ * Parameters are replaced in the message in the same manner that
+ * {@link strtr()} uses.
+ *
+ * Example usage:
+ *
+ * $translator = new DefaultTranslator();
+ *
+ * echo $translator->trans(
+ * 'This is a {{ var }}.',
+ * array('{{ var }}' => 'donkey')
+ * );
+ *
+ * // -> This is a donkey.
+ *
+ * @param string $id The message id
+ * @param array $parameters An array of parameters for the message
+ * @param string $domain Ignored
+ * @param string $locale Ignored
+ *
+ * @return string The interpolated string
+ */
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+ {
+ return strtr($id, $parameters);
+ }
+
+ /**
+ * Interpolates the given choice message by choosing a variant according to a number.
+ *
+ * The variants are passed in the message ID using the format
+ * "<singular>|<plural>". "<singular>" is chosen if the passed $number is
+ * exactly 1. "<plural>" is chosen otherwise.
+ *
+ * This format is consistent with the format supported by
+ * {@link \Symfony\Component\Translation\Translator}, but it does not
+ * have the same expressiveness. While Translator supports intervals in
+ * message translations, which are needed for languages other than English,
+ * this translator does not. You should use Translator or a custom
+ * implementation of {@link \Symfony\Component\Translation\TranslatorInterface} if you need this or similar
+ * functionality.
+ *
+ * Example usage:
+ *
+ * echo $translator->transChoice(
+ * 'This is {{ count }} donkey.|These are {{ count }} donkeys.',
+ * 0,
+ * array('{{ count }}' => 0)
+ * );
+ *
+ * // -> These are 0 donkeys.
+ *
+ * echo $translator->transChoice(
+ * 'This is {{ count }} donkey.|These are {{ count }} donkeys.',
+ * 1,
+ * array('{{ count }}' => 1)
+ * );
+ *
+ * // -> This is 1 donkey.
+ *
+ * echo $translator->transChoice(
+ * 'This is {{ count }} donkey.|These are {{ count }} donkeys.',
+ * 3,
+ * array('{{ count }}' => 3)
+ * );
+ *
+ * // -> These are 3 donkeys.
+ *
+ * @param string $id The message id
+ * @param int $number The number to use to find the index of the message
+ * @param array $parameters An array of parameters for the message
+ * @param string $domain Ignored
+ * @param string $locale Ignored
+ *
+ * @return string The translated string
+ *
+ * @throws InvalidArgumentException if the message id does not have the format
+ * "singular|plural"
+ */
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+ {
+ $ids = explode('|', $id);
+
+ if (1 == $number) {
+ return strtr($ids[0], $parameters);
+ }
+
+ if (!isset($ids[1])) {
+ throw new InvalidArgumentException(sprintf('The message "%s" cannot be pluralized, because it is missing a plural (e.g. "There is one apple|There are %%count%% apples").', $id));
+ }
+
+ return strtr($ids[1], $parameters);
+ }
+
+ /**
+ * Not supported.
+ *
+ * @param string $locale The locale
+ *
+ * @throws BadMethodCallException
+ */
+ public function setLocale($locale)
+ {
+ throw new BadMethodCallException('Unsupported method.');
+ }
+
+ /**
+ * Returns the locale of the translator.
+ *
+ * @return string Always returns 'en'
+ */
+ public function getLocale()
+ {
+ return 'en';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/BadMethodCallException.php b/public/system/storage/vendor/symfony/validator/Exception/BadMethodCallException.php
new file mode 100644
index 0000000..939161b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/BadMethodCallException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * Base BadMethodCallException for the Validator component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/ConstraintDefinitionException.php b/public/system/storage/vendor/symfony/validator/Exception/ConstraintDefinitionException.php
new file mode 100644
index 0000000..b24fdd6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/ConstraintDefinitionException.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class ConstraintDefinitionException extends ValidatorException
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/ExceptionInterface.php b/public/system/storage/vendor/symfony/validator/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..77d09b9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * Base ExceptionInterface for the Validator component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/GroupDefinitionException.php b/public/system/storage/vendor/symfony/validator/Exception/GroupDefinitionException.php
new file mode 100644
index 0000000..ab7e91d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/GroupDefinitionException.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class GroupDefinitionException extends ValidatorException
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/InvalidArgumentException.php b/public/system/storage/vendor/symfony/validator/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..22da39b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/InvalidArgumentException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * Base InvalidArgumentException for the Validator component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/InvalidOptionsException.php b/public/system/storage/vendor/symfony/validator/Exception/InvalidOptionsException.php
new file mode 100644
index 0000000..ce87c42
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/InvalidOptionsException.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class InvalidOptionsException extends ValidatorException
+{
+ private $options;
+
+ public function __construct($message, array $options)
+ {
+ parent::__construct($message);
+
+ $this->options = $options;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/MappingException.php b/public/system/storage/vendor/symfony/validator/Exception/MappingException.php
new file mode 100644
index 0000000..4c8c057
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/MappingException.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class MappingException extends ValidatorException
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/MissingOptionsException.php b/public/system/storage/vendor/symfony/validator/Exception/MissingOptionsException.php
new file mode 100644
index 0000000..07c5d9e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/MissingOptionsException.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class MissingOptionsException extends ValidatorException
+{
+ private $options;
+
+ public function __construct($message, array $options)
+ {
+ parent::__construct($message);
+
+ $this->options = $options;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/NoSuchMetadataException.php b/public/system/storage/vendor/symfony/validator/Exception/NoSuchMetadataException.php
new file mode 100644
index 0000000..4cac74c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/NoSuchMetadataException.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NoSuchMetadataException extends ValidatorException
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/OutOfBoundsException.php b/public/system/storage/vendor/symfony/validator/Exception/OutOfBoundsException.php
new file mode 100644
index 0000000..30906e8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/OutOfBoundsException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * Base OutOfBoundsException for the Validator component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/RuntimeException.php b/public/system/storage/vendor/symfony/validator/Exception/RuntimeException.php
new file mode 100644
index 0000000..df4a50c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/RuntimeException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * Base RuntimeException for the Validator component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/UnexpectedTypeException.php b/public/system/storage/vendor/symfony/validator/Exception/UnexpectedTypeException.php
new file mode 100644
index 0000000..485dbca
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/UnexpectedTypeException.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class UnexpectedTypeException extends ValidatorException
+{
+ public function __construct($value, $expectedType)
+ {
+ parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, \is_object($value) ? \get_class($value) : \gettype($value)));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/UnsupportedMetadataException.php b/public/system/storage/vendor/symfony/validator/Exception/UnsupportedMetadataException.php
new file mode 100644
index 0000000..aff569b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/UnsupportedMetadataException.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class UnsupportedMetadataException extends InvalidArgumentException
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Exception/ValidatorException.php b/public/system/storage/vendor/symfony/validator/Exception/ValidatorException.php
new file mode 100644
index 0000000..28bd470
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Exception/ValidatorException.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Exception;
+
+class ValidatorException extends RuntimeException
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/ExecutionContext.php b/public/system/storage/vendor/symfony/validator/ExecutionContext.php
new file mode 100644
index 0000000..8d93e69
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ExecutionContext.php
@@ -0,0 +1,269 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+@trigger_error('The '.__NAMESPACE__.'\ExecutionContext class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Validator\Context\ExecutionContext class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+
+/**
+ * Default implementation of {@link ExecutionContextInterface}.
+ *
+ * This class is immutable by design.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContext} instead.
+ */
+class ExecutionContext implements ExecutionContextInterface
+{
+ private $globalContext;
+ private $translator;
+ private $translationDomain;
+ private $metadata;
+ private $value;
+ private $group;
+ private $propertyPath;
+
+ /**
+ * Creates a new execution context.
+ *
+ * @param GlobalExecutionContextInterface $globalContext The global context storing node-independent state
+ * @param TranslatorInterface $translator The translator for translating violation messages
+ * @param string|null $translationDomain The domain of the validation messages
+ * @param MetadataInterface $metadata The metadata of the validated node
+ * @param mixed $value The value of the validated node
+ * @param string $group The current validation group
+ * @param string $propertyPath The property path to the current node
+ */
+ public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '')
+ {
+ if (null === $group) {
+ $group = Constraint::DEFAULT_GROUP;
+ }
+
+ $this->globalContext = $globalContext;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ $this->metadata = $metadata;
+ $this->value = $value;
+ $this->propertyPath = $propertyPath;
+ $this->group = $group;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addViolation($message, array $params = array(), $invalidValue = null, $plural = null, $code = null)
+ {
+ if (null === $plural) {
+ $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain);
+ } else {
+ try {
+ $translatedMessage = $this->translator->transChoice($message, $plural, $params, $this->translationDomain);
+ } catch (\InvalidArgumentException $e) {
+ $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain);
+ }
+ }
+
+ $this->globalContext->getViolations()->add(new ConstraintViolation(
+ $translatedMessage,
+ $message,
+ $params,
+ $this->globalContext->getRoot(),
+ $this->propertyPath,
+ // check using func_num_args() to allow passing null values
+ \func_num_args() >= 3 ? $invalidValue : $this->value,
+ $plural,
+ $code
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null)
+ {
+ $this->globalContext->getViolations()->add(new ConstraintViolation(
+ null === $plural
+ ? $this->translator->trans($message, $parameters, $this->translationDomain)
+ : $this->translator->transChoice($message, $plural, $parameters, $this->translationDomain),
+ $message,
+ $parameters,
+ $this->globalContext->getRoot(),
+ $this->getPropertyPath($subPath),
+ // check using func_num_args() to allow passing null values
+ \func_num_args() >= 4 ? $invalidValue : $this->value,
+ $plural,
+ $code
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getViolations()
+ {
+ return $this->globalContext->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRoot()
+ {
+ return $this->globalContext->getRoot();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyPath($subPath = '')
+ {
+ if ('' != $subPath && '' !== $this->propertyPath && '[' !== $subPath[0]) {
+ return $this->propertyPath.'.'.$subPath;
+ }
+
+ return $this->propertyPath.$subPath;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getClassName()
+ {
+ if ($this->metadata instanceof ClassBasedInterface) {
+ return $this->metadata->getClassName();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyName()
+ {
+ if ($this->metadata instanceof PropertyMetadataInterface) {
+ return $this->metadata->getPropertyName();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroup()
+ {
+ return $this->group;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata()
+ {
+ return $this->metadata;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFor($value)
+ {
+ return $this->globalContext->getMetadataFactory()->getMetadataFor($value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false)
+ {
+ $propertyPath = $this->getPropertyPath($subPath);
+
+ $visitor = $this->globalContext->getVisitor();
+ foreach ($this->resolveGroups($groups) as $group) {
+ $visitor->validate($value, $group, $propertyPath, $traverse, $deep);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateValue($value, $constraints, $subPath = '', $groups = null)
+ {
+ $constraints = \is_array($constraints) ? $constraints : array($constraints);
+
+ if (null === $groups && '' === $subPath) {
+ $context = clone $this;
+ $context->value = $value;
+ $context->executeConstraintValidators($value, $constraints);
+
+ return;
+ }
+
+ $propertyPath = $this->getPropertyPath($subPath);
+
+ foreach ($this->resolveGroups($groups) as $group) {
+ $context = clone $this;
+ $context->value = $value;
+ $context->group = $group;
+ $context->propertyPath = $propertyPath;
+ $context->executeConstraintValidators($value, $constraints);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFactory()
+ {
+ return $this->globalContext->getMetadataFactory();
+ }
+
+ /**
+ * Executes the validators of the given constraints for the given value.
+ *
+ * @param mixed $value The value to validate
+ * @param Constraint[] $constraints The constraints to match against
+ */
+ private function executeConstraintValidators($value, array $constraints)
+ {
+ foreach ($constraints as $constraint) {
+ $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint);
+ $validator->initialize($this);
+ $validator->validate($value, $constraint);
+ }
+ }
+
+ /**
+ * Returns an array of group names.
+ *
+ * @param string|string[]|null $groups The groups to resolve. If a single string is
+ * passed, it is converted to an array. If null
+ * is passed, an array containing the current
+ * group of the context is returned.
+ *
+ * @return array An array of validation groups
+ */
+ private function resolveGroups($groups)
+ {
+ return $groups ? (array) $groups : (array) $this->group;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ExecutionContextInterface.php b/public/system/storage/vendor/symfony/validator/ExecutionContextInterface.php
new file mode 100644
index 0000000..4d5d2f6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ExecutionContextInterface.php
@@ -0,0 +1,299 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Stores the validator's state during validation.
+ *
+ * For example, let's validate the following object graph:
+ *
+ * (Person)---($firstName: string)
+ * \
+ * ($address: Address)---($street: string)
+ *
+ * We validate the <tt>Person</tt> instance, which becomes the "root" of the
+ * validation run (see {@link getRoot}). The state of the context after the
+ * first step will be like this:
+ *
+ * (Person)---($firstName: string)
+ * ^ \
+ * ($address: Address)---($street: string)
+ *
+ * The validator is stopped at the <tt>Person</tt> node, both the root and the
+ * value (see {@link getValue}) of the context point to the <tt>Person</tt>
+ * instance. The property path is empty at this point (see {@link getPropertyPath}).
+ * The metadata of the context is the metadata of the <tt>Person</tt> node
+ * (see {@link getMetadata}).
+ *
+ * After advancing to the property <tt>$firstName</tt> of the <tt>Person</tt>
+ * instance, the state of the context looks like this:
+ *
+ * (Person)---($firstName: string)
+ * \ ^
+ * ($address: Address)---($street: string)
+ *
+ * The validator is stopped at the property <tt>$firstName</tt>. The root still
+ * points to the <tt>Person</tt> instance, because this is where the validation
+ * started. The property path is now "firstName" and the current value is the
+ * value of that property.
+ *
+ * After advancing to the <tt>$address</tt> property and then to the
+ * <tt>$street</tt> property of the <tt>Address</tt> instance, the context state
+ * looks like this:
+ *
+ * (Person)---($firstName: string)
+ * \
+ * ($address: Address)---($street: string)
+ * ^
+ *
+ * The validator is stopped at the property <tt>$street</tt>. The root still
+ * points to the <tt>Person</tt> instance, but the property path is now
+ * "address.street" and the validated value is the value of that property.
+ *
+ * Apart from the root, the property path and the currently validated value,
+ * the execution context also knows the metadata of the current node (see
+ * {@link getMetadata}) which for example returns a {@link Mapping\PropertyMetadata}
+ * or a {@link Mapping\ClassMetadata} object. he context also contains the
+ * validation group that is currently being validated (see {@link getGroup}) and
+ * the violations that happened up until now (see {@link getViolations}).
+ *
+ * Apart from reading the execution context, you can also use
+ * {@link addViolation} or {@link addViolationAt} to add new violations and
+ * {@link validate} or {@link validateValue} to validate values that the
+ * validator otherwise would not reach.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContextInterface} instead.
+ */
+interface ExecutionContextInterface
+{
+ /**
+ * Adds a violation at the current node of the validation graph.
+ *
+ * Note: the parameters $invalidValue, $plural and $code are deprecated since version 2.5 and will be removed in 3.0.
+ *
+ * @param string $message The error message
+ * @param array $params The parameters substituted in the error message
+ * @param mixed $invalidValue The invalid, validated value
+ * @param int|null $plural The number to use to pluralize of the message
+ * @param int|null $code The violation code
+ */
+ public function addViolation($message, array $params = array(), $invalidValue = null, $plural = null, $code = null);
+
+ /**
+ * Adds a violation at the validation graph node with the given property
+ * path relative to the current property path.
+ *
+ * @param string $subPath The relative property path for the violation
+ * @param string $message The error message
+ * @param array $parameters The parameters substituted in the error message
+ * @param mixed $invalidValue The invalid, validated value
+ * @param int|null $plural The number to use to pluralize of the message
+ * @param int|null $code The violation code
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContextInterface::buildViolation()}
+ * instead.
+ */
+ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null);
+
+ /**
+ * Validates the given value within the scope of the current validation.
+ *
+ * The value may be any value recognized by the used metadata factory
+ * (see {@link MetadataFactoryInterface::getMetadata}), or an array or a
+ * traversable object of such values.
+ *
+ * Usually you validate a value that is not the current node of the
+ * execution context. For this case, you can pass the {@link $subPath}
+ * argument which is appended to the current property path when a violation
+ * is created. For example, take the following object graph:
+ *
+ * (Person)---($address: Address)---($phoneNumber: PhoneNumber)
+ *
+ * When the execution context stops at the <tt>Person</tt> instance, the
+ * property path is "address". When you validate the <tt>PhoneNumber</tt>
+ * instance now, pass "phoneNumber" as sub path to correct the property path
+ * to "address.phoneNumber":
+ *
+ * $context->validate($address->phoneNumber, 'phoneNumber');
+ *
+ * Any violations generated during the validation will be added to the
+ * violation list that you can access with {@link getViolations}.
+ *
+ * @param mixed $value The value to validate
+ * @param string $subPath The path to append to the context's property path
+ * @param string|string[]|null $groups The groups to validate in. If you don't pass any
+ * groups here, the current group of the context
+ * will be used.
+ * @param bool $traverse Whether to traverse the value if it is an array
+ * or an instance of <tt>\Traversable</tt>
+ * @param bool $deep Whether to traverse the value recursively if
+ * it is a collection of collections
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContextInterface::getValidator()}
+ * instead.
+ */
+ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false);
+
+ /**
+ * Validates a value against a constraint.
+ *
+ * Use the parameter <tt>$subPath</tt> to adapt the property path for the
+ * validated value. For example, take the following object graph:
+ *
+ * (Person)---($address: Address)---($street: string)
+ *
+ * When the validator validates the <tt>Address</tt> instance, the
+ * property path stored in the execution context is "address". When you
+ * manually validate the property <tt>$street</tt> now, pass the sub path
+ * "street" to adapt the full property path to "address.street":
+ *
+ * $context->validate($address->street, new NotNull(), 'street');
+ *
+ * @param mixed $value The value to validate
+ * @param Constraint|Constraint[] $constraints The constraint(s) to validate against
+ * @param string $subPath The path to append to the context's property path
+ * @param string|string[]|null $groups The groups to validate in. If you don't pass any
+ * groups here, the current group of the context
+ * will be used.
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContextInterface::getValidator()}
+ * instead.
+ */
+ public function validateValue($value, $constraints, $subPath = '', $groups = null);
+
+ /**
+ * Returns the violations generated by the validator so far.
+ *
+ * @return ConstraintViolationListInterface The constraint violation list
+ */
+ public function getViolations();
+
+ /**
+ * Returns the value at which validation was started in the object graph.
+ *
+ * The validator, when given an object, traverses the properties and
+ * related objects and their properties. The root of the validation is the
+ * object from which the traversal started.
+ *
+ * The current value is returned by {@link getValue}.
+ *
+ * @return mixed The root value of the validation
+ */
+ public function getRoot();
+
+ /**
+ * Returns the value that the validator is currently validating.
+ *
+ * If you want to retrieve the object that was originally passed to the
+ * validator, use {@link getRoot}.
+ *
+ * @return mixed The currently validated value
+ */
+ public function getValue();
+
+ /**
+ * Returns the metadata for the currently validated value.
+ *
+ * With the core implementation, this method returns a
+ * {@link Mapping\ClassMetadata} instance if the current value is an object,
+ * a {@link Mapping\PropertyMetadata} instance if the current value is
+ * the value of a property and a {@link Mapping\GetterMetadata} instance if
+ * the validated value is the result of a getter method.
+ *
+ * If the validated value is neither of these, for example if the validator
+ * has been called with a plain value and constraint, this method returns
+ * null.
+ *
+ * @return MetadataInterface|null the metadata of the currently validated
+ * value
+ */
+ public function getMetadata();
+
+ /**
+ * Returns the used metadata factory.
+ *
+ * @return MetadataFactoryInterface The metadata factory
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContextInterface::getValidator()}
+ * instead and call
+ * {@link Validator\ValidatorInterface::getMetadataFor()} or
+ * {@link Validator\ValidatorInterface::hasMetadataFor()} there.
+ */
+ public function getMetadataFactory();
+
+ /**
+ * Returns the validation group that is currently being validated.
+ *
+ * @return string The current validation group
+ */
+ public function getGroup();
+
+ /**
+ * Returns the class name of the current node.
+ *
+ * If the metadata of the current node does not implement
+ * {@link ClassBasedInterface} or if no metadata is available for the
+ * current node, this method returns null.
+ *
+ * @return string|null The class name or null, if no class name could be found
+ */
+ public function getClassName();
+
+ /**
+ * Returns the property name of the current node.
+ *
+ * If the metadata of the current node does not implement
+ * {@link PropertyMetadataInterface} or if no metadata is available for the
+ * current node, this method returns null.
+ *
+ * @return string|null The property name or null, if no property name could be found
+ */
+ public function getPropertyName();
+
+ /**
+ * Returns the property path to the value that the validator is currently
+ * validating.
+ *
+ * For example, take the following object graph:
+ *
+ * (Person)---($address: Address)---($street: string)
+ *
+ * When the <tt>Person</tt> instance is passed to the validator, the
+ * property path is initially empty. When the <tt>$address</tt> property
+ * of that person is validated, the property path is "address". When
+ * the <tt>$street</tt> property of the related <tt>Address</tt> instance
+ * is validated, the property path is "address.street".
+ *
+ * Properties of objects are prefixed with a dot in the property path.
+ * Indices of arrays or objects implementing the {@link \ArrayAccess}
+ * interface are enclosed in brackets. For example, if the property in
+ * the previous example is <tt>$addresses</tt> and contains an array
+ * of <tt>Address</tt> instance, the property path generated for the
+ * <tt>$street</tt> property of one of these addresses is for example
+ * "addresses[0].street".
+ *
+ * @param string $subPath Optional. The suffix appended to the current
+ * property path.
+ *
+ * @return string The current property path. The result may be an empty
+ * string if the validator is currently validating the
+ * root value of the validation graph.
+ */
+ public function getPropertyPath($subPath = '');
+}
diff --git a/public/system/storage/vendor/symfony/validator/GlobalExecutionContextInterface.php b/public/system/storage/vendor/symfony/validator/GlobalExecutionContextInterface.php
new file mode 100644
index 0000000..d9bd315
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/GlobalExecutionContextInterface.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Stores the node-independent state of a validation run.
+ *
+ * When the validator validates a graph of objects, it uses two classes to
+ * store the state during the validation:
+ *
+ * <ul>
+ * <li>For each node in the validation graph (objects, properties, getters) the
+ * validator creates an instance of {@link ExecutionContextInterface} that
+ * stores the information about that node.</li>
+ * <li>One single <tt>GlobalExecutionContextInterface</tt> stores the state
+ * that is independent of the current node.</li>
+ * </ul>
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Context\ExecutionContextInterface} instead.
+ */
+interface GlobalExecutionContextInterface
+{
+ /**
+ * Returns the violations generated by the validator so far.
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations
+ */
+ public function getViolations();
+
+ /**
+ * Returns the value at which validation was started in the object graph.
+ *
+ * @return mixed The root value
+ *
+ * @see ExecutionContextInterface::getRoot()
+ */
+ public function getRoot();
+
+ /**
+ * Returns the visitor instance used to validate the object graph nodes.
+ *
+ * @return ValidationVisitorInterface The validation visitor
+ */
+ public function getVisitor();
+
+ /**
+ * Returns the factory for constraint validators.
+ *
+ * @return ConstraintValidatorFactoryInterface The constraint validator factory
+ */
+ public function getValidatorFactory();
+
+ /**
+ * Returns the factory for validation metadata objects.
+ *
+ * @return MetadataFactoryInterface The metadata factory
+ */
+ public function getMetadataFactory();
+}
diff --git a/public/system/storage/vendor/symfony/validator/GroupSequenceProviderInterface.php b/public/system/storage/vendor/symfony/validator/GroupSequenceProviderInterface.php
new file mode 100644
index 0000000..5894397
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/GroupSequenceProviderInterface.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+use Symfony\Component\Validator\Constraints\GroupSequence;
+
+/**
+ * Defines the interface for a group sequence provider.
+ */
+interface GroupSequenceProviderInterface
+{
+ /**
+ * Returns which validation groups should be used for a certain state
+ * of the object.
+ *
+ * @return string[]|GroupSequence An array of validation groups
+ */
+ public function getGroupSequence();
+}
diff --git a/public/system/storage/vendor/symfony/validator/LICENSE b/public/system/storage/vendor/symfony/validator/LICENSE
new file mode 100644
index 0000000..21d7fb9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2018 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/BlackholeMetadataFactory.php b/public/system/storage/vendor/symfony/validator/Mapping/BlackholeMetadataFactory.php
new file mode 100644
index 0000000..34a3b44
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/BlackholeMetadataFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+@trigger_error('The '.__NAMESPACE__.'\BlackholeMetadataFactory class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Validator\Mapping\Factory\BlackHoleMetadataFactory class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Validator\Mapping\Factory\BlackHoleMetadataFactory as MappingBlackHoleMetadataFactory;
+
+/**
+ * Alias of {@link Factory\BlackHoleMetadataFactory}.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Factory\BlackHoleMetadataFactory} instead.
+ */
+class BlackholeMetadataFactory extends MappingBlackHoleMetadataFactory
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Cache/ApcCache.php b/public/system/storage/vendor/symfony/validator/Mapping/Cache/ApcCache.php
new file mode 100644
index 0000000..0adaf04
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Cache/ApcCache.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Cache;
+
+@trigger_error('The '.__NAMESPACE__.'\ApcCache class is deprecated since Symfony 2.5 and will be removed in 3.0. Use DoctrineCache with the Doctrine\Common\Cache\ApcCache class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use DoctrineCache with \Doctrine\Common\Cache\ApcCache instead.
+ */
+class ApcCache implements CacheInterface
+{
+ private $prefix;
+
+ public function __construct($prefix)
+ {
+ if (!\extension_loaded('apc')) {
+ throw new \RuntimeException('Unable to use ApcCache to cache validator mappings as APC is not enabled.');
+ }
+
+ $this->prefix = $prefix;
+ }
+
+ public function has($class)
+ {
+ if (!\function_exists('apc_exists')) {
+ $exists = false;
+
+ apc_fetch($this->prefix.$class, $exists);
+
+ return $exists;
+ }
+
+ return apc_exists($this->prefix.$class);
+ }
+
+ public function read($class)
+ {
+ return apc_fetch($this->prefix.$class);
+ }
+
+ public function write(ClassMetadata $metadata)
+ {
+ apc_store($this->prefix.$metadata->getClassName(), $metadata);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Cache/CacheInterface.php b/public/system/storage/vendor/symfony/validator/Mapping/Cache/CacheInterface.php
new file mode 100644
index 0000000..f770f46
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Cache/CacheInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Cache;
+
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Persists ClassMetadata instances in a cache.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface CacheInterface
+{
+ /**
+ * Returns whether metadata for the given class exists in the cache.
+ *
+ * @param string $class
+ */
+ public function has($class);
+
+ /**
+ * Returns the metadata for the given class from the cache.
+ *
+ * @param string $class Class Name
+ *
+ * @return ClassMetadata|false A ClassMetadata instance or false on miss
+ */
+ public function read($class);
+
+ /**
+ * Stores a class metadata in the cache.
+ */
+ public function write(ClassMetadata $metadata);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Cache/DoctrineCache.php b/public/system/storage/vendor/symfony/validator/Mapping/Cache/DoctrineCache.php
new file mode 100644
index 0000000..36f1feb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Cache/DoctrineCache.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Cache;
+
+use Doctrine\Common\Cache\Cache;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Adapts a Doctrine cache to a CacheInterface.
+ *
+ * @author Florian Voutzinos <florian@voutzinos.com>
+ */
+final class DoctrineCache implements CacheInterface
+{
+ private $cache;
+
+ public function __construct(Cache $cache)
+ {
+ $this->cache = $cache;
+ }
+
+ public function setCache(Cache $cache)
+ {
+ $this->cache = $cache;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($class)
+ {
+ return $this->cache->contains($class);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read($class)
+ {
+ return $this->cache->fetch($class);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write(ClassMetadata $metadata)
+ {
+ $this->cache->save($metadata->getClassName(), $metadata);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/CascadingStrategy.php b/public/system/storage/vendor/symfony/validator/Mapping/CascadingStrategy.php
new file mode 100644
index 0000000..c78fb42
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/CascadingStrategy.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+/**
+ * Specifies whether an object should be cascaded.
+ *
+ * Cascading is relevant for any node type but class nodes. If such a node
+ * contains an object of value, and if cascading is enabled, then the node
+ * traverser will try to find class metadata for that object and validate the
+ * object against that metadata.
+ *
+ * If no metadata is found for a cascaded object, and if that object implements
+ * {@link \Traversable}, the node traverser will iterate over the object and
+ * cascade each object or collection contained within, unless iteration is
+ * prohibited by the specified {@link TraversalStrategy}.
+ *
+ * Although the constants currently represent a boolean switch, they are
+ * implemented as bit mask in order to allow future extensions.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see TraversalStrategy
+ */
+class CascadingStrategy
+{
+ /**
+ * Specifies that a node should not be cascaded.
+ */
+ const NONE = 1;
+
+ /**
+ * Specifies that a node should be cascaded.
+ */
+ const CASCADE = 2;
+
+ /**
+ * Not instantiable.
+ */
+ private function __construct()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadata.php b/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadata.php
new file mode 100644
index 0000000..c3a6544
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadata.php
@@ -0,0 +1,591 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\Constraints\Traverse;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\GroupDefinitionException;
+use Symfony\Component\Validator\ValidationVisitorInterface;
+
+/**
+ * Default implementation of {@link ClassMetadataInterface}.
+ *
+ * This class supports serialization and cloning.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ClassMetadata extends ElementMetadata implements ClassMetadataInterface
+{
+ /**
+ * @var string
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getClassName()} instead.
+ */
+ public $name;
+
+ /**
+ * @var string
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getDefaultGroup()} instead.
+ */
+ public $defaultGroup;
+
+ /**
+ * @var MemberMetadata[][]
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getPropertyMetadata()} instead.
+ */
+ public $members = array();
+
+ /**
+ * @var PropertyMetadata[]
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getPropertyMetadata()} instead.
+ */
+ public $properties = array();
+
+ /**
+ * @var GetterMetadata[]
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getPropertyMetadata()} instead.
+ */
+ public $getters = array();
+
+ /**
+ * @var array
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getGroupSequence()} instead.
+ */
+ public $groupSequence = array();
+
+ /**
+ * @var bool
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link isGroupSequenceProvider()} instead.
+ */
+ public $groupSequenceProvider = false;
+
+ /**
+ * The strategy for traversing traversable objects.
+ *
+ * By default, only instances of {@link \Traversable} are traversed.
+ *
+ * @var int
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getTraversalStrategy()} instead.
+ */
+ public $traversalStrategy = TraversalStrategy::IMPLICIT;
+
+ /**
+ * @var \ReflectionClass
+ */
+ private $reflClass;
+
+ /**
+ * Constructs a metadata for the given class.
+ *
+ * @param string $class
+ */
+ public function __construct($class)
+ {
+ $this->name = $class;
+ // class name without namespace
+ if (false !== $nsSep = strrpos($class, '\\')) {
+ $this->defaultGroup = substr($class, $nsSep + 1);
+ } else {
+ $this->defaultGroup = $class;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group
+ && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) {
+ if ($this->hasGroupSequence()) {
+ $groups = $this->getGroupSequence()->groups;
+ } else {
+ $groups = $value->getGroupSequence();
+ }
+
+ foreach ($groups as $group) {
+ $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP);
+
+ if (\count($visitor->getViolations()) > 0) {
+ break;
+ }
+ }
+
+ return;
+ }
+
+ $visitor->visit($this, $value, $group, $propertyPath);
+
+ if (null !== $value) {
+ $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'.';
+
+ foreach ($this->getConstrainedProperties() as $property) {
+ foreach ($this->getPropertyMetadata($property) as $member) {
+ $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __sleep()
+ {
+ $parentProperties = parent::__sleep();
+
+ // Don't store the cascading strategy. Classes never cascade.
+ unset($parentProperties[array_search('cascadingStrategy', $parentProperties)]);
+
+ return array_merge($parentProperties, array(
+ 'getters',
+ 'groupSequence',
+ 'groupSequenceProvider',
+ 'members',
+ 'name',
+ 'properties',
+ 'defaultGroup',
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getClassName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Returns the name of the default group for this class.
+ *
+ * For each class, the group "Default" is an alias for the group
+ * "<ClassName>", where <ClassName> is the non-namespaced name of the
+ * class. All constraints implicitly or explicitly assigned to group
+ * "Default" belong to both of these groups, unless the class defines
+ * a group sequence.
+ *
+ * If a class defines a group sequence, validating the class in "Default"
+ * will validate the group sequence. The constraints assigned to "Default"
+ * can still be validated by validating the class in "<ClassName>".
+ *
+ * @return string The name of the default group
+ */
+ public function getDefaultGroup()
+ {
+ return $this->defaultGroup;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addConstraint(Constraint $constraint)
+ {
+ if (!\in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) {
+ throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', \get_class($constraint)));
+ }
+
+ if ($constraint instanceof Valid) {
+ throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', \get_class($constraint)));
+ }
+
+ if ($constraint instanceof Traverse) {
+ if ($constraint->traverse) {
+ // If traverse is true, traversal should be explicitly enabled
+ $this->traversalStrategy = TraversalStrategy::TRAVERSE;
+ } else {
+ // If traverse is false, traversal should be explicitly disabled
+ $this->traversalStrategy = TraversalStrategy::NONE;
+ }
+
+ // The constraint is not added
+ return $this;
+ }
+
+ $constraint->addImplicitGroupName($this->getDefaultGroup());
+
+ parent::addConstraint($constraint);
+
+ return $this;
+ }
+
+ /**
+ * Adds a constraint to the given property.
+ *
+ * @param string $property The name of the property
+ * @param Constraint $constraint The constraint
+ *
+ * @return $this
+ */
+ public function addPropertyConstraint($property, Constraint $constraint)
+ {
+ if (!isset($this->properties[$property])) {
+ $this->properties[$property] = new PropertyMetadata($this->getClassName(), $property);
+
+ $this->addPropertyMetadata($this->properties[$property]);
+ }
+
+ $constraint->addImplicitGroupName($this->getDefaultGroup());
+
+ $this->properties[$property]->addConstraint($constraint);
+
+ return $this;
+ }
+
+ /**
+ * @param string $property
+ * @param Constraint[] $constraints
+ *
+ * @return $this
+ */
+ public function addPropertyConstraints($property, array $constraints)
+ {
+ foreach ($constraints as $constraint) {
+ $this->addPropertyConstraint($property, $constraint);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds a constraint to the getter of the given property.
+ *
+ * The name of the getter is assumed to be the name of the property with an
+ * uppercased first letter and either the prefix "get" or "is".
+ *
+ * @param string $property The name of the property
+ * @param Constraint $constraint The constraint
+ *
+ * @return $this
+ */
+ public function addGetterConstraint($property, Constraint $constraint)
+ {
+ if (!isset($this->getters[$property])) {
+ $this->getters[$property] = new GetterMetadata($this->getClassName(), $property);
+
+ $this->addPropertyMetadata($this->getters[$property]);
+ }
+
+ $constraint->addImplicitGroupName($this->getDefaultGroup());
+
+ $this->getters[$property]->addConstraint($constraint);
+
+ return $this;
+ }
+
+ /**
+ * Adds a constraint to the getter of the given property.
+ *
+ * @param string $property The name of the property
+ * @param string $method The name of the getter method
+ * @param Constraint $constraint The constraint
+ *
+ * @return $this
+ */
+ public function addGetterMethodConstraint($property, $method, Constraint $constraint)
+ {
+ if (!isset($this->getters[$property])) {
+ $this->getters[$property] = new GetterMetadata($this->getClassName(), $property, $method);
+
+ $this->addPropertyMetadata($this->getters[$property]);
+ }
+
+ $constraint->addImplicitGroupName($this->getDefaultGroup());
+
+ $this->getters[$property]->addConstraint($constraint);
+
+ return $this;
+ }
+
+ /**
+ * @param string $property
+ * @param Constraint[] $constraints
+ *
+ * @return $this
+ */
+ public function addGetterConstraints($property, array $constraints)
+ {
+ foreach ($constraints as $constraint) {
+ $this->addGetterConstraint($property, $constraint);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string $property
+ * @param string $method
+ * @param Constraint[] $constraints
+ *
+ * @return $this
+ */
+ public function addGetterMethodConstraints($property, $method, array $constraints)
+ {
+ foreach ($constraints as $constraint) {
+ $this->addGetterMethodConstraint($property, $method, $constraint);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Merges the constraints of the given metadata into this object.
+ */
+ public function mergeConstraints(ClassMetadata $source)
+ {
+ if ($source->isGroupSequenceProvider()) {
+ $this->setGroupSequenceProvider(true);
+ }
+
+ foreach ($source->getConstraints() as $constraint) {
+ $this->addConstraint(clone $constraint);
+ }
+
+ foreach ($source->getConstrainedProperties() as $property) {
+ foreach ($source->getPropertyMetadata($property) as $member) {
+ $member = clone $member;
+
+ foreach ($member->getConstraints() as $constraint) {
+ if (\in_array($constraint::DEFAULT_GROUP, $constraint->groups, true)) {
+ $member->constraintsByGroup[$this->getDefaultGroup()][] = $constraint;
+ }
+
+ $constraint->addImplicitGroupName($this->getDefaultGroup());
+ }
+
+ $this->addPropertyMetadata($member);
+
+ if ($member instanceof MemberMetadata && !$member->isPrivate($this->name)) {
+ $property = $member->getPropertyName();
+
+ if ($member instanceof PropertyMetadata && !isset($this->properties[$property])) {
+ $this->properties[$property] = $member;
+ } elseif ($member instanceof GetterMetadata && !isset($this->getters[$property])) {
+ $this->getters[$property] = $member;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a member metadata.
+ *
+ * @param MemberMetadata $metadata
+ *
+ * @deprecated since version 2.6, to be removed in 3.0.
+ */
+ protected function addMemberMetadata(MemberMetadata $metadata)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the addPropertyMetadata() method instead.', E_USER_DEPRECATED);
+
+ $this->addPropertyMetadata($metadata);
+ }
+
+ /**
+ * Returns true if metadatas of members is present for the given property.
+ *
+ * @param string $property The name of the property
+ *
+ * @return bool
+ *
+ * @deprecated since version 2.6, to be removed in 3.0. Use {@link hasPropertyMetadata} instead.
+ */
+ public function hasMemberMetadatas($property)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the hasPropertyMetadata() method instead.', E_USER_DEPRECATED);
+
+ return $this->hasPropertyMetadata($property);
+ }
+
+ /**
+ * Returns all metadatas of members describing the given property.
+ *
+ * @param string $property The name of the property
+ *
+ * @return MemberMetadata[] An array of MemberMetadata
+ *
+ * @deprecated since version 2.6, to be removed in 3.0. Use {@link getPropertyMetadata} instead.
+ */
+ public function getMemberMetadatas($property)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the getPropertyMetadata() method instead.', E_USER_DEPRECATED);
+
+ return $this->getPropertyMetadata($property);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasPropertyMetadata($property)
+ {
+ return array_key_exists($property, $this->members);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyMetadata($property)
+ {
+ if (!isset($this->members[$property])) {
+ return array();
+ }
+
+ return $this->members[$property];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConstrainedProperties()
+ {
+ return array_keys($this->members);
+ }
+
+ /**
+ * Sets the default group sequence for this class.
+ *
+ * @param string[]|GroupSequence $groupSequence An array of group names
+ *
+ * @return $this
+ *
+ * @throws GroupDefinitionException
+ */
+ public function setGroupSequence($groupSequence)
+ {
+ if ($this->isGroupSequenceProvider()) {
+ throw new GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider');
+ }
+
+ if (\is_array($groupSequence)) {
+ $groupSequence = new GroupSequence($groupSequence);
+ }
+
+ if (\in_array(Constraint::DEFAULT_GROUP, $groupSequence->groups, true)) {
+ throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP));
+ }
+
+ if (!\in_array($this->getDefaultGroup(), $groupSequence->groups, true)) {
+ throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup()));
+ }
+
+ $this->groupSequence = $groupSequence;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasGroupSequence()
+ {
+ return $this->groupSequence && \count($this->groupSequence->groups) > 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroupSequence()
+ {
+ return $this->groupSequence;
+ }
+
+ /**
+ * Returns a ReflectionClass instance for this class.
+ *
+ * @return \ReflectionClass
+ */
+ public function getReflectionClass()
+ {
+ if (!$this->reflClass) {
+ $this->reflClass = new \ReflectionClass($this->getClassName());
+ }
+
+ return $this->reflClass;
+ }
+
+ /**
+ * Sets whether a group sequence provider should be used.
+ *
+ * @param bool $active
+ *
+ * @throws GroupDefinitionException
+ */
+ public function setGroupSequenceProvider($active)
+ {
+ if ($this->hasGroupSequence()) {
+ throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence');
+ }
+
+ if (!$this->getReflectionClass()->implementsInterface('Symfony\Component\Validator\GroupSequenceProviderInterface')) {
+ throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface', $this->name));
+ }
+
+ $this->groupSequenceProvider = $active;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isGroupSequenceProvider()
+ {
+ return $this->groupSequenceProvider;
+ }
+
+ /**
+ * Class nodes are never cascaded.
+ *
+ * {@inheritdoc}
+ */
+ public function getCascadingStrategy()
+ {
+ return CascadingStrategy::NONE;
+ }
+
+ private function addPropertyMetadata(PropertyMetadataInterface $metadata)
+ {
+ $property = $metadata->getPropertyName();
+
+ $this->members[$property][] = $metadata;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataFactory.php b/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataFactory.php
new file mode 100644
index 0000000..17c459b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+@trigger_error('The '.__NAMESPACE__.'\ClassMetadataFactory class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
+
+/**
+ * Alias of {@link LazyLoadingMetadataFactory}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link LazyLoadingMetadataFactory} instead.
+ */
+class ClassMetadataFactory extends LazyLoadingMetadataFactory
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataInterface.php b/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataInterface.php
new file mode 100644
index 0000000..d8c3d84
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/ClassMetadataInterface.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\ClassBasedInterface;
+use Symfony\Component\Validator\PropertyMetadataContainerInterface as LegacyPropertyMetadataContainerInterface;
+
+/**
+ * Stores all metadata needed for validating objects of specific class.
+ *
+ * Most importantly, the metadata stores the constraints against which an object
+ * and its properties should be validated.
+ *
+ * Additionally, the metadata stores whether the "Default" group is overridden
+ * by a group sequence for that class and whether instances of that class
+ * should be traversed or not.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see MetadataInterface
+ * @see \Symfony\Component\Validator\Constraints\GroupSequence
+ * @see \Symfony\Component\Validator\GroupSequenceProviderInterface
+ * @see TraversalStrategy
+ */
+interface ClassMetadataInterface extends MetadataInterface, LegacyPropertyMetadataContainerInterface, ClassBasedInterface
+{
+ /**
+ * Returns the names of all constrained properties.
+ *
+ * @return string[] A list of property names
+ */
+ public function getConstrainedProperties();
+
+ /**
+ * Returns whether the "Default" group is overridden by a group sequence.
+ *
+ * If it is, you can access the group sequence with {@link getGroupSequence()}.
+ *
+ * @return bool Returns true if the "Default" group is overridden
+ *
+ * @see \Symfony\Component\Validator\Constraints\GroupSequence
+ */
+ public function hasGroupSequence();
+
+ /**
+ * Returns the group sequence that overrides the "Default" group for this
+ * class.
+ *
+ * @return \Symfony\Component\Validator\Constraints\GroupSequence|null The group sequence or null
+ *
+ * @see \Symfony\Component\Validator\Constraints\GroupSequence
+ */
+ public function getGroupSequence();
+
+ /**
+ * Returns whether the "Default" group is overridden by a dynamic group
+ * sequence obtained by the validated objects.
+ *
+ * If this method returns true, the class must implement
+ * {@link \Symfony\Component\Validator\GroupSequenceProviderInterface}.
+ * This interface will be used to obtain the group sequence when an object
+ * of this class is validated.
+ *
+ * @return bool Returns true if the "Default" group is overridden by
+ * a dynamic group sequence
+ *
+ * @see \Symfony\Component\Validator\GroupSequenceProviderInterface
+ */
+ public function isGroupSequenceProvider();
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/ElementMetadata.php b/public/system/storage/vendor/symfony/validator/Mapping/ElementMetadata.php
new file mode 100644
index 0000000..2c9b080
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/ElementMetadata.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+/**
+ * Contains the metadata of a structural element.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Extend {@link GenericMetadata} instead.
+ */
+abstract class ElementMetadata extends GenericMetadata
+{
+ public function __construct()
+ {
+ if (!$this instanceof MemberMetadata && !$this instanceof ClassMetadata) {
+ @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Validator\Mapping\GenericMetadata class instead.', E_USER_DEPRECATED);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Factory/BlackHoleMetadataFactory.php b/public/system/storage/vendor/symfony/validator/Mapping/Factory/BlackHoleMetadataFactory.php
new file mode 100644
index 0000000..5b38d0c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Factory/BlackHoleMetadataFactory.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Factory;
+
+/**
+ * Metadata factory that does not store metadata.
+ *
+ * This implementation is useful if you want to validate values against
+ * constraints only and you don't need to add constraints to classes and
+ * properties.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class BlackHoleMetadataFactory implements MetadataFactoryInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFor($value)
+ {
+ throw new \LogicException('This class does not support metadata.');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasMetadataFor($value)
+ {
+ return false;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/public/system/storage/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php
new file mode 100644
index 0000000..fc1236e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php
@@ -0,0 +1,167 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Factory;
+
+use Symfony\Component\Validator\Exception\NoSuchMetadataException;
+use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
+use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
+use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
+
+/**
+ * Creates new {@link ClassMetadataInterface} instances.
+ *
+ * Whenever {@link getMetadataFor()} is called for the first time with a given
+ * class name or object of that class, a new metadata instance is created and
+ * returned. On subsequent requests for the same class, the same metadata
+ * instance will be returned.
+ *
+ * You can optionally pass a {@link LoaderInterface} instance to the constructor.
+ * Whenever a new metadata instance is created, it is passed to the loader,
+ * which can configure the metadata based on configuration loaded from the
+ * filesystem or a database. If you want to use multiple loaders, wrap them in a
+ * {@link LoaderChain}.
+ *
+ * You can also optionally pass a {@link CacheInterface} instance to the
+ * constructor. This cache will be used for persisting the generated metadata
+ * between multiple PHP requests.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LazyLoadingMetadataFactory implements MetadataFactoryInterface
+{
+ protected $loader;
+ protected $cache;
+
+ /**
+ * The loaded metadata, indexed by class name.
+ *
+ * @var ClassMetadata[]
+ */
+ protected $loadedClasses = array();
+
+ /**
+ * Creates a new metadata factory.
+ *
+ * @param LoaderInterface|null $loader The loader for configuring new metadata
+ * @param CacheInterface|null $cache The cache for persisting metadata
+ * between multiple PHP requests
+ */
+ public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null)
+ {
+ $this->loader = $loader;
+ $this->cache = $cache;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * If the method was called with the same class name (or an object of that
+ * class) before, the same metadata instance is returned.
+ *
+ * If the factory was configured with a cache, this method will first look
+ * for an existing metadata instance in the cache. If an existing instance
+ * is found, it will be returned without further ado.
+ *
+ * Otherwise, a new metadata instance is created. If the factory was
+ * configured with a loader, the metadata is passed to the
+ * {@link LoaderInterface::loadClassMetadata()} method for further
+ * configuration. At last, the new object is returned.
+ */
+ public function getMetadataFor($value)
+ {
+ if (!\is_object($value) && !\is_string($value)) {
+ throw new NoSuchMetadataException(sprintf('Cannot create metadata for non-objects. Got: %s', \gettype($value)));
+ }
+
+ $class = ltrim(\is_object($value) ? \get_class($value) : $value, '\\');
+
+ if (isset($this->loadedClasses[$class])) {
+ return $this->loadedClasses[$class];
+ }
+
+ if (!class_exists($class) && !interface_exists($class, false)) {
+ throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class));
+ }
+
+ if (null !== $this->cache && false !== ($metadata = $this->cache->read($class))) {
+ // Include constraints from the parent class
+ $this->mergeConstraints($metadata);
+
+ return $this->loadedClasses[$class] = $metadata;
+ }
+
+ $metadata = new ClassMetadata($class);
+
+ if (null !== $this->loader) {
+ $this->loader->loadClassMetadata($metadata);
+ }
+
+ if (null !== $this->cache) {
+ $this->cache->write($metadata);
+ }
+
+ // Include constraints from the parent class
+ $this->mergeConstraints($metadata);
+
+ return $this->loadedClasses[$class] = $metadata;
+ }
+
+ private function mergeConstraints(ClassMetadata $metadata)
+ {
+ // Include constraints from the parent class
+ if ($parent = $metadata->getReflectionClass()->getParentClass()) {
+ $metadata->mergeConstraints($this->getMetadataFor($parent->name));
+ }
+
+ $interfaces = $metadata->getReflectionClass()->getInterfaces();
+
+ $interfaces = array_filter($interfaces, function ($interface) use ($parent, $interfaces) {
+ $interfaceName = $interface->getName();
+
+ if ($parent && $parent->implementsInterface($interfaceName)) {
+ return false;
+ }
+
+ foreach ($interfaces as $i) {
+ if ($i !== $interface && $i->implementsInterface($interfaceName)) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ // Include constraints from all directly implemented interfaces
+ foreach ($interfaces as $interface) {
+ if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) {
+ continue;
+ }
+ $metadata->mergeConstraints($this->getMetadataFor($interface->name));
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasMetadataFor($value)
+ {
+ if (!\is_object($value) && !\is_string($value)) {
+ return false;
+ }
+
+ $class = ltrim(\is_object($value) ? \get_class($value) : $value, '\\');
+
+ return class_exists($class) || interface_exists($class, false);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Factory/MetadataFactoryInterface.php b/public/system/storage/vendor/symfony/validator/Mapping/Factory/MetadataFactoryInterface.php
new file mode 100644
index 0000000..438ef98
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Factory/MetadataFactoryInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Factory;
+
+use Symfony\Component\Validator\MetadataFactoryInterface as LegacyMetadataFactoryInterface;
+
+/**
+ * Returns {@link \Symfony\Component\Validator\Mapping\MetadataInterface} instances for values.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface MetadataFactoryInterface extends LegacyMetadataFactoryInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/GenericMetadata.php b/public/system/storage/vendor/symfony/validator/Mapping/GenericMetadata.php
new file mode 100644
index 0000000..2e4330f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/GenericMetadata.php
@@ -0,0 +1,237 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\Traverse;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\Exception\BadMethodCallException;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\ValidationVisitorInterface;
+
+/**
+ * A generic container of {@link Constraint} objects.
+ *
+ * This class supports serialization and cloning.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GenericMetadata implements MetadataInterface
+{
+ /**
+ * @var Constraint[]
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getConstraints()} and {@link findConstraints()} instead.
+ */
+ public $constraints = array();
+
+ /**
+ * @var array
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link findConstraints()} instead.
+ */
+ public $constraintsByGroup = array();
+
+ /**
+ * The strategy for cascading objects.
+ *
+ * By default, objects are not cascaded.
+ *
+ * @var int
+ *
+ * @see CascadingStrategy
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getCascadingStrategy()} instead.
+ */
+ public $cascadingStrategy = CascadingStrategy::NONE;
+
+ /**
+ * The strategy for traversing traversable objects.
+ *
+ * By default, traversable objects are not traversed.
+ *
+ * @var int
+ *
+ * @see TraversalStrategy
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getTraversalStrategy()} instead.
+ */
+ public $traversalStrategy = TraversalStrategy::NONE;
+
+ /**
+ * Returns the names of the properties that should be serialized.
+ *
+ * @return string[]
+ */
+ public function __sleep()
+ {
+ return array(
+ 'constraints',
+ 'constraintsByGroup',
+ 'cascadingStrategy',
+ 'traversalStrategy',
+ );
+ }
+
+ /**
+ * Clones this object.
+ */
+ public function __clone()
+ {
+ $constraints = $this->constraints;
+
+ $this->constraints = array();
+ $this->constraintsByGroup = array();
+
+ foreach ($constraints as $constraint) {
+ $this->addConstraint(clone $constraint);
+ }
+ }
+
+ /**
+ * Adds a constraint.
+ *
+ * If the constraint {@link Valid} is added, the cascading strategy will be
+ * changed to {@link CascadingStrategy::CASCADE}. Depending on the
+ * properties $traverse and $deep of that constraint, the traversal strategy
+ * will be set to one of the following:
+ *
+ * - {@link TraversalStrategy::IMPLICIT} if $traverse is enabled and $deep
+ * is enabled
+ * - {@link TraversalStrategy::IMPLICIT} | {@link TraversalStrategy::STOP_RECURSION}
+ * if $traverse is enabled, but $deep is disabled
+ * - {@link TraversalStrategy::NONE} if $traverse is disabled
+ *
+ * @return $this
+ *
+ * @throws ConstraintDefinitionException When trying to add the
+ * {@link Traverse} constraint
+ */
+ public function addConstraint(Constraint $constraint)
+ {
+ if ($constraint instanceof Traverse) {
+ throw new ConstraintDefinitionException(sprintf('The constraint "%s" can only be put on classes. Please use "Symfony\Component\Validator\Constraints\Valid" instead.', \get_class($constraint)));
+ }
+
+ if ($constraint instanceof Valid) {
+ $this->cascadingStrategy = CascadingStrategy::CASCADE;
+
+ if ($constraint->traverse) {
+ // Traverse unless the value is not traversable
+ $this->traversalStrategy = TraversalStrategy::IMPLICIT;
+
+ if (!$constraint->deep) {
+ $this->traversalStrategy |= TraversalStrategy::STOP_RECURSION;
+ }
+ } else {
+ $this->traversalStrategy = TraversalStrategy::NONE;
+ }
+
+ return $this;
+ }
+
+ $this->constraints[] = $constraint;
+
+ foreach ($constraint->groups as $group) {
+ $this->constraintsByGroup[$group][] = $constraint;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds an list of constraints.
+ *
+ * @param Constraint[] $constraints The constraints to add
+ *
+ * @return $this
+ */
+ public function addConstraints(array $constraints)
+ {
+ foreach ($constraints as $constraint) {
+ $this->addConstraint($constraint);
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConstraints()
+ {
+ return $this->constraints;
+ }
+
+ /**
+ * Returns whether this element has any constraints.
+ *
+ * @return bool
+ */
+ public function hasConstraints()
+ {
+ return \count($this->constraints) > 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Aware of the global group (* group).
+ */
+ public function findConstraints($group)
+ {
+ return isset($this->constraintsByGroup[$group])
+ ? $this->constraintsByGroup[$group]
+ : array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCascadingStrategy()
+ {
+ return $this->cascadingStrategy;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTraversalStrategy()
+ {
+ return $this->traversalStrategy;
+ }
+
+ /**
+ * Exists for compatibility with the deprecated
+ * {@link Symfony\Component\Validator\MetadataInterface}.
+ *
+ * Should not be used.
+ *
+ * Implemented for backward compatibility with Symfony < 2.5.
+ *
+ * @throws BadMethodCallException
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath)
+ {
+ throw new BadMethodCallException('Not supported.');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/GetterMetadata.php b/public/system/storage/vendor/symfony/validator/Mapping/GetterMetadata.php
new file mode 100644
index 0000000..5a72bd8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/GetterMetadata.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\Exception\ValidatorException;
+
+/**
+ * Stores all metadata needed for validating a class property via its getter
+ * method.
+ *
+ * A property getter is any method that is equal to the property's name,
+ * prefixed with either "get" or "is". That method will be used to access the
+ * property's value.
+ *
+ * The getter will be invoked by reflection, so the access of private and
+ * protected getters is supported.
+ *
+ * This class supports serialization and cloning.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see PropertyMetadataInterface
+ */
+class GetterMetadata extends MemberMetadata
+{
+ /**
+ * @param string $class The class the getter is defined on
+ * @param string $property The property which the getter returns
+ * @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection)
+ *
+ * @throws ValidatorException
+ */
+ public function __construct($class, $property, $method = null)
+ {
+ if (null === $method) {
+ $getMethod = 'get'.ucfirst($property);
+ $isMethod = 'is'.ucfirst($property);
+ $hasMethod = 'has'.ucfirst($property);
+
+ if (method_exists($class, $getMethod)) {
+ $method = $getMethod;
+ } elseif (method_exists($class, $isMethod)) {
+ $method = $isMethod;
+ } elseif (method_exists($class, $hasMethod)) {
+ $method = $hasMethod;
+ } else {
+ throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod));
+ }
+ } elseif (!method_exists($class, $method)) {
+ throw new ValidatorException(sprintf('The %s() method does not exist in class %s.', $method, $class));
+ }
+
+ parent::__construct($class, $method, $property);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyValue($object)
+ {
+ return $this->newReflectionMember($object)->invoke($object);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function newReflectionMember($objectOrClassName)
+ {
+ return new \ReflectionMethod($objectOrClassName, $this->getName());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/AbstractLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/AbstractLoader.php
new file mode 100644
index 0000000..9d92de3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/AbstractLoader.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\MappingException;
+
+/**
+ * Base loader for validation metadata.
+ *
+ * This loader supports the loading of constraints from Symfony's default
+ * namespace (see {@link DEFAULT_NAMESPACE}) using the short class names of
+ * those constraints. Constraints can also be loaded using their fully
+ * qualified class names. At last, namespace aliases can be defined to load
+ * constraints with the syntax "alias:ShortName".
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class AbstractLoader implements LoaderInterface
+{
+ /**
+ * The namespace to load constraints from by default.
+ */
+ const DEFAULT_NAMESPACE = '\\Symfony\\Component\\Validator\\Constraints\\';
+
+ protected $namespaces = array();
+
+ /**
+ * Adds a namespace alias.
+ *
+ * The namespace alias can be used to reference constraints from specific
+ * namespaces in {@link newConstraint()}:
+ *
+ * $this->addNamespaceAlias('mynamespace', '\\Acme\\Package\\Constraints\\');
+ *
+ * $constraint = $this->newConstraint('mynamespace:NotNull');
+ *
+ * @param string $alias The alias
+ * @param string $namespace The PHP namespace
+ */
+ protected function addNamespaceAlias($alias, $namespace)
+ {
+ $this->namespaces[$alias] = $namespace;
+ }
+
+ /**
+ * Creates a new constraint instance for the given constraint name.
+ *
+ * @param string $name The constraint name. Either a constraint relative
+ * to the default constraint namespace, or a fully
+ * qualified class name. Alternatively, the constraint
+ * may be preceded by a namespace alias and a colon.
+ * The namespace alias must have been defined using
+ * {@link addNamespaceAlias()}.
+ * @param mixed $options The constraint options
+ *
+ * @return Constraint
+ *
+ * @throws MappingException If the namespace prefix is undefined
+ */
+ protected function newConstraint($name, $options = null)
+ {
+ if (false !== strpos($name, '\\') && class_exists($name)) {
+ $className = (string) $name;
+ } elseif (false !== strpos($name, ':')) {
+ list($prefix, $className) = explode(':', $name, 2);
+
+ if (!isset($this->namespaces[$prefix])) {
+ throw new MappingException(sprintf('Undefined namespace prefix "%s"', $prefix));
+ }
+
+ $className = $this->namespaces[$prefix].$className;
+ } else {
+ $className = self::DEFAULT_NAMESPACE.$name;
+ }
+
+ return new $className($options);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/AnnotationLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/AnnotationLoader.php
new file mode 100644
index 0000000..c2d1bdf
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/AnnotationLoader.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Doctrine\Common\Annotations\Reader;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
+use Symfony\Component\Validator\Exception\MappingException;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Loads validation metadata using a Doctrine annotation {@link Reader}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class AnnotationLoader implements LoaderInterface
+{
+ protected $reader;
+
+ public function __construct(Reader $reader)
+ {
+ $this->reader = $reader;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadClassMetadata(ClassMetadata $metadata)
+ {
+ $reflClass = $metadata->getReflectionClass();
+ $className = $reflClass->name;
+ $success = false;
+
+ foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) {
+ if ($constraint instanceof GroupSequence) {
+ $metadata->setGroupSequence($constraint->groups);
+ } elseif ($constraint instanceof GroupSequenceProvider) {
+ $metadata->setGroupSequenceProvider(true);
+ } elseif ($constraint instanceof Constraint) {
+ $metadata->addConstraint($constraint);
+ }
+
+ $success = true;
+ }
+
+ foreach ($reflClass->getProperties() as $property) {
+ if ($property->getDeclaringClass()->name === $className) {
+ foreach ($this->reader->getPropertyAnnotations($property) as $constraint) {
+ if ($constraint instanceof Constraint) {
+ $metadata->addPropertyConstraint($property->name, $constraint);
+ }
+
+ $success = true;
+ }
+ }
+ }
+
+ foreach ($reflClass->getMethods() as $method) {
+ if ($method->getDeclaringClass()->name === $className) {
+ foreach ($this->reader->getMethodAnnotations($method) as $constraint) {
+ if ($constraint instanceof Callback) {
+ $constraint->callback = $method->getName();
+ $constraint->methods = null;
+
+ $metadata->addConstraint($constraint);
+ } elseif ($constraint instanceof Constraint) {
+ if (preg_match('/^(get|is|has)(.+)$/i', $method->name, $matches)) {
+ $metadata->addGetterMethodConstraint(lcfirst($matches[2]), $matches[0], $constraint);
+ } else {
+ throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get", "is" or "has".', $className, $method->name));
+ }
+ }
+
+ $success = true;
+ }
+ }
+ }
+
+ return $success;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/FileLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/FileLoader.php
new file mode 100644
index 0000000..b8f9490
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/FileLoader.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Validator\Exception\MappingException;
+
+/**
+ * Base loader for loading validation metadata from a file.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see YamlFileLoader
+ * @see XmlFileLoader
+ */
+abstract class FileLoader extends AbstractLoader
+{
+ protected $file;
+
+ /**
+ * Creates a new loader.
+ *
+ * @param string $file The mapping file to load
+ *
+ * @throws MappingException If the file does not exist or is not readable
+ */
+ public function __construct($file)
+ {
+ if (!is_file($file)) {
+ throw new MappingException(sprintf('The mapping file "%s" does not exist', $file));
+ }
+
+ if (!is_readable($file)) {
+ throw new MappingException(sprintf('The mapping file "%s" is not readable', $file));
+ }
+
+ if (!stream_is_local($this->file)) {
+ throw new MappingException(sprintf('The mapping file "%s" is not a local file', $file));
+ }
+
+ $this->file = $file;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/FilesLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/FilesLoader.php
new file mode 100644
index 0000000..571c7e7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/FilesLoader.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+/**
+ * Base loader for loading validation metadata from a list of files.
+ *
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see YamlFilesLoader
+ * @see XmlFilesLoader
+ */
+abstract class FilesLoader extends LoaderChain
+{
+ /**
+ * Creates a new loader.
+ *
+ * @param array $paths An array of file paths
+ */
+ public function __construct(array $paths)
+ {
+ parent::__construct($this->getFileLoaders($paths));
+ }
+
+ /**
+ * Returns an array of file loaders for the given file paths.
+ *
+ * @param array $paths An array of file paths
+ *
+ * @return LoaderInterface[] The metadata loaders
+ */
+ protected function getFileLoaders($paths)
+ {
+ $loaders = array();
+
+ foreach ($paths as $path) {
+ $loaders[] = $this->getFileLoaderInstance($path);
+ }
+
+ return $loaders;
+ }
+
+ /**
+ * Creates a loader for the given file path.
+ *
+ * @param string $path The file path
+ *
+ * @return LoaderInterface The created loader
+ */
+ abstract protected function getFileLoaderInstance($path);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderChain.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderChain.php
new file mode 100644
index 0000000..2c5108f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderChain.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Validator\Exception\MappingException;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Loads validation metadata from multiple {@link LoaderInterface} instances.
+ *
+ * Pass the loaders when constructing the chain. Once
+ * {@link loadClassMetadata()} is called, that method will be called on all
+ * loaders in the chain.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class LoaderChain implements LoaderInterface
+{
+ protected $loaders;
+
+ /**
+ * @param LoaderInterface[] $loaders The metadata loaders to use
+ *
+ * @throws MappingException If any of the loaders has an invalid type
+ */
+ public function __construct(array $loaders)
+ {
+ foreach ($loaders as $loader) {
+ if (!$loader instanceof LoaderInterface) {
+ throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', \get_class($loader)));
+ }
+ }
+
+ $this->loaders = $loaders;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadClassMetadata(ClassMetadata $metadata)
+ {
+ $success = false;
+
+ foreach ($this->loaders as $loader) {
+ $success = $loader->loadClassMetadata($metadata) || $success;
+ }
+
+ return $success;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderInterface.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderInterface.php
new file mode 100644
index 0000000..d988309
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/LoaderInterface.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Loads validation metadata into {@link ClassMetadata} instances.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface LoaderInterface
+{
+ /**
+ * Loads validation metadata into a {@link ClassMetadata} instance.
+ *
+ * @return bool Whether the loader succeeded
+ */
+ public function loadClassMetadata(ClassMetadata $metadata);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/StaticMethodLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/StaticMethodLoader.php
new file mode 100644
index 0000000..95fc578
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/StaticMethodLoader.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Validator\Exception\MappingException;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Loads validation metadata by calling a static method on the loaded class.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class StaticMethodLoader implements LoaderInterface
+{
+ protected $methodName;
+
+ /**
+ * Creates a new loader.
+ *
+ * @param string $methodName The name of the static method to call
+ */
+ public function __construct($methodName = 'loadValidatorMetadata')
+ {
+ $this->methodName = $methodName;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadClassMetadata(ClassMetadata $metadata)
+ {
+ /** @var \ReflectionClass $reflClass */
+ $reflClass = $metadata->getReflectionClass();
+
+ if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) {
+ $reflMethod = $reflClass->getMethod($this->methodName);
+
+ if ($reflMethod->isAbstract()) {
+ return false;
+ }
+
+ if (!$reflMethod->isStatic()) {
+ throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName));
+ }
+
+ if ($reflMethod->getDeclaringClass()->name != $reflClass->name) {
+ return false;
+ }
+
+ $reflMethod->invoke(null, $metadata);
+
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFileLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFileLoader.php
new file mode 100644
index 0000000..0c6c19b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFileLoader.php
@@ -0,0 +1,213 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Validator\Exception\MappingException;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+/**
+ * Loads validation metadata from an XML file.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class XmlFileLoader extends FileLoader
+{
+ /**
+ * The XML nodes of the mapping file.
+ *
+ * @var \SimpleXMLElement[]|null
+ */
+ protected $classes;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadClassMetadata(ClassMetadata $metadata)
+ {
+ if (null === $this->classes) {
+ // This method may throw an exception. Do not modify the class'
+ // state before it completes
+ $xml = $this->parseFile($this->file);
+
+ $this->classes = array();
+
+ foreach ($xml->namespace as $namespace) {
+ $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
+ }
+
+ foreach ($xml->class as $class) {
+ $this->classes[(string) $class['name']] = $class;
+ }
+ }
+
+ if (isset($this->classes[$metadata->getClassName()])) {
+ $classDescription = $this->classes[$metadata->getClassName()];
+
+ $this->loadClassMetadataFromXml($metadata, $classDescription);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parses a collection of "constraint" XML nodes.
+ *
+ * @param \SimpleXMLElement $nodes The XML nodes
+ *
+ * @return array The Constraint instances
+ */
+ protected function parseConstraints(\SimpleXMLElement $nodes)
+ {
+ $constraints = array();
+
+ foreach ($nodes as $node) {
+ if (\count($node) > 0) {
+ if (\count($node->value) > 0) {
+ $options = $this->parseValues($node->value);
+ } elseif (\count($node->constraint) > 0) {
+ $options = $this->parseConstraints($node->constraint);
+ } elseif (\count($node->option) > 0) {
+ $options = $this->parseOptions($node->option);
+ } else {
+ $options = array();
+ }
+ } elseif (\strlen((string) $node) > 0) {
+ $options = XmlUtils::phpize(trim($node));
+ } else {
+ $options = null;
+ }
+
+ $constraints[] = $this->newConstraint((string) $node['name'], $options);
+ }
+
+ return $constraints;
+ }
+
+ /**
+ * Parses a collection of "value" XML nodes.
+ *
+ * @param \SimpleXMLElement $nodes The XML nodes
+ *
+ * @return array The values
+ */
+ protected function parseValues(\SimpleXMLElement $nodes)
+ {
+ $values = array();
+
+ foreach ($nodes as $node) {
+ if (\count($node) > 0) {
+ if (\count($node->value) > 0) {
+ $value = $this->parseValues($node->value);
+ } elseif (\count($node->constraint) > 0) {
+ $value = $this->parseConstraints($node->constraint);
+ } else {
+ $value = array();
+ }
+ } else {
+ $value = trim($node);
+ }
+
+ if (isset($node['key'])) {
+ $values[(string) $node['key']] = $value;
+ } else {
+ $values[] = $value;
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * Parses a collection of "option" XML nodes.
+ *
+ * @param \SimpleXMLElement $nodes The XML nodes
+ *
+ * @return array The options
+ */
+ protected function parseOptions(\SimpleXMLElement $nodes)
+ {
+ $options = array();
+
+ foreach ($nodes as $node) {
+ if (\count($node) > 0) {
+ if (\count($node->value) > 0) {
+ $value = $this->parseValues($node->value);
+ } elseif (\count($node->constraint) > 0) {
+ $value = $this->parseConstraints($node->constraint);
+ } else {
+ $value = array();
+ }
+ } else {
+ $value = XmlUtils::phpize($node);
+ if (\is_string($value)) {
+ $value = trim($value);
+ }
+ }
+
+ $options[(string) $node['name']] = $value;
+ }
+
+ return $options;
+ }
+
+ /**
+ * Loads the XML class descriptions from the given file.
+ *
+ * @param string $path The path of the XML file
+ *
+ * @return \SimpleXMLElement The class descriptions
+ *
+ * @throws MappingException If the file could not be loaded
+ */
+ protected function parseFile($path)
+ {
+ try {
+ $dom = XmlUtils::loadFile($path, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd');
+ } catch (\Exception $e) {
+ throw new MappingException($e->getMessage(), $e->getCode(), $e);
+ }
+
+ return simplexml_import_dom($dom);
+ }
+
+ private function loadClassMetadataFromXml(ClassMetadata $metadata, \SimpleXMLElement $classDescription)
+ {
+ if (\count($classDescription->{'group-sequence-provider'}) > 0) {
+ $metadata->setGroupSequenceProvider(true);
+ }
+
+ foreach ($classDescription->{'group-sequence'} as $groupSequence) {
+ if (\count($groupSequence->value) > 0) {
+ $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value));
+ }
+ }
+
+ foreach ($this->parseConstraints($classDescription->constraint) as $constraint) {
+ $metadata->addConstraint($constraint);
+ }
+
+ foreach ($classDescription->property as $property) {
+ foreach ($this->parseConstraints($property->constraint) as $constraint) {
+ $metadata->addPropertyConstraint((string) $property['name'], $constraint);
+ }
+ }
+
+ foreach ($classDescription->getter as $getter) {
+ foreach ($this->parseConstraints($getter->constraint) as $constraint) {
+ $metadata->addGetterConstraint((string) $getter['property'], $constraint);
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFilesLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFilesLoader.php
new file mode 100644
index 0000000..6017c3f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/XmlFilesLoader.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+/**
+ * Loads validation metadata from a list of XML files.
+ *
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see FilesLoader
+ */
+class XmlFilesLoader extends FilesLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getFileLoaderInstance($file)
+ {
+ return new XmlFileLoader($file);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFileLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFileLoader.php
new file mode 100644
index 0000000..d1ec7f0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFileLoader.php
@@ -0,0 +1,178 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Parser as YamlParser;
+
+/**
+ * Loads validation metadata from a YAML file.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class YamlFileLoader extends FileLoader
+{
+ /**
+ * An array of YAML class descriptions.
+ *
+ * @var array
+ */
+ protected $classes = null;
+
+ /**
+ * Caches the used YAML parser.
+ *
+ * @var YamlParser
+ */
+ private $yamlParser;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadClassMetadata(ClassMetadata $metadata)
+ {
+ if (null === $this->classes) {
+ if (null === $this->yamlParser) {
+ $this->yamlParser = new YamlParser();
+ }
+
+ $this->classes = $this->parseFile($this->file);
+
+ if (isset($this->classes['namespaces'])) {
+ foreach ($this->classes['namespaces'] as $alias => $namespace) {
+ $this->addNamespaceAlias($alias, $namespace);
+ }
+
+ unset($this->classes['namespaces']);
+ }
+ }
+
+ if (isset($this->classes[$metadata->getClassName()])) {
+ $classDescription = $this->classes[$metadata->getClassName()];
+
+ $this->loadClassMetadataFromYaml($metadata, $classDescription);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parses a collection of YAML nodes.
+ *
+ * @param array $nodes The YAML nodes
+ *
+ * @return array An array of values or Constraint instances
+ */
+ protected function parseNodes(array $nodes)
+ {
+ $values = array();
+
+ foreach ($nodes as $name => $childNodes) {
+ if (is_numeric($name) && \is_array($childNodes) && 1 === \count($childNodes)) {
+ $options = current($childNodes);
+
+ if (\is_array($options)) {
+ $options = $this->parseNodes($options);
+ }
+
+ $values[] = $this->newConstraint(key($childNodes), $options);
+ } else {
+ if (\is_array($childNodes)) {
+ $childNodes = $this->parseNodes($childNodes);
+ }
+
+ $values[$name] = $childNodes;
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * Loads the YAML class descriptions from the given file.
+ *
+ * @param string $path The path of the YAML file
+ *
+ * @return array The class descriptions
+ *
+ * @throws \InvalidArgumentException If the file could not be loaded or did
+ * not contain a YAML array
+ */
+ private function parseFile($path)
+ {
+ try {
+ $classes = $this->yamlParser->parse(file_get_contents($path));
+ } catch (ParseException $e) {
+ throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
+ }
+
+ // empty file
+ if (null === $classes) {
+ return array();
+ }
+
+ // not an array
+ if (!\is_array($classes)) {
+ throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file));
+ }
+
+ return $classes;
+ }
+
+ /**
+ * Loads the validation metadata from the given YAML class description.
+ *
+ * @param ClassMetadata $metadata The metadata to load
+ * @param array $classDescription The YAML class description
+ */
+ private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $classDescription)
+ {
+ if (isset($classDescription['group_sequence_provider'])) {
+ $metadata->setGroupSequenceProvider(
+ (bool) $classDescription['group_sequence_provider']
+ );
+ }
+
+ if (isset($classDescription['group_sequence'])) {
+ $metadata->setGroupSequence($classDescription['group_sequence']);
+ }
+
+ if (isset($classDescription['constraints']) && \is_array($classDescription['constraints'])) {
+ foreach ($this->parseNodes($classDescription['constraints']) as $constraint) {
+ $metadata->addConstraint($constraint);
+ }
+ }
+
+ if (isset($classDescription['properties']) && \is_array($classDescription['properties'])) {
+ foreach ($classDescription['properties'] as $property => $constraints) {
+ if (null !== $constraints) {
+ foreach ($this->parseNodes($constraints) as $constraint) {
+ $metadata->addPropertyConstraint($property, $constraint);
+ }
+ }
+ }
+ }
+
+ if (isset($classDescription['getters']) && \is_array($classDescription['getters'])) {
+ foreach ($classDescription['getters'] as $getter => $constraints) {
+ if (null !== $constraints) {
+ foreach ($this->parseNodes($constraints) as $constraint) {
+ $metadata->addGetterConstraint($getter, $constraint);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFilesLoader.php b/public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFilesLoader.php
new file mode 100644
index 0000000..235856f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/YamlFilesLoader.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping\Loader;
+
+/**
+ * Loads validation metadata from a list of YAML files.
+ *
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see FilesLoader
+ */
+class YamlFilesLoader extends FilesLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getFileLoaderInstance($file)
+ {
+ return new YamlFileLoader($file);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd b/public/system/storage/vendor/symfony/validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd
new file mode 100644
index 0000000..1ca840b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd
@@ -0,0 +1,160 @@
+<?xml version="1.0" ?>
+
+<xsd:schema xmlns="http://symfony.com/schema/dic/constraint-mapping"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://symfony.com/schema/dic/constraint-mapping"
+ elementFormDefault="qualified">
+
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Symfony Validator Constraint Mapping Schema, version 1.0
+ Authors: Bernhard Schussek
+
+ A constraint mapping connects classes, properties and getters with
+ validation constraints.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="constraint-mapping" type="constraint-mapping" />
+
+ <xsd:complexType name="constraint-mapping">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The root element of the constraint mapping definition.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="namespace" type="namespace" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="class" type="class" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="namespace">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains the abbreviation for a namespace.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="prefix" type="xsd:string" use="required" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="class">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains constraints for a single class.
+
+ Nested elements may be class constraints, property and/or getter
+ definitions.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="group-sequence-provider" type="group-sequence-provider" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="group-sequence" type="group-sequence" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="constraint" type="constraint" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:choice>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <xsd:complexType name="group-sequence">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains the group sequence of a class. Each group should be written
+ into a "value" tag.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="group-sequence-provider">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Defines the name of the group sequence provider for a class.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:complexType>
+
+ <xsd:complexType name="property">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains constraints for a single property. The name of the property
+ should be given in the "name" option.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <xsd:complexType name="getter">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains constraints for a getter method. The name of the corresponding
+ property should be given in the "property" option.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="property" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <xsd:complexType name="constraint" mixed="true">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains a constraint definition. The name of the constraint should be
+ given in the "name" option.
+
+ May contain a single value, multiple "constraint" elements,
+ multiple "value" elements or multiple "option" elements.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0">
+ <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
+ <xsd:element name="option" type="option" minOccurs="1" maxOccurs="unbounded" />
+ <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
+ </xsd:choice>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <xsd:complexType name="option" mixed="true">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Contains a constraint option definition. The name of the option
+ should be given in the "name" option.
+
+ May contain a single value, multiple "value" elements or multiple
+ "constraint" elements.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0">
+ <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
+ <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
+ </xsd:choice>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <xsd:complexType name="value" mixed="true">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A value of an element.
+
+ May contain a single value, multiple "value" elements or multiple
+ "constraint" elements.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0">
+ <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
+ <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
+ </xsd:choice>
+ <xsd:attribute name="key" type="xsd:string" use="optional" />
+ </xsd:complexType>
+</xsd:schema>
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/MemberMetadata.php b/public/system/storage/vendor/symfony/validator/Mapping/MemberMetadata.php
new file mode 100644
index 0000000..565f2f4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/MemberMetadata.php
@@ -0,0 +1,248 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\ValidationVisitorInterface;
+
+/**
+ * Stores all metadata needed for validating a class property.
+ *
+ * The method of accessing the property's value must be specified by subclasses
+ * by implementing the {@link newReflectionMember()} method.
+ *
+ * This class supports serialization and cloning.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see PropertyMetadataInterface
+ */
+abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface
+{
+ /**
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getClassName()} instead.
+ */
+ public $class;
+
+ /**
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getName()} instead.
+ */
+ public $name;
+
+ /**
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getPropertyName()} instead.
+ */
+ public $property;
+
+ /**
+ * @var \ReflectionMethod[]|\ReflectionProperty[]
+ */
+ private $reflMember = array();
+
+ /**
+ * @param string $class The name of the class this member is defined on
+ * @param string $name The name of the member
+ * @param string $property The property the member belongs to
+ */
+ public function __construct($class, $name, $property)
+ {
+ $this->class = $class;
+ $this->name = $name;
+ $this->property = $property;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+ $visitor->visit($this, $value, $group, $propertyPath);
+
+ if ($this->isCascaded()) {
+ $visitor->validate($value, $propagatedGroup ?: $group, $propertyPath, $this->isCollectionCascaded(), $this->isCollectionCascadedDeeply());
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addConstraint(Constraint $constraint)
+ {
+ if (!\in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) {
+ throw new ConstraintDefinitionException(sprintf('The constraint %s cannot be put on properties or getters', \get_class($constraint)));
+ }
+
+ parent::addConstraint($constraint);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __sleep()
+ {
+ return array_merge(parent::__sleep(), array(
+ 'class',
+ 'name',
+ 'property',
+ ));
+ }
+
+ /**
+ * Returns the name of the member.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getClassName()
+ {
+ return $this->class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyName()
+ {
+ return $this->property;
+ }
+
+ /**
+ * Returns whether this member is public.
+ *
+ * @param object|string $objectOrClassName The object or the class name
+ *
+ * @return bool
+ */
+ public function isPublic($objectOrClassName)
+ {
+ return $this->getReflectionMember($objectOrClassName)->isPublic();
+ }
+
+ /**
+ * Returns whether this member is protected.
+ *
+ * @param object|string $objectOrClassName The object or the class name
+ *
+ * @return bool
+ */
+ public function isProtected($objectOrClassName)
+ {
+ return $this->getReflectionMember($objectOrClassName)->isProtected();
+ }
+
+ /**
+ * Returns whether this member is private.
+ *
+ * @param object|string $objectOrClassName The object or the class name
+ *
+ * @return bool
+ */
+ public function isPrivate($objectOrClassName)
+ {
+ return $this->getReflectionMember($objectOrClassName)->isPrivate();
+ }
+
+ /**
+ * Returns whether objects stored in this member should be validated.
+ *
+ * @return bool
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link getCascadingStrategy()} instead.
+ */
+ public function isCascaded()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the getCascadingStrategy() method instead.', E_USER_DEPRECATED);
+
+ return (bool) ($this->cascadingStrategy & CascadingStrategy::CASCADE);
+ }
+
+ /**
+ * Returns whether arrays or traversable objects stored in this member
+ * should be traversed and validated in each entry.
+ *
+ * @return bool
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link getTraversalStrategy()} instead.
+ */
+ public function isCollectionCascaded()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the getTraversalStrategy() method instead.', E_USER_DEPRECATED);
+
+ return (bool) ($this->traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE));
+ }
+
+ /**
+ * Returns whether arrays or traversable objects stored in this member
+ * should be traversed recursively for inner arrays/traversable objects.
+ *
+ * @return bool
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link getTraversalStrategy()} instead.
+ */
+ public function isCollectionCascadedDeeply()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the getTraversalStrategy() method instead.', E_USER_DEPRECATED);
+
+ return !($this->traversalStrategy & TraversalStrategy::STOP_RECURSION);
+ }
+
+ /**
+ * Returns the reflection instance for accessing the member's value.
+ *
+ * @param object|string $objectOrClassName The object or the class name
+ *
+ * @return \ReflectionMethod|\ReflectionProperty The reflection instance
+ */
+ public function getReflectionMember($objectOrClassName)
+ {
+ $className = \is_string($objectOrClassName) ? $objectOrClassName : \get_class($objectOrClassName);
+ if (!isset($this->reflMember[$className])) {
+ $this->reflMember[$className] = $this->newReflectionMember($objectOrClassName);
+ }
+
+ return $this->reflMember[$className];
+ }
+
+ /**
+ * Creates a new reflection instance for accessing the member's value.
+ *
+ * Must be implemented by subclasses.
+ *
+ * @param object|string $objectOrClassName The object or the class name
+ *
+ * @return \ReflectionMethod|\ReflectionProperty The reflection instance
+ */
+ abstract protected function newReflectionMember($objectOrClassName);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/MetadataInterface.php b/public/system/storage/vendor/symfony/validator/Mapping/MetadataInterface.php
new file mode 100644
index 0000000..1e9d3c8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/MetadataInterface.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\MetadataInterface as LegacyMetadataInterface;
+
+/**
+ * A container for validation metadata.
+ *
+ * Most importantly, the metadata stores the constraints against which an object
+ * and its properties should be validated.
+ *
+ * Additionally, the metadata stores whether objects should be validated
+ * against their class' metadata and whether traversable objects should be
+ * traversed or not.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see CascadingStrategy
+ * @see TraversalStrategy
+ */
+interface MetadataInterface extends LegacyMetadataInterface
+{
+ /**
+ * Returns the strategy for cascading objects.
+ *
+ * @return int The cascading strategy
+ *
+ * @see CascadingStrategy
+ */
+ public function getCascadingStrategy();
+
+ /**
+ * Returns the strategy for traversing traversable objects.
+ *
+ * @return int The traversal strategy
+ *
+ * @see TraversalStrategy
+ */
+ public function getTraversalStrategy();
+
+ /**
+ * Returns all constraints of this element.
+ *
+ * @return Constraint[] A list of Constraint instances
+ */
+ public function getConstraints();
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadata.php b/public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadata.php
new file mode 100644
index 0000000..b03a059
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadata.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\Exception\ValidatorException;
+
+/**
+ * Stores all metadata needed for validating a class property.
+ *
+ * The value of the property is obtained by directly accessing the property.
+ * The property will be accessed by reflection, so the access of private and
+ * protected properties is supported.
+ *
+ * This class supports serialization and cloning.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see PropertyMetadataInterface
+ */
+class PropertyMetadata extends MemberMetadata
+{
+ /**
+ * @param string $class The class this property is defined on
+ * @param string $name The name of this property
+ *
+ * @throws ValidatorException
+ */
+ public function __construct($class, $name)
+ {
+ if (!property_exists($class, $name)) {
+ throw new ValidatorException(sprintf('Property "%s" does not exist in class "%s"', $name, $class));
+ }
+
+ parent::__construct($class, $name, $name);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPropertyValue($object)
+ {
+ return $this->getReflectionMember($object)->getValue($object);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function newReflectionMember($objectOrClassName)
+ {
+ $originalClass = \is_string($objectOrClassName) ? $objectOrClassName : \get_class($objectOrClassName);
+
+ while (!property_exists($objectOrClassName, $this->getName())) {
+ $objectOrClassName = get_parent_class($objectOrClassName);
+
+ if (false === $objectOrClassName) {
+ throw new ValidatorException(sprintf('Property "%s" does not exist in class "%s".', $this->getName(), $originalClass));
+ }
+ }
+
+ $member = new \ReflectionProperty($objectOrClassName, $this->getName());
+ $member->setAccessible(true);
+
+ return $member;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadataInterface.php b/public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadataInterface.php
new file mode 100644
index 0000000..d7a4114
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/PropertyMetadataInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+use Symfony\Component\Validator\ClassBasedInterface;
+use Symfony\Component\Validator\PropertyMetadataInterface as LegacyPropertyMetadataInterface;
+
+/**
+ * Stores all metadata needed for validating the value of a class property.
+ *
+ * Most importantly, the metadata stores the constraints against which the
+ * property's value should be validated.
+ *
+ * Additionally, the metadata stores whether objects stored in the property
+ * should be validated against their class' metadata and whether traversable
+ * objects should be traversed or not.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see MetadataInterface
+ * @see CascadingStrategy
+ * @see TraversalStrategy
+ */
+interface PropertyMetadataInterface extends MetadataInterface, LegacyPropertyMetadataInterface, ClassBasedInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Mapping/TraversalStrategy.php b/public/system/storage/vendor/symfony/validator/Mapping/TraversalStrategy.php
new file mode 100644
index 0000000..164992b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Mapping/TraversalStrategy.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Mapping;
+
+/**
+ * Specifies whether and how a traversable object should be traversed.
+ *
+ * If the node traverser traverses a node whose value is an instance of
+ * {@link \Traversable}, and if that node is either a class node or if
+ * cascading is enabled, then the node's traversal strategy will be checked.
+ * Depending on the requested traversal strategy, the node traverser will
+ * iterate over the object and cascade each object or collection returned by
+ * the iterator.
+ *
+ * The traversal strategy is ignored for arrays. Arrays are always iterated.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see CascadingStrategy
+ */
+class TraversalStrategy
+{
+ /**
+ * Specifies that a node's value should be iterated only if it is an
+ * instance of {@link \Traversable}.
+ */
+ const IMPLICIT = 1;
+
+ /**
+ * Specifies that a node's value should never be iterated.
+ */
+ const NONE = 2;
+
+ /**
+ * Specifies that a node's value should always be iterated. If the value is
+ * not an instance of {@link \Traversable}, an exception should be thrown.
+ */
+ const TRAVERSE = 4;
+
+ /**
+ * Specifies that nested instances of {@link \Traversable} should never be
+ * iterated. Can be combined with {@link IMPLICIT} or {@link TRAVERSE}.
+ *
+ * @deprecated since version 2.5, to be removed in 3.0. This constant was added for backwards compatibility only.
+ *
+ * @internal
+ */
+ const STOP_RECURSION = 8;
+
+ /**
+ * Not instantiable.
+ */
+ private function __construct()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/MetadataFactoryInterface.php b/public/system/storage/vendor/symfony/validator/MetadataFactoryInterface.php
new file mode 100644
index 0000000..555bea9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/MetadataFactoryInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Returns {@link MetadataInterface} instances for values.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Mapping\Factory\MetadataFactoryInterface} instead.
+ */
+interface MetadataFactoryInterface
+{
+ /**
+ * Returns the metadata for the given value.
+ *
+ * @param mixed $value Some value
+ *
+ * @return MetadataInterface The metadata for the value
+ *
+ * @throws Exception\NoSuchMetadataException If no metadata exists for the given value
+ */
+ public function getMetadataFor($value);
+
+ /**
+ * Returns whether the class is able to return metadata for the given value.
+ *
+ * @param mixed $value Some value
+ *
+ * @return bool Whether metadata can be returned for that value
+ */
+ public function hasMetadataFor($value);
+}
diff --git a/public/system/storage/vendor/symfony/validator/MetadataInterface.php b/public/system/storage/vendor/symfony/validator/MetadataInterface.php
new file mode 100644
index 0000000..2c89449
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/MetadataInterface.php
@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * A container for validation metadata.
+ *
+ * The container contains constraints that may belong to different validation
+ * groups. Constraints for a specific group can be fetched by calling
+ * {@link findConstraints}.
+ *
+ * Implement this interface to add validation metadata to your own metadata
+ * layer. Each metadata may have named properties. Each property can be
+ * represented by one or more {@link PropertyMetadataInterface} instances that
+ * are returned by {@link getPropertyMetadata}. Since
+ * <tt>PropertyMetadataInterface</tt> inherits from <tt>MetadataInterface</tt>,
+ * each property may be divided into further properties.
+ *
+ * The {@link accept} method of each metadata implements the Visitor pattern.
+ * The method should forward the call to the visitor's
+ * {@link ValidationVisitorInterface::visit} method and additionally call
+ * <tt>accept()</tt> on all structurally related metadata instances.
+ *
+ * For example, to store constraints for PHP classes and their properties,
+ * create a class <tt>ClassMetadata</tt> (implementing <tt>MetadataInterface</tt>)
+ * and a class <tt>PropertyMetadata</tt> (implementing <tt>PropertyMetadataInterface</tt>).
+ * <tt>ClassMetadata::getPropertyMetadata($property)</tt> returns all
+ * <tt>PropertyMetadata</tt> instances for a property of that class. Its
+ * <tt>accept()</tt>-method simply forwards to <tt>ValidationVisitorInterface::visit()</tt>
+ * and calls <tt>accept()</tt> on all contained <tt>PropertyMetadata</tt>
+ * instances, which themselves call <tt>ValidationVisitorInterface::visit()</tt>
+ * again.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Mapping\MetadataInterface} instead.
+ */
+interface MetadataInterface
+{
+ /**
+ * Implementation of the Visitor design pattern.
+ *
+ * Calls {@link ValidationVisitorInterface::visit} and then forwards the
+ * <tt>accept()</tt>-call to all property metadata instances.
+ *
+ * @param ValidationVisitorInterface $visitor The visitor implementing the validation logic
+ * @param mixed $value The value to validate
+ * @param string|string[] $group The validation group to validate in
+ * @param string $propertyPath The current property path in the validation graph
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath);
+
+ /**
+ * Returns all constraints for a given validation group.
+ *
+ * @param string $group The validation group
+ *
+ * @return Constraint[] A list of constraint instances
+ */
+ public function findConstraints($group);
+}
diff --git a/public/system/storage/vendor/symfony/validator/ObjectInitializerInterface.php b/public/system/storage/vendor/symfony/validator/ObjectInitializerInterface.php
new file mode 100644
index 0000000..5f9cdad
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ObjectInitializerInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Prepares an object for validation.
+ *
+ * Concrete implementations of this interface are used by {@link ValidationVisitorInterface}
+ * and {@link Validator\ContextualValidatorInterface} to initialize objects just before validating them.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ObjectInitializerInterface
+{
+ /**
+ * Initializes an object just before validation.
+ *
+ * @param object $object The object to validate
+ */
+ public function initialize($object);
+}
diff --git a/public/system/storage/vendor/symfony/validator/PropertyMetadataContainerInterface.php b/public/system/storage/vendor/symfony/validator/PropertyMetadataContainerInterface.php
new file mode 100644
index 0000000..b5c9cf4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/PropertyMetadataContainerInterface.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * A container for {@link PropertyMetadataInterface} instances.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Mapping\ClassMetadataInterface} instead.
+ */
+interface PropertyMetadataContainerInterface
+{
+ /**
+ * Check if there's any metadata attached to the given named property.
+ *
+ * @param string $property The property name
+ *
+ * @return bool
+ */
+ public function hasPropertyMetadata($property);
+
+ /**
+ * Returns all metadata instances for the given named property.
+ *
+ * If your implementation does not support properties, simply throw an
+ * exception in this method (for example a <tt>BadMethodCallException</tt>).
+ *
+ * @param string $property The property name
+ *
+ * @return PropertyMetadataInterface[] A list of metadata instances. Empty if
+ * no metadata exists for the property.
+ */
+ public function getPropertyMetadata($property);
+}
diff --git a/public/system/storage/vendor/symfony/validator/PropertyMetadataInterface.php b/public/system/storage/vendor/symfony/validator/PropertyMetadataInterface.php
new file mode 100644
index 0000000..64ae881
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/PropertyMetadataInterface.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * A container for validation metadata of a property.
+ *
+ * What exactly you define as "property" is up to you. The validator expects
+ * implementations of {@link MetadataInterface} that contain constraints and
+ * optionally a list of named properties that also have constraints (and may
+ * have further sub properties). Such properties are mapped by implementations
+ * of this interface.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see MetadataInterface
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Mapping\PropertyMetadataInterface} instead.
+ */
+interface PropertyMetadataInterface extends MetadataInterface
+{
+ /**
+ * Returns the name of the property.
+ *
+ * @return string The property name
+ */
+ public function getPropertyName();
+
+ /**
+ * Extracts the value of the property from the given container.
+ *
+ * @param mixed $containingValue The container to extract the property value from
+ *
+ * @return mixed The value of the property
+ */
+ public function getPropertyValue($containingValue);
+}
diff --git a/public/system/storage/vendor/symfony/validator/README.md b/public/system/storage/vendor/symfony/validator/README.md
new file mode 100644
index 0000000..3ccb290
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/README.md
@@ -0,0 +1,16 @@
+Validator Component
+===================
+
+The Validator component provides tools to validate values following the
+[JSR-303 Bean Validation specification][1].
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/validator.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
+
+[1]: http://jcp.org/en/jsr/detail?id=303
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.af.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.af.xlf
new file mode 100644
index 0000000..177bb00
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.af.xlf
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Hierdie waarde moet vals wees.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Hierdie waarde moet waar wees.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Hierdie waarde moet van die soort {{type}} wees.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Hierdie waarde moet leeg wees.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Die waarde wat jy gekies het is nie 'n geldige keuse nie.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Jy moet ten minste {{ limit }} kies.|Jy moet ten minste {{ limit }} keuses kies.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Jy moet by die meeste {{ limit }} keuse kies.|Jy moet by die meeste {{ limit }} keuses kies.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Een of meer van die gegewe waardes is ongeldig.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Die veld is nie verwag nie.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Hierdie veld ontbreek.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Hierdie waarde is nie 'n geldige datum nie.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Hierdie waarde is nie 'n geldige datum en tyd nie.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Hierdie waarde is nie 'n geldige e-pos adres nie.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Die lêer kon nie gevind word nie.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Die lêer kan nie gelees word nie.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Die lêer is te groot ({{ size }} {{ suffix }}). Toegelaat maksimum grootte is {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Die MIME-tipe van die lêer is ongeldig ({{ type }}). Toegelaat MIME-tipes is {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Hierdie waarde moet {{ limit }} of minder wees.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Hierdie waarde is te lank. Dit moet {{ limit }} karakter of minder wees.|Hierdie waarde is te lank. Dit moet {{ limit }} karakters of minder wees.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Hierdie waarde moet {{ limit }} of meer wees.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Hierdie waarde is te kort. Dit moet {{ limit }} karakter of meer wees.|Hierdie waarde is te kort. Dit moet {{ limit }} karakters of meer wees.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Hierdie waarde moet nie leeg wees nie.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Hierdie waarde moet nie nul wees nie.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Hierdie waarde moet nul wees.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Hierdie waarde is nie geldig nie.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Hierdie waarde is nie 'n geldige tyd nie.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Hierdie waarde is nie 'n geldige URL nie.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Die twee waardes moet gelyk wees.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Die lêer is te groot. Toegelaat maksimum grootte is {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Die lêer is te groot.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Die lêer kan nie opgelaai word nie.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Hierdie waarde moet 'n geldige nommer wees.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Hierdie lêer is nie 'n geldige beeld nie.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Hierdie is nie 'n geldige IP-adres nie.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Hierdie waarde is nie 'n geldige taal nie.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Hierdie waarde is nie 'n geldige land instelling nie.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Hierdie waarde is nie 'n geldige land nie.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Hierdie waarde word reeds gebruik.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Die grootte van die beeld kon nie opgespoor word nie.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Die beeld breedte is te groot ({{ width }}px). Toegelaat maksimum breedte is {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Die beeld breedte is te klein ({{ width }}px). Minimum breedte verwag is {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Die beeld hoogte is te groot ({{ height }}px). Toegelaat maksimum hoogte is {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Die beeld hoogte is te klein ({{ height }}px). Minimum hoogte verwag is {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Hierdie waarde moet die huidige wagwoord van die gebruiker wees.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Hierdie waarde moet presies {{ limit }} karakter wees.|Hierdie waarde moet presies {{ limit }} karakters wees.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Die lêer is slegs gedeeltelik opgelaai.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Geen lêer is opgelaai nie.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Geen tydelike lêer is ingestel in php.ini nie.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan nie tydelike lêer skryf op skyf nie.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>'n PHP-uitbreiding veroorsaak die oplaai van die lêer om te misluk.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Hierdie versameling moet {{ limit }} element of meer bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Hierdie versameling moet {{ limit }} element of minder bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Hierdie versameling moet presies {{ limit }} element bevat.|Hierdie versameling moet presies {{ limit }} elemente bevat.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ongeldige kredietkaart nommer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ar.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ar.xlf
new file mode 100644
index 0000000..4950e0c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ar.xlf
@@ -0,0 +1,315 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>هذه القيمة يجب أن تكون خاطئة.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>هذه القيمة يجب أن تكون حقيقية.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>هذه القيمة يجب ان تكون من نوع {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>هذه القيمة يجب ان تكون فارغة.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>القيمة المختارة ليست خيارا صحيحا.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيارات على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيارات على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>واحد أو أكثر من القيم المعطاه خاطئ.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>لم يكن من المتوقع هذا المجال.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>هذا المجال مفقود.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>هذه القيمة ليست تاريخا صالحا.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>هذه القيمة ليست تاريخا و وقتا صالحا.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>هذه القيمة ليست عنوان بريد إلكتروني صحيح.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>لا يمكن العثور على الملف.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>الملف غير قابل للقراءة.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>الملف كبير جدا ({{ size }} {{ suffix }}).اقصى مساحه مسموح بها ({{ limit }} {{ suffix }}).</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>نوع الملف غير صحيح ({{ type }}). الانواع المسموح بها هى {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>هذه القيمة يجب ان تكون {{ limit }} او اقل.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حروف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>هذه القيمة يجب ان تكون {{ limit }} او اكثر.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حروف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>هذه القيمة يجب الا تكون فارغة.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>هذه القيمة يجب الا تكون فارغة.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>هذه القيمة يجب ان تكون فارغة.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>هذه القيمة غير صحيحة.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>هذه القيمة ليست وقت صحيح.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>هذه القيمة ليست رابط الكترونى صحيح.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>القيمتان يجب ان تكونا متساويتان.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>الملف كبير جدا. اقصى مساحه مسموح بها {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>الملف كبير جدا.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>لم استطع استقبال الملف.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>هذه القيمة يجب ان تكون رقم.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>هذا الملف ليس صورة صحيحة.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>هذه القيمة ليست عنوان رقمى صحيح.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>هذه القيمة ليست لغة صحيحة.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>هذه القيمة ليست موقع صحيح.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>هذه القيمة ليست بلدا صالحا.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>هذه القيمة مستخدمة بالفعل.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>لم استطع معرفة حجم الصورة.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>عرض الصورة كبير جدا ({{ width }}px). اقصى عرض مسموح به هو{{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>عرض الصورة صغير جدا ({{ width }}px). اقل عرض مسموح به هو{{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>طول الصورة كبير جدا ({{ height }}px). اقصى طول مسموح به هو{{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>طول الصورة صغير جدا ({{ height }}px). اقل طول مسموح به هو{{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>هذه القيمة يجب ان تكون كلمة سر المستخدم الحالية.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حروف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>تم استقبال جزء من الملف فقط.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>لم يتم ارسال اى ملف.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>لم يتم تهيئة حافظة مؤقتة فى ملف php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>لم استطع كتابة الملف المؤقت.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>احد اضافات PHP تسببت فى فشل استقبال الملف.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>رقم البطاقه غير صحيح.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>نوع البطاقه غير مدعوم او الرقم غير صحيح.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>الرقم IBAN (رقم الحساب المصرفي الدولي) الذي تم إدخاله غير صالح.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>هذه القيمة ليست ISBN-10 صالحة.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>هذه القيمة ليست ISBN-13 صالحة.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>هذه القيمة ليست ISBN-10 صالحة ولا ISBN-13 صالحة.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>هذه القيمة ليست ISSN صالحة.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>العُملة غير صحيحة.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>القيمة يجب ان تساوي {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>القيمة يجب ان تكون اعلي من {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>القيمة يجب ان تكون مساوية او اعلي من {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>القيمة يجب ان تطابق {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>القيمة يجب ان تكون اقل من {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>القيمة يجب ان تساوي او تقل عن {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>القيمة يجب ان لا تساوي {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>القيمة يجب ان لا تطابق {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>نسبة العرض على الارتفاع للصورة كبيرة جدا ({{ ratio }}). الحد الأقصى للنسبة المسموح به هو {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>نسبة العرض على الارتفاع للصورة صغيرة جدا ({{ ratio }}). الحد الأدنى للنسبة المسموح به هو {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>الصورة مربعة ({{ width }}x{{ height }}px). الصور المربعة غير مسموح بها.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>الصورة في وضع أفقي ({{ width }}x{{ height }}px). الصور في وضع أفقي غير مسموح بها.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>الصورة في وضع عمودي ({{ width }}x{{ height }}px). الصور في وضع عمودي غير مسموح بها.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>ملف فارغ غير مسموح به.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>يتعذر الإتصال بالنطاق.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>هذه القيمة غير متطابقة مع صيغة التحويل {{ charset }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.az.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.az.xlf
new file mode 100644
index 0000000..add868c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.az.xlf
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Bu dəyər false olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Bu dəyər true olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Bu dəyərin tipi {{ type }} olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Bu dəyər boş olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Seçdiyiniz dəyər düzgün bir seçim değil.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Ən az {{ limit }} seçim qeyd edilməlidir.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Ən çox {{ limit }} seçim qeyd edilməlidir.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Təqdim edilən dəyərlərdən bir və ya bir neçəsi yanlışdır.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Bu sahə gözlənilmirdi.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Bu sahə əksikdir.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Bu dəyər düzgün bir tarix deyil.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Bu dəyər düzgün bir tarixsaat deyil.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Bu dəyər düzgün bir e-poçt adresi deyil.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Fayl tapılmadı.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Fayl oxunabilən deyil.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fayl çox böyükdür ({{ size }} {{ suffix }}). İcazə verilən maksimum fayl ölçüsü {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Faylın mime tipi yanlışdr ({{ type }}). İcazə verilən mime tipləri {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Bu dəyər {{ limit }} və ya altında olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Bu dəyər çox uzundur. {{ limit }} və ya daha az simvol olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Bu dəyər {{ limit }} veya daha fazla olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Bu dəyər çox qısadır. {{ limit }} və ya daha çox simvol olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Bu dəyər boş olmamalıdır.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Bu dəyər boş olmamalıdır.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Bu dəyər boş olmamalıdır.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Bu dəyər doğru deyil.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Bu dəyər doğru bir saat deyil.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Bu dəyər doğru bir URL değil.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>İki dəyər eyni olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fayl çox böyükdür. İcazə verilən ən böyük fayl ölçüsü {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Fayl çox böyükdür.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Fayl yüklənəbilmir.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Bu dəyər rəqəm olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Bu fayl düzgün bir şəkil deyil.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Bu düzgün bir IP adresi deyil.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Bu dəyər düzgün bir dil deyil.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Bu dəyər düzgün bir dil deyil.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Bu dəyər düzgün bir ölkə deyil.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Bu dəyər hal-hazırda istifadədədir.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Şəklin ölçüsü hesablana bilmir.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Şəklin genişliyi çox böyükdür ({{ width }}px). İcazə verilən ən böyük genişlik {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Şəklin genişliyi çox kiçikdir ({{ width }}px). Ən az {{ min_width }}px olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Şəklin yüksəkliyi çox böyükdür ({{ height }}px). İcazə verilən ən böyük yüksəklik {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Şəklin yüksəkliyi çox kiçikdir ({{ height }}px). Ən az {{ min_height }}px olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Bu dəyər istifadəçinin hazırkı parolu olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Bu dəyər tam olaraq {{ limit }} simvol olmaldır.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Fayl qismən yükləndi.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Fayl yüklənmədi.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>php.ini'də müvəqqəti qovluq quraşdırılmayıb.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Müvəqqəti fayl diskə yazıla bilmir.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Bir PHP əlavəsi faylın yüklənməsinə mane oldu.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Bu kolleksiyada {{ limit }} və ya daha çox element olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Bu kolleksiyada {{ limit }} və ya daha az element olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Bu kolleksiyada tam olaraq {{ limit }} element olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Yanlış kart nömrəsi.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Dəstəklənməyən kart tipi və ya yanlış kart nömrəsi.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.bg.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.bg.xlf
new file mode 100644
index 0000000..dc6f95f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.bg.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Стойността трябва да бъде лъжа (false).</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Стойността трябва да бъде истина (true).</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Стойността трябва да бъде от тип {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Стойността трябва да бъде празна.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Избраната стойност е невалидна.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Една или повече от зададените стойности е невалидна.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Това поле не се е очаквало.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Това поле липсва.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Стойността не е валидна дата (date).</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Стойността не е валидна дата (datetime).</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Стойността не е валиден email адрес.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Файлът не беше открит.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Файлът не може да бъде прочетен.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Стойността трябва да бъде {{ limit }} или по-малко.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Стойността трябва да бъде {{ limit }} или повече.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Стойността не трябва да бъде празна.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Стойността не трябва да бъде null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Стойността трябва да бъде null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Стойността не е валидна.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Стойността не е валидно време (time).</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Стойността не е валиден URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Двете стойности трябва да бъдат равни.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Файлът е твърде голям.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Файлът не може да бъде качен.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Стойността трябва да бъде валиден номер.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Файлът не е валидно изображение.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Това не е валиден IP адрес.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Стойността не е валиден език.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Стойността не е валидна локализация.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Стойността не е валидна държава.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Стойността вече е в употреба.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Размера на изображението не може да бъде определен.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Стойността трябва да бъде текущата потребителска парола.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Файлът е качен частично.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Файлът не беше качен.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Не е посочена директория за временни файлове в php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Не може да запише временен файл на диска.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP разширение предизвика прекъсване на качването.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Невалиден номер на картата.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Неподдържан тип карта или невалиден номер на картата.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Невалиден Международен номер на банкова сметка (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Невалиден ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Невалиден ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Невалидна стойност както за ISBN-10, така и за ISBN-13 .</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Невалиден Международен стандартен сериен номер (ISSN).</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Невалидна валута.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Стойността трябва да бъде равна на {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Стойността трябва да бъде по-голяма от {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Стойността трябва да бъде по-голяма или равна на {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Стойността трябва да бъде по-малка {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Стойността трябва да бъде по-малка или равна на {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Стойността не трябва да бъде равна на {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Изображението е с твърде голяма пропорция ({{ ratio }}). Максималната пропорция трябва да е {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Изображението е с твърде малка пропорция ({{ ratio }}). Минималната пропорция трябва да е {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Изображението е квадрат ({{ width }}x{{ height }}px). Такива изображения не са разрешени.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Изображението е с пейзажна ориентация ({{ width }}x{{ height }}px). Изображения с такава ориентация не са разрешени.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Изображението е с портретна ориентация ({{ width }}x{{ height }}px). Изображения с такава ориентация не са разрешени.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Празни файлове не са разрешени.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Хостът е недостъпен.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Стойността не съвпада с {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Невалиден бизнес идентификационен код (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Грешка</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ca.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ca.xlf
new file mode 100644
index 0000000..078a25d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ca.xlf
@@ -0,0 +1,311 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Aquest valor hauria de ser fals.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Aquest valor hauria de ser cert.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Aquest valor hauria de ser del tipus {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Aquest valor hauria d'estar buit.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>El valor seleccionat no és una opció vàlida.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Ha de seleccionar almenys {{ limit }} opció.|Ha de seleccionar almenys {{ limit }} opcions.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Ha de seleccionar com a màxim {{ limit }} opció.|Ha de seleccionar com a màxim {{ limit }} opcions.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Un o més dels valors facilitats són incorrectes.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Aquest camp no s'esperava.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Aquest camp està desaparegut.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Aquest valor no és una data vàlida.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Aquest valor no és una data i hora vàlida.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Aquest valor no és una adreça d'email vàlida.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>No s'ha pogut trobar l'arxiu.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>No es pot llegir l'arxiu.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>L'arxiu és massa gran ({{ size }} {{ suffix }}). La grandària màxima permesa és {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>El tipus mime de l'arxiu no és vàlid ({{ type }}). Els tipus mime vàlids són {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Aquest valor hauria de ser {{ limit }} o menys.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcter o menys.|Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcters o menys.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Aquest valor hauria de ser {{ limit }} o més.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Aquest valor és massa curt. Hauria de tenir {{ limit }} caràcters o més.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Aquest valor no hauria d'estar buit.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Aquest valor no hauria de ser null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Aquest valor hauria de ser null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Aquest valor no és vàlid.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Aquest valor no és una hora vàlida.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Aquest valor no és una URL vàlida.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Els dos valors haurien de ser iguals.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>L'arxiu és massa gran. El tamany màxim permés és {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>L'arxiu és massa gran.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>No es pot pujar l'arxiu.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Aquest valor hauria de ser un nombre vàlid.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>L'arxiu no és una imatge vàlida.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Això no és una adreça IP vàlida.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Aquest valor no és un idioma vàlid.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Aquest valor no és una localització vàlida.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Aquest valor no és un país vàlid.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Aquest valor ja s'ha utilitzat.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>No s'ha pogut determinar la grandària de la imatge.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>L'amplària de la imatge és massa gran ({{ width }}px). L'amplària màxima permesa són {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>L'amplària de la imatge és massa petita ({{ width }}px). L'amplària mínima requerida són {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>L'altura de la imatge és massa gran ({{ height }}px). L'altura màxima permesa són {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>L'altura de la imatge és massa petita ({{ height }}px). L'altura mínima requerida són {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Aquest valor hauria de ser la contrasenya actual de l'usuari.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Aquest valor hauria de tenir exactament {{ limit }} caràcter.|Aquest valor hauria de tenir exactament {{ limit }} caràcters.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>L'arxiu va ser només pujat parcialment.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Cap arxiu va ser pujat.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Cap carpeta temporal va ser configurada en php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>No es va poder escriure l'arxiu temporal en el disc.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Una extensió de PHP va fer que la pujada fallara.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Aquesta col·lecció ha de contenir {{ limit }} element o més.|Aquesta col·lecció ha de contenir {{ limit }} elements o més.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Aquesta col·lecció ha de contenir {{ limit }} element o menys.|Aquesta col·lecció ha de contenir {{ limit }} elements o menys.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Aquesta col·lecció ha de contenir exactament {{ limit }} element.|Aquesta col·lecció ha de contenir exactament {{ limit }} elements.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Número de targeta invàlid.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipus de targeta no suportada o número de targeta invàlid.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Això no és un nombre de compte bancari internacional (IBAN) vàlid.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Aquest valor no és un ISBN-10 vàlid.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Aquest valor no és un ISBN-13 vàlid.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Aquest valor no és ni un ISBN-10 vàlid ni un ISBN-13 vàlid.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Aquest valor no és un ISSN vàlid.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Aquest valor no és una divisa vàlida.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Aquest valor hauria de ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Aquest valor hauria de ser més gran a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Aquest valor hauria de ser major o igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Aquest valor hauria de ser idèntic a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Aquest valor hauria de ser menor a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Aquest valor hauria de ser menor o igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Aquest valor no hauria de ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Aquest valor no hauria de idèntic a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>La proporció de l'imatge és massa gran ({{ ratio }}). La màxima proporció permesa és {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>La proporció de l'imatge és massa petita ({{ ratio }}). La mínima proporció permesa és {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>L'imatge és quadrada({{ width }}x{{ height }}px). Les imatges quadrades no estan permeses.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>L'imatge està orientada horitzontalment ({{ width }}x{{ height }}px). Les imatges orientades horitzontalment no estan permeses.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>L'imatge està orientada verticalment ({{ width }}x{{ height }}px). Les imatges orientades verticalment no estan permeses.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>No està permès un fixter buit.</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Aquest valor no és un UUID vàlid.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.cs.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.cs.xlf
new file mode 100644
index 0000000..4b96669
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.cs.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Tato hodnota musí být nepravdivá (false).</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Tato hodnota musí být pravdivá (true).</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Tato hodnota musí být typu {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Tato hodnota musí být prázdná.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Vybraná hodnota není platnou možností.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Musí být vybrána nejméně {{ limit }} možnost.|Musí být vybrány nejméně {{ limit }} možnosti.|Musí být vybráno nejméně {{ limit }} možností.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Musí být vybrána maximálně {{ limit }} možnost.|Musí být vybrány maximálně {{ limit }} možnosti.|Musí být vybráno maximálně {{ limit }} možností.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Některé z uvedených hodnot jsou neplatné.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Toto pole nebylo očekáváno.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Toto pole chybí.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Tato hodnota není platné datum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Tato hodnota není platné datum s časovým údajem.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Tato hodnota není platná e-mailová adresa.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Soubor nebyl nalezen.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Soubor je nečitelný.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Soubor je příliš velký ({{ size }} {{ suffix }}). Maximální povolená velikost souboru je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Neplatný mime typ souboru ({{ type }}). Povolené mime typy souborů jsou {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Tato hodnota musí být {{ limit }} nebo méně.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znak.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaky.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaků.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Tato hodnota musí být {{ limit }} nebo více.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znak.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaky.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaků.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Tato hodnota nesmí být prázdná.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Tato hodnota nesmí být null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Tato hodnota musí být null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Tato hodnota není platná.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Tato hodnota není platný časový údaj.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Tato hodnota není platná URL adresa.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Tyto dvě hodnoty musí být stejné.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Soubor je příliš velký. Maximální povolená velikost souboru je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Soubor je příliš velký.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Soubor se nepodařilo nahrát.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Tato hodnota musí být číslo.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Tento soubor není obrázek.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Toto není platná IP adresa.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Tento jazyk neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Tato lokalizace neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Tato země neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Tato hodnota je již používána.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Nepodařily se zjistit rozměry obrázku.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Obrázek je příliš široký ({{ width }}px). Maximální povolená šířka obrázku je {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Obrázek je příliš úzký ({{ width }}px). Minimální šířka musí být {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Obrázek je příliš vysoký ({{ height }}px). Maximální povolená výška obrázku je {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Obrázek je příliš nízký ({{ height }}px). Minimální výška obrázku musí být {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Tato hodnota musí být aktuální heslo uživatele.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Tato hodnota musí mít přesně {{ limit }} znak.|Tato hodnota musí mít přesně {{ limit }} znaky.|Tato hodnota musí mít přesně {{ limit }} znaků.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Byla nahrána jen část souboru.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Žádný soubor nebyl nahrán.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>V php.ini není nastavena cesta k adresáři pro dočasné soubory.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Dočasný soubor se nepodařilo zapsat na disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Rozšíření PHP zabránilo nahrání souboru.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Tato kolekce musí obsahovat minimálně {{ limit }} prvek.|Tato kolekce musí obsahovat minimálně {{ limit }} prvky.|Tato kolekce musí obsahovat minimálně {{ limit }} prvků.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Tato kolekce musí obsahovat maximálně {{ limit }} prvek.|Tato kolekce musí obsahovat maximálně {{ limit }} prvky.|Tato kolekce musí obsahovat maximálně {{ limit }} prvků.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Tato kolekce musí obsahovat přesně {{ limit }} prvek.|Tato kolekce musí obsahovat přesně {{ limit }} prvky.|Tato kolekce musí obsahovat přesně {{ limit }} prvků.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Neplatné číslo karty.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nepodporovaný typ karty nebo neplatné číslo karty.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Toto je neplatný IBAN.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Tato hodnota není platné ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Tato hodnota není platné ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Tato hodnota není platné ISBN-10 ani ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Tato hodnota není platné ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Tato měna neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Tato hodnota musí být rovna {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Tato hodnota musí být větší než {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Tato hodnota musí být větší nebo rovna {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Tato hodnota musí být typu {{ compared_value_type }} a zároveň musí být rovna {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Tato hodnota musí být menší než {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Tato hodnota musí být menší nebo rovna {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Tato hodnota nesmí být rovna {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Tato hodnota nesmí být typu {{ compared_value_type }} a zároveň nesmí být rovna {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Poměr stran obrázku je příliš velký ({{ ratio }}). Maximální povolený poměr stran obrázku je {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Poměr stran obrázku je příliš malý ({{ ratio }}). Minimální povolený poměr stran obrázku je {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Strany obrázku jsou čtvercové ({{ width }}x{{ height }}px). Čtvercové obrázky nejsou povolené.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Obrázek je orientovaný na šířku ({{ width }}x{{ height }}px). Obrázky orientované na šířku nejsou povolené.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Obrázek je orientovaný na výšku ({{ width }}x{{ height }}px). Obrázky orientované na výšku nejsou povolené.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Soubor nesmí být prázdný.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Hostitele nebylo možné rozpoznat.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Tato hodnota neodpovídá očekávané znakové sadě {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Tato hodnota není platný identifikační kód podniku (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Chyba</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.cy.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.cy.xlf
new file mode 100644
index 0000000..da7cb9a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.cy.xlf
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Dylid bod y gwerth hwn yn ffug.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Dylid bod y gwerth hwn yn wir.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Dylid bod y gwerth hwn bod o fath {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Dylid bod y gwerth hwn yn wag.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Nid yw'r gwerth â ddewiswyd yn ddilys.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Rhaid dewis o leiaf {{ limit }} opsiwn.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Rhaid dewis dim mwy na {{ limit }} opsiwn.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Mae un neu fwy o'r gwerthoedd a roddwyd yn annilys.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Nid oedd disgwyl y maes hwn.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Mae'r maes hwn ar goll.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Nid yw'r gwerth yn ddyddiad dilys.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Nid yw'r gwerth yn datetime dilys.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Nid yw'r gwerth yn gyfeiriad ebost dilys.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Ni ddarganfyddwyd y ffeil.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Ni ellir darllen y ffeil.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Mae'r ffeil yn rhy fawr ({{ size }} {{ suffix }}). Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Nid yw math mime y ffeil yn ddilys ({{ type }}). Dyma'r mathau â ganiateir {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Dylai'r gwerth hwn fod yn {{ limit }} neu lai.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Mae'r gwerth hwn rhy hir. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu lai.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Dylai'r gwerth hwn fod yn {{ limit }} neu fwy.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Mae'r gwerth hwn yn rhy fyr. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu fwy.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ni ddylai'r gwerth hwn fod yn wag.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Ni ddylai'r gwerth hwn fod yn null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Dylai'r gwerth fod yn null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Nid yw'r gwerth hwn yn ddilys.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Nid yw'r gwerth hwn yn amser dilys.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Nid yw'r gwerth hwn yn URL dilys.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Rhaid i'r ddau werth fod yn gyfystyr a'u gilydd.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Mae'r ffeil yn rhy fawr. Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Mae'r ffeil yn rhy fawr.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Methwyd ag uwchlwytho'r ffeil.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Dylai'r gwerth hwn fod yn rif dilys.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Nid yw'r ffeil hon yn ddelwedd dilys.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Nid yw hwn yn gyfeiriad IP dilys.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Nid yw'r gwerth hwn yn iaith ddilys.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Nid yw'r gwerth hwn yn locale dilys.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Nid yw'r gwerth hwn yn wlad dilys.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Mae'r gwerth hwn eisoes yn cael ei ddefnyddio.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Methwyd â darganfod maint y ddelwedd.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Mae lled y ddelwedd yn rhy fawr ({{ width }}px). Y lled mwyaf â ganiateir yw {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Mae lled y ddelwedd yn rhy fach ({{ width }}px). Y lled lleiaf â ganiateir yw {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Mae uchder y ddelwedd yn rhy fawr ({{ width }}px). Yr uchder mwyaf â ganiateir yw {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Mae uchder y ddelwedd yn rhy fach ({{ width }}px). Yr uchder lleiaf â ganiateir yw {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Dylaid bod y gwerth hwn yn gyfrinair presenol y defnyddiwr.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Dylai'r gwerth hwn fod yn union {{ limit }} nodyn cyfrifiadurol o hyd.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Dim ond rhan o'r ffeil ag uwchlwythwyd.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ni uwchlwythwyd unrhyw ffeil.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nid oes ffolder dros-dro wedi'i gosod yn php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Methwyd ag ysgrifennu'r ffeil dros-dro ar ddisg.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Methwyd ag uwchlwytho oherwydd ategyn PHP.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu fwy.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu lai.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Dylai'r casgliad hwn gynnwys union {{ limit }} elfen.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Nid oedd rhif y cerdyn yn ddilys.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.da.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.da.xlf
new file mode 100644
index 0000000..3a545c8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.da.xlf
@@ -0,0 +1,251 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Værdien skal være falsk.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Værdien skal være sand.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Værdien skal være af typen {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Værdien skal være blank.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Den valgte værdi er ikke gyldig.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Du skal vælge mindst én mulighed.|Du skal vælge mindst {{ limit }} muligheder.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Du kan højst vælge én mulighed.|Du kan højst vælge {{ limit }} muligheder.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>En eller flere af de angivne værdier er ugyldige.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Feltet blev ikke forventet.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Dette felt mangler.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Værdien er ikke en gyldig dato.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Værdien er ikke et gyldigt tidspunkt.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Værdien er ikke en gyldig e-mailadresse.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Filen kunne ikke findes.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Filen kan ikke læses.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen er for stor ({{ size }} {{ suffix }}). Maksimale tilladte størrelse er {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Filens MIME-type er ugyldig ({{ type }}). Tilladte MIME-typer er {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Værdien skal være {{ limit }} eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Værdien er for lang. Den må højst indeholde {{ limit }} tegn.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Værdien skal være {{ limit }} eller mere.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Værdien er for kort. Den skal indeholde mindst {{ limit }} tegn.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Værdien må ikke være blank.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Værdien må ikke være tom (null).</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Værdien skal være tom (null).</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Værdien er ikke gyldig.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Værdien er ikke et gyldigt klokkeslæt.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Værdien er ikke en gyldig URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>De to værdier skal være ens.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Filen er for stor.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Filen kunne ikke blive uploadet.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Værdien skal være et gyldigt tal.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Filen er ikke gyldigt billede.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dette er ikke en gyldig IP-adresse.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Værdien er ikke et gyldigt sprog.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Værdien er ikke en gyldig lokalitet.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Værdien er ikke et gyldigt land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Værdien er allerede i brug.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Størrelsen på billedet kunne ikke detekteres.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Billedet er for bredt ({{ width }}px). Største tilladte bredde er {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Billedet er for smalt ({{ width }}px). Mindste forventede bredde er {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Billedet er for højt ({{ height }}px). Største tilladte højde er {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Billedet er for lavt ({{ height }}px). Mindste forventede højde er {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Værdien skal være brugerens nuværende adgangskode.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Værdien skal være på præcis {{ limit }} tegn.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Filen blev kun delvist uploadet.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ingen fil blev uploadet.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Ingen midlertidig mappe er konfigureret i php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan ikke skrive midlertidig fil til disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>En PHP-udvidelse forårsagede fejl i upload.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Denne samling skal indeholde mindst ét element.|Denne samling skal indeholde mindst {{ limit }} elementer.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Denne samling skal indeholde højst ét element.|Denne samling skal indeholde højst {{ limit }} elementer.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Denne samling skal indeholde præcis ét element.|Denne samling skal indeholde præcis {{ limit }} elementer.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ugyldigt kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Ikke-understøttet korttype eller ugyldigt kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Det er ikke et gyldigt International Bank Account Number (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Værdien er ikke en gyldig ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Værdien er ikke en gyldig ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Værdien er hverken en gyldig ISBN-10 eller en gyldig ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Værdien er ikke en gyldig ISSN.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Fejl</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.de.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.de.xlf
new file mode 100644
index 0000000..3e44e1e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.de.xlf
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Dieser Wert sollte false sein.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Dieser Wert sollte true sein.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Dieser Wert sollte vom Typ {{ type }} sein.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Dieser Wert sollte leer sein.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Sie haben einen ungültigen Wert ausgewählt.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Sie dürfen höchstens {{ limit }} Möglichkeit wählen.|Sie dürfen höchstens {{ limit }} Möglichkeiten wählen.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Einer oder mehrere der angegebenen Werte sind ungültig.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Dieses Feld wurde nicht erwartet.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Dieses Feld fehlt.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Dieser Wert entspricht keiner gültigen Datumsangabe.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Dieser Wert entspricht keiner gültigen Datums- und Zeitangabe.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Dieser Wert ist keine gültige E-Mail-Adresse.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Die Datei wurde nicht gefunden.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Die Datei ist nicht lesbar.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Die Datei ist zu groß ({{ size }} {{ suffix }}). Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Der Dateityp ist ungültig ({{ type }}). Erlaubte Dateitypen sind {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Dieser Wert sollte kleiner oder gleich {{ limit }} sein.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Dieser Wert sollte größer oder gleich {{ limit }} sein.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Dieser Wert sollte nicht leer sein.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Dieser Wert sollte nicht null sein.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Dieser Wert sollte null sein.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Dieser Wert ist nicht gültig.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Dieser Wert entspricht keiner gültigen Zeitangabe.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Dieser Wert ist keine gültige URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Die beiden Werte sollten identisch sein.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Die Datei ist zu groß. Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Die Datei ist zu groß.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Die Datei konnte nicht hochgeladen werden.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Dieser Wert sollte eine gültige Zahl sein.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Diese Datei ist kein gültiges Bild.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dies ist keine gültige IP-Adresse.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Dieser Wert entspricht keiner gültigen Sprache.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Dieser Wert entspricht keinem gültigen Gebietsschema.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Dieser Wert entspricht keinem gültigen Land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Dieser Wert wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Die Größe des Bildes konnte nicht ermittelt werden.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Die Bildbreite ist zu groß ({{ width }}px). Die maximal zulässige Breite beträgt {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Die Bildbreite ist zu gering ({{ width }}px). Die erwartete Mindestbreite beträgt {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Die Bildhöhe ist zu groß ({{ height }}px). Die maximal zulässige Höhe beträgt {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Die Bildhöhe ist zu gering ({{ height }}px). Die erwartete Mindesthöhe beträgt {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Dieser Wert sollte dem aktuellen Benutzerpasswort entsprechen.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Dieser Wert sollte genau {{ limit }} Zeichen lang sein.|Dieser Wert sollte genau {{ limit }} Zeichen lang sein.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Die Datei wurde nur teilweise hochgeladen.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Es wurde keine Datei hochgeladen.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Es wurde kein temporärer Ordner in der php.ini konfiguriert oder der temporäre Ordner existiert nicht.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kann die temporäre Datei nicht speichern.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Eine PHP-Erweiterung verhinderte den Upload.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Diese Sammlung sollte genau {{ limit }} Element beinhalten.|Diese Sammlung sollte genau {{ limit }} Elemente beinhalten.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ungültige Kartennummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nicht unterstützer Kartentyp oder ungültige Kartennummer.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Dieser Wert ist keine gültige internationale Bankkontonummer (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Dieser Wert entspricht keiner gültigen ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Dieser Wert entspricht keiner gültigen ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Dieser Wert ist weder eine gültige ISBN-10 noch eine gültige ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Dieser Wert ist keine gültige ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Dieser Wert ist keine gültige Währung.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Dieser Wert sollte gleich {{ compared_value }} sein.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Dieser Wert sollte größer als {{ compared_value }} sein.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Dieser Wert sollte größer oder gleich {{ compared_value }} sein.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Dieser Wert sollte identisch sein mit {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Dieser Wert sollte kleiner als {{ compared_value }} sein.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Dieser Wert sollte kleiner oder gleich {{ compared_value }} sein.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Dieser Wert sollte nicht {{ compared_value }} sein.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Dieser Wert sollte nicht identisch sein mit {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Das Seitenverhältnis des Bildes ist zu groß ({{ ratio }}). Der erlaubte Maximalwert ist {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Das Seitenverhältnis des Bildes ist zu klein ({{ ratio }}). Der erwartete Minimalwert ist {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Das Bild ist quadratisch ({{ width }}x{{ height }}px). Quadratische Bilder sind nicht erlaubt.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Das Bild ist im Querformat ({{ width }}x{{ height }}px). Bilder im Querformat sind nicht erlaubt.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Das Bild ist im Hochformat ({{ width }}x{{ height }}px). Bilder im Hochformat sind nicht erlaubt.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Eine leere Datei ist nicht erlaubt.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Der Hostname konnte nicht aufgelöst werden.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Dieser Wert entspricht nicht dem erwarteten Zeichensatz {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Dieser Wert ist kein gültiger BIC.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Fehler</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Dies ist keine gültige UUID.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.el.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.el.xlf
new file mode 100644
index 0000000..a3199bc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.el.xlf
@@ -0,0 +1,283 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Αυτή η τιμή πρέπει να είναι ψευδής.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Αυτή η τιμή πρέπει να είναι αληθής.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Αυτή η τιμή πρέπει να είναι τύπου {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Αυτή η τιμή πρέπει να είναι κενή.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Η τιμή που επιλέχθηκε δεν αντιστοιχεί σε έγκυρη επιλογή.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Μια ή περισσότερες τιμές δεν είναι έγκυρες.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Αυτό το πεδίο δεν ήταν αναμενόμενο.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Λείπει αυτό το πεδίο.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία και ώρα.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Η τιμή δεν αντιστοιχεί σε έγκυρο email.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Το αρχείο δε μπορεί να βρεθεί.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Το αρχείο δεν είναι αναγνώσιμο.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Το αρχείο είναι πολύ μεγάλο ({{ size }} {{ suffix }}). Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Ο τύπος mime του αρχείου δεν είναι έγκυρος ({{ type }}). Οι έγκρυοι τύποι mime είναι {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή λιγότερο.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή λιγότερο.|Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή λιγότερο.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή περισσότερο.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή περισσότερο.|Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή περισσότερο.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Αυτή η τιμή δεν πρέπει να είναι κενή.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Αυτή η τιμή δεν πρέπει να είναι μηδενική.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Αυτή η τιμή πρέπει να είναι μηδενική.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Αυτή η τιμή δεν είναι έγκυρη.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Αυτή η τιμή δεν αντιστοιχεί σε έγκυρη ώρα.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Αυτή η τιμή δεν αντιστοιχεί σε έγκυρο URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Οι δύο τιμές θα πρέπει να είναι ίδιες.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Το αρχείο είναι πολύ μεγάλο.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Το αρχείο δε μπορεί να ανέβει.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι ένας έγκυρος αριθμός.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Το αρχείο δεν αποτελεί έγκυρη εικόνα.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Αυτό δεν είναι μια έγκυρη διεύθυνση IP.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Αυτή η τιμή δεν αντιστοιχεί σε μια έγκυρη γλώσσα.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Αυτή η τιμή δεν αντιστοιχεί σε έκγυρο κωδικό τοποθεσίας.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Αυτή η τιμή δεν αντιστοιχεί σε μια έγκυρη χώρα.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Αυτή η τιμή χρησιμοποιείται ήδη.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Το μέγεθος της εικόνας δεν ήταν δυνατό να ανιχνευθεί.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Το πλάτος της εικόνας είναι πολύ μεγάλο ({{ width }}px). Το μέγιστο επιτρεπτό πλάτος είναι {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Το πλάτος της εικόνας είναι πολύ μικρό ({{ width }}px). Το ελάχιστο επιτρεπτό πλάτος είναι {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Το ύψος της εικόνας είναι πολύ μεγάλο ({{ height }}px). Το μέγιστο επιτρεπτό ύψος είναι {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Το ύψος της εικόνας είναι πολύ μικρό ({{ height }}px). Το ελάχιστο επιτρεπτό ύψος είναι {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Αυτή η τιμή θα έπρεπε να είναι ο τρέχων κωδικός.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρα.|Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρες.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Το αρχείο δεν ανέβηκε ολόκληρο.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Δεν ανέβηκε κανένα αρχείο.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Κανένας προσωρινός φάκελος δεν έχει ρυθμιστεί στο php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Αδυναμία εγγραφής προσωρινού αρχείου στο δίσκο.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Μια επέκταση PHP προκάλεσε αδυναμία ανεβάσματος.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείο ή περισσότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή περισσότερα.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείo ή λιγότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή λιγότερα.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχείo.|Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχεία.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Μη έγκυρος αριθμός κάρτας.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Μη υποστηριζόμενος τύπος κάρτας ή μη έγκυρος αριθμός κάρτας.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Αυτό δεν αντιστοιχεί σε έκγυρο διεθνή αριθμό τραπεζικού λογαριασμού (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Αυτό δεν είναι έγκυρος κωδικός ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Αυτό δεν είναι έγκυρος κωδικός ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Αυτό δεν είναι ούτε έγκυρος κωδικός ISBN-10 ούτε έγκυρος κωδικός ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Αυτό δεν είναι έγκυρος κωδικός ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Αυτό δεν αντιστοιχεί σε έγκυρο νόμισμα.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι ίση με {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη από {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη ή ίση με {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι μικρότερη από {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Αυτή η τιμή θα πρέπει να είναι μικρότερη ή ίση με {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Αυτή η τιμή δεν θα πρέπει να είναι ίση με {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.en.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.en.xlf
new file mode 100644
index 0000000..4bb2760
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.en.xlf
@@ -0,0 +1,331 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>This value should be false.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>This value should be true.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>This value should be of type {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>This value should be blank.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>The value you selected is not a valid choice.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>One or more of the given values is invalid.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>This field was not expected.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>This field is missing.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>This value is not a valid date.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>This value is not a valid datetime.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>This value is not a valid email address.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>The file could not be found.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>The file is not readable.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>This value should be {{ limit }} or less.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>This value should be {{ limit }} or more.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>This value should not be blank.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>This value should not be null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>This value should be null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>This value is not valid.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>This value is not a valid time.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>This value is not a valid URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>The two values should be equal.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>The file is too large.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>The file could not be uploaded.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>This value should be a valid number.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>This file is not a valid image.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>This is not a valid IP address.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>This value is not a valid language.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>This value is not a valid locale.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>This value is not a valid country.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>This value is already used.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>The size of the image could not be detected.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>This value should be the user's current password.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>The file was only partially uploaded.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>No file was uploaded.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>No temporary folder was configured in php.ini, or the configured folder does not exist.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Cannot write temporary file to disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>A PHP extension caused the upload to fail.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Invalid card number.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Unsupported card type or invalid card number.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>This is not a valid International Bank Account Number (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>This value is not a valid ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>This value is not a valid ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>This value is neither a valid ISBN-10 nor a valid ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>This value is not a valid ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>This value is not a valid currency.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>This value should be equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>This value should be greater than {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>This value should be greater than or equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>This value should be less than {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>This value should be less than or equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>This value should not be equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>An empty file is not allowed.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>The host could not be resolved.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>This value does not match the expected {{ charset }} charset.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>This is not a valid Business Identifier Code (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Error</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>This is not a valid UUID.</target>
+ </trans-unit>
+ <trans-unit id="84">
+ <source>This value should be a multiple of {{ compared_value }}.</source>
+ <target>This value should be a multiple of {{ compared_value }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.es.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.es.xlf
new file mode 100644
index 0000000..25d5b8a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.es.xlf
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Este valor debería ser falso.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Este valor debería ser verdadero.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Este valor debería ser de tipo {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Este valor debería estar vacío.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>El valor seleccionado no es una opción válida.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Debe seleccionar al menos {{ limit }} opción.|Debe seleccionar al menos {{ limit }} opciones.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opciones.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Uno o más de los valores indicados no son válidos.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Este campo no se esperaba.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Este campo está desaparecido.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Este valor no es una fecha válida.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Este valor no es una fecha y hora válidas.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Este valor no es una dirección de email válida.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>No se pudo encontrar el archivo.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>No se puede leer el archivo.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>El archivo es demasiado grande ({{ size }} {{ suffix }}). El tamaño máximo permitido es {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>El tipo mime del archivo no es válido ({{ type }}). Los tipos mime válidos son {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Este valor debería ser {{ limit }} o menos.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Este valor es demasiado largo. Debería tener {{ limit }} carácter o menos.|Este valor es demasiado largo. Debería tener {{ limit }} caracteres o menos.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Este valor debería ser {{ limit }} o más.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Este valor es demasiado corto. Debería tener {{ limit }} carácter o más.|Este valor es demasiado corto. Debería tener {{ limit }} caracteres o más.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Este valor no debería estar vacío.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Este valor no debería ser nulo.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Este valor debería ser nulo.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Este valor no es válido.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Este valor no es una hora válida.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Este valor no es una URL válida.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Los dos valores deberían ser iguales.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>El archivo es demasiado grande. El tamaño máximo permitido es {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>El archivo es demasiado grande.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>No se pudo subir el archivo.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Este valor debería ser un número válido.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>El archivo no es una imagen válida.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Esto no es una dirección IP válida.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Este valor no es un idioma válido.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Este valor no es una localización válida.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Este valor no es un país válido.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Este valor ya se ha utilizado.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>No se pudo determinar el tamaño de la imagen.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>El ancho de la imagen es demasiado grande ({{ width }}px). El ancho máximo permitido es de {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>El ancho de la imagen es demasiado pequeño ({{ width }}px). El ancho mínimo requerido es {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>La altura de la imagen es demasiado grande ({{ height }}px). La altura máxima permitida es de {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>La altura de la imagen es demasiado pequeña ({{ height }}px). La altura mínima requerida es de {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Este valor debería ser la contraseña actual del usuario.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Este valor debería tener exactamente {{ limit }} carácter.|Este valor debería tener exactamente {{ limit }} caracteres.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>El archivo fue sólo subido parcialmente.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ningún archivo fue subido.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Ninguna carpeta temporal fue configurada en php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>No se pudo escribir el archivo temporal en el disco.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Una extensión de PHP hizo que la subida fallara.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Esta colección debe contener {{ limit }} elemento o más.|Esta colección debe contener {{ limit }} elementos o más.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Esta colección debe contener {{ limit }} elemento o menos.|Esta colección debe contener {{ limit }} elementos o menos.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Esta colección debe contener exactamente {{ limit }} elemento.|Esta colección debe contener exactamente {{ limit }} elementos.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Número de tarjeta inválido.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipo de tarjeta no soportado o número de tarjeta inválido.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Esto no es un International Bank Account Number (IBAN) válido.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Este valor no es un ISBN-10 válido.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Este valor no es un ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Este valor no es ni un ISBN-10 válido ni un ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Este valor no es un ISSN válido.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Este valor no es una divisa válida.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser igual que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Este valor debería ser mayor que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser mayor o igual que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor debería ser idéntico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Este valor debería ser menor que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser menor o igual que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser distinto de {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor no debería ser idéntico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>La proporción de la imagen es demasiado grande ({{ ratio }}). La máxima proporción permitida es {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>La proporción de la imagen es demasiado pequeña ({{ ratio }}). La mínima proporción permitida es {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>La imagen es cuadrada ({{ width }}x{{ height }}px). Las imágenes cuadradas no están permitidas.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>La imagen está orientada horizontalmente ({{ width }}x{{ height }}px). Las imágenes orientadas horizontalmente no están permitidas.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>La imagen está orientada verticalmente ({{ width }}x{{ height }}px). Las imágenes orientadas verticalmente no están permitidas.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>No está permitido un archivo vacío.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>No se puede resolver el host.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>La codificación de caracteres para este valor debería ser {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>No es un Código de Identificación Bancaria (BIC) válido.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Error</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Este valor no es un UUID válido.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.et.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.et.xlf
new file mode 100644
index 0000000..d047c8b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.et.xlf
@@ -0,0 +1,283 @@
+<?xml version='1.0'?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Väärtus peaks olema väär.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Väärtus peaks oleme tõene.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Väärtus peaks olema {{ type }}-tüüpi.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Väärtus peaks olema tühi.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Väärtus peaks olema üks etteantud valikutest.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Valima peaks vähemalt {{ limit }} valikut.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Valima peaks mitte rohkem kui {{ limit }} valikut.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>One or more of the given values is invalid.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>See väli ei oodatud.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>See väli on puudu.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Väärtus pole korrektne kuupäev.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Väärtus pole korrektne kuupäev ja kellaeg.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Väärtus pole korrektne e-maili aadress.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Faili ei leita.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Fail ei ole loetav.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fail on liiga suur ({{ size }} {{ suffix }}). Suurim lubatud suurus on {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Faili sisutüüp on vigane ({{ type }}). Lubatud sisutüübid on {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Väärtus peaks olema {{ limit }} või vähem.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Väärtus on liiga pikk. Pikkus peaks olema {{ limit }} tähemärki või vähem.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Väärtus peaks olema {{ limit }} või rohkem.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Väärtus on liiga lühike. Pikkus peaks olema {{ limit }} tähemärki või rohkem.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Väärtus ei tohiks olla tühi.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Väärtus ei tohiks olla 'null'.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Väärtus peaks olema 'null'.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Väärtus on vigane.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Väärtus pole korrektne aeg.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Väärtus pole korrektne URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Väärtused peaksid olema võrdsed.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fail on liiga suur. Maksimaalne lubatud suurus on {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Fail on liiga suur.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Faili ei saa üles laadida.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Väärtus peaks olema korrektne number.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Fail ei ole korrektne pilt.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>IP aadress pole korrektne.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Väärtus pole korrektne keel.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Väärtus pole korrektne asukohakeel.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Väärtus pole olemasolev riik.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Väärtust on juba kasutatud.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Pildi suurust polnud võimalik tuvastada.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Pilt on liiga lai ({{ width }}px). Suurim lubatud laius on {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Pilt on liiga kitsas ({{ width }}px). Vähim lubatud laius on {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Pilt on liiga pikk ({{ height }}px). Lubatud suurim pikkus on {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Pilt pole piisavalt pikk ({{ height }}px). Lubatud vähim pikkus on {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Väärtus peaks olema kasutaja kehtiv salasõna.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} characters.</source>
+ <target>Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Fail ei laetud täielikult üles.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ühtegi faili ei laetud üles.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Ühtegi ajutist kausta polnud php.ini-s seadistatud.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Ajutist faili ei saa kettale kirjutada.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP laiendi tõttu ebaõnnestus faili üleslaadimine.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} elements or more.</source>
+ <target>Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} elements or less.</source>
+ <target>Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} elements.</source>
+ <target>Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Vigane kaardi number.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Kaardi tüüpi ei toetata või kaardi number on vigane.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Väärtus pole korrektne IBAN-number.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Väärtus pole korrektne ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Väärtus pole korrektne ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Väärtus pole korrektne ISBN-10 ega ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Väärtus pole korrektne ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Väärtus pole korrektne valuuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Väärtus peaks olema võrdne {{ compared_value }}-ga.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Väärtus peaks olema suurem kui {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Väärtus peaks olema suurem kui või võrduma {{ compared_value }}-ga.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Väärtus peaks olema identne väärtusega {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Väärtus peaks olema väiksem kui {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Väärtus peaks olema väiksem kui või võrduma {{ compared_value }}-ga.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Väärtus ei tohiks võrduda {{ compared_value }}-ga.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Väärtus ei tohiks olla identne väärtusega {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.eu.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.eu.xlf
new file mode 100644
index 0000000..d311ded
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.eu.xlf
@@ -0,0 +1,291 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Balio hau faltsua izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Balio hau egia izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Balio hau {{ type }} motakoa izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Balio hau hutsik egon beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Hautatu duzun balioa ez da aukera egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Gutxienez aukera {{ limit }} hautatu behar duzu.|Gutxienez {{ limit }} aukera hautatu behar dituzu.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Gehienez aukera {{ limit }} hautatu behar duzu.|Gehienez {{ limit }} aukera hautatu behar dituzu.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Emandako balioetatik gutxienez bat ez da egokia.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Eremu hau ez zen espero.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Eremu hau falta da.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Balio hau ez da data egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Balio hau ez da data-ordu egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Balio hau ez da posta elektroniko egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Ezin izan da fitxategia aurkitu.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Fitxategia ez da irakurgarria.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fitxategia handiegia da ({{ size }} {{ suffix }}). Baimendutako tamaina handiena {{ limit }} {{ suffix }} da.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Fitxategiaren mime mota ez da egokia ({{ type }}). Hauek dira baimendutako mime motak: {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Balio hau gehienez {{ limit }} izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Balio hau luzeegia da. Gehienez karaktere {{ limit }} eduki beharko luke.|Balio hau luzeegia da. Gehienez {{ limit }} karaktere eduki beharko lituzke.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Balio hau gutxienez {{ limit }} izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Balio hau motzegia da. Karaktere {{ limit }} gutxienez eduki beharko luke.|Balio hau motzegia da. Gutxienez {{ limit }} karaktere eduki beharko lituzke.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Balio hau ez litzateke hutsik egon behar.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Balio hau ez litzateke nulua izan behar.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Balio hau nulua izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Balio hau ez da egokia.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Balio hau ez da ordu egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Balio hau ez da baliabideen kokatzaile uniforme (URL) egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Bi balioak berdinak izan beharko lirateke.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fitxategia handiegia da. Baimendutako tamaina handiena {{ limit }} {{ suffix }} da.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Fitxategia handiegia da.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Ezin izan da fitxategia igo.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Balio hau zenbaki egoki bat izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Fitxategi hau ez da irudi egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Honako hau ez da IP helbide egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Balio hau ez da hizkuntza egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Balio hau ez da kokapen egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Balio hau ez da herrialde egoki bat.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Balio hau jadanik erabilia izan da.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Ezin izan da irudiaren tamaina detektatu.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Irudiaren zabalera handiegia da ({{ width }}px). Onartutako gehienezko zabalera {{ max_width }}px dira.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Irudiaren zabalera txikiegia da ({{ width }}px). Onartutako gutxieneko zabalera {{ min_width }}px dira.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Irudiaren altuera handiegia da ({{ height }}px). Onartutako gehienezko altuera {{ max_height }}px dira.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Irudiaren altuera txikiegia da ({{ height }}px). Onartutako gutxieneko altuera {{ min_height }}px dira.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Balio hau uneko erabiltzailearen pasahitza izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Balio honek zehazki karaktere {{ limit }} izan beharko luke.|Balio honek zehazki {{ limit }} karaktere izan beharko lituzke.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Fitxategiaren zati bat bakarrik igo da.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ez da fitxategirik igo.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Ez da aldi baterako karpetarik konfiguratu php.ini fitxategian.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Ezin izan da aldi baterako fitxategia diskoan idatzi.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP luzapen batek igoeraren hutsa eragin du.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Bilduma honek gutxienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gutxienez {{ limit }} elementu eduki beharko lituzke.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Bilduma honek gehienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gehienez {{ limit }} elementu eduki beharko lituzke.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Bilduma honek zehazki elementu {{ limit }} eduki beharko luke.|Bilduma honek zehazki {{ limit }} elementu eduki beharko lituzke.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Txartel zenbaki baliogabea.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Txartel mota onartezina edo txartel zenbaki baliogabea.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Hau ez da baliozko banku internazionaleko kontu zenbaki (IBAN) bat.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Balio hau ez da onartutako ISBN-10 bat.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Balio hau ez da onartutako ISBN-13 bat.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Balio hau ez da onartutako ISBN-10 edo ISBN-13 bat.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Balio hau ez da onartutako ISSN bat.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Balio hau ez da baliozko moneta bat.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Balio hau {{ compared_value }}-(r)en berbera izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Balio hau {{ compared_value }} baino handiagoa izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Balio hau {{ compared_value }}-(r)en berdina edota handiagoa izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Balio hau {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Balio hau {{ compared_value }} baino txikiagoa izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Balio hau {{ compared_value }}-(r)en berdina edota txikiagoa izan beharko litzateke.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Balio hau ez litzateke {{ compared_value }}-(r)en berdina izan behar.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Balio hau ez litzateke {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan behar.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Errore</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Balio hau ez da onartutako UUID bat.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fa.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fa.xlf
new file mode 100644
index 0000000..98b4bd6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fa.xlf
@@ -0,0 +1,283 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target state="needs-review-translation">این مقدار باید نادرست(False) باشد.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>این مقدار باید درست(True) باشد.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>این مقدار باید از نوع {{ type }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>این فیلد باید خالی باشد.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>گزینه انتخابی معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>یک یا چند مقدار نامعتبر وجود دارد.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>The fields {{ fields }} were not expected.</source>
+ <target>فیلدهای {{ fields }} اضافی هستند.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>The fields {{ fields }} are missing.</source>
+ <target>فیلدهای {{ fields }} کم هستند.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>این مقدار یک تاریخ معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>این مقدار یک تاریخ و زمان معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>این یک رایانامه معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>فایل پیدا نشد.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>فایل قابلیت خواندن ندارد.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>این مقدار باید کوچکتر یا مساوی {{ limit }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>این مقدار باید برابر و یا بیشتر از {{ limit }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>این مقدار نباید تهی باشد.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>باید مقداری داشته باشد..</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>نباید مقداری داشته باشد.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>این مقدار معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>این مقدار یک زمان صحیح نیست.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>این یک URL معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>دو مقدار باید برابر باشند.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>فایل بیش از اندازه بزرگ است.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>بارگذاری فایل با شکست مواجه شد.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>این مقدار باید یک عدد معتبر باشد.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>این فایل یک تصویر نیست.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>این مقدار یک IP معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>این مقدار یک زبان صحیح نیست.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>این مقدار یک محل صحیح نیست.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>این مقدار یک کشور صحیح نیست.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>این مقدار قبلا مورد استفاده قرار گرفته است.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>اندازه تصویر قابل شناسایی نیست.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>این مقدار می بایست کلمه عبور کنونی کاربر باشد.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target> این مقدار می بایست دقیقا {{ limit }} کاراکتر داشته باشد.| این مقدار می بایست دقیقا {{ limit }} کاراکتر داشته باشد.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>فایل به صورت جزیی بارگذاری شده است.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>هیچ فایلی بارگذاری نشد.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>فولدر موقت در php.ini پیکربندی نشده است.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>فایل موقت را نمی توان در دیسک نوشت.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>شماره کارت نامعتبر است.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>این یک شماره حساب بین المللی بانک (IBAN) درست نیست.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>این مقدار یک ISBN-10 درست نیست.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>این مقدار یک ISBN-13 درست نیست.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>این مقدار یک ISSN درست نیست.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>این مقدار یک یکای پول درست نیست.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>این مقدار باید برابر با {{ compared_value }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>این مقدار باید از {{ compared_value }} بیشتر باشد.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>این مقدار باید کمتر از {{ compared_value }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>این مقدار نباید با {{ compared_value }} برابر باشد.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fi.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fi.xlf
new file mode 100644
index 0000000..e439098
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fi.xlf
@@ -0,0 +1,231 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Arvon tulee olla epätosi.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Arvon tulee olla tosi.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Arvon tulee olla tyyppiä {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Arvon tulee olla tyhjä.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Arvon tulee olla yksi annetuista vaihtoehdoista.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Sinun tulee valita vähintään {{ limit }} vaihtoehtoa.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Sinun tulee valitan enintään {{ limit }} vaihtoehtoa.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Yksi tai useampi annetuista arvoista on virheellinen.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Tässä kentässä ei odotettu.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Tämä kenttä puuttuu.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Annettu arvo ei ole kelvollinen päivämäärä.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Annettu arvo ei ole kelvollinen päivämäärä ja kellonaika.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Annettu arvo ei ole kelvollinen sähköpostiosoite.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Tiedostoa ei löydy.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Tiedostoa ei voida lukea.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Tiedostonkoko ({{ size }} {{ suffix }}) on liian iso. Suurin sallittu tiedostonkoko on {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Tiedostotyyppi ({{ type }}) on virheellinen. Sallittuja tiedostotyyppejä ovat {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Arvon tulee olla {{ limit }} tai vähemmän.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Liian pitkä syöte. Syöte saa olla enintään {{ limit }} merkkiä.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Arvon tulee olla {{ limit }} tai enemmän.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Liian lyhyt syöte. Syötteen tulee olla vähintään {{ limit }} merkkiä.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Kenttä ei voi olla tyhjä.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Syöte ei voi olla null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Syötteen tulee olla null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Virheellinen arvo.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Annettu arvo ei ole kelvollinen kellonaika.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Annettu arvo ei ole kelvollinen URL-osoite.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Kahden annetun arvon tulee olla samat.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Annettu tiedosto on liian iso. Suurin sallittu tiedostokoko on {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Tiedosto on liian iso.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Tiedoston siirto epäonnistui.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Tämän arvon tulee olla numero.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Tämä tiedosto ei ole kelvollinen kuva.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Tämä ei ole kelvollinen IP-osoite.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Tämä arvo ei ole kelvollinen kieli.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Tämä arvo ei ole kelvollinen kieli- ja alueasetus (locale).</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Tämä arvo ei ole kelvollinen maa.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Tämä arvo on jo käytetty.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Kuvan kokoa ei voitu tunnistaa.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Kuva on liian leveä ({{ width }}px). Sallittu maksimileveys on {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Kuva on liian kapea ({{ width }}px). Leveyden tulisi olla vähintään {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Kuva on liian korkea ({{ width }}px). Sallittu maksimikorkeus on {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Kuva on liian matala ({{ height }}px). Korkeuden tulisi olla vähintään {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Tämän arvon tulisi olla käyttäjän tämänhetkinen salasana.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Tämän arvon tulisi olla tasan yhden merkin pituinen.|Tämän arvon tulisi olla tasan {{ limit }} merkkiä pitkä.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Tiedosto ladattiin vain osittain.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Tiedostoa ei ladattu.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Väliaikaishakemistoa ei ole asetettu php.ini -tiedostoon.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Väliaikaistiedostoa ei voitu kirjoittaa levylle.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP-laajennoksen vuoksi tiedoston lataus epäonnistui.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Tässä ryhmässä tulisi olla yksi tai useampi elementti.|Tässä ryhmässä tulisi olla vähintään {{ limit }} elementtiä.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Tässä ryhmässä tulisi olla enintään yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Tässä ryhmässä tulisi olla tasan yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Virheellinen korttinumero.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tätä korttityyppiä ei tueta tai korttinumero on virheellinen.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Virhe</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fr.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fr.xlf
new file mode 100644
index 0000000..382acb9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.fr.xlf
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Cette valeur doit être fausse.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Cette valeur doit être vraie.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Cette valeur doit être de type {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Cette valeur doit être vide.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Cette valeur doit être l'un des choix proposés.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Vous devez sélectionner au moins {{ limit }} choix.|Vous devez sélectionner au moins {{ limit }} choix.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Vous devez sélectionner au maximum {{ limit }} choix.|Vous devez sélectionner au maximum {{ limit }} choix.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Une ou plusieurs des valeurs soumises sont invalides.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Ce champ n'a pas été prévu.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ce champ est manquant.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Cette valeur n'est pas une date valide.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Cette valeur n'est pas une date valide.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Cette valeur n'est pas une adresse email valide.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Le fichier n'a pas été trouvé.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Le fichier n'est pas lisible.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Le fichier est trop volumineux ({{ size }} {{ suffix }}). Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Le type du fichier est invalide ({{ type }}). Les types autorisés sont {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Cette valeur doit être inférieure ou égale à {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractères.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Cette valeur doit être supérieure ou égale à {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractères.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Cette valeur ne doit pas être vide.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Cette valeur ne doit pas être nulle.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Cette valeur doit être nulle.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Cette valeur n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Cette valeur n'est pas une heure valide.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Cette valeur n'est pas une URL valide.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Les deux valeurs doivent être identiques.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Le fichier est trop volumineux. Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Le fichier est trop volumineux.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Le téléchargement de ce fichier est impossible.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Cette valeur doit être un nombre.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ce fichier n'est pas une image valide.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Cette adresse IP n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Cette langue n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Ce paramètre régional n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Ce pays n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Cette valeur est déjà utilisée.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>La taille de l'image n'a pas pu être détectée.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>La largeur de l'image est trop grande ({{ width }}px). La largeur maximale autorisée est de {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>La largeur de l'image est trop petite ({{ width }}px). La largeur minimale attendue est de {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>La hauteur de l'image est trop grande ({{ height }}px). La hauteur maximale autorisée est de {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>La hauteur de l'image est trop petite ({{ height }}px). La hauteur minimale attendue est de {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Cette valeur doit être le mot de passe actuel de l'utilisateur.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Cette chaîne doit avoir exactement {{ limit }} caractère.|Cette chaîne doit avoir exactement {{ limit }} caractères.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Le fichier a été partiellement transféré.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Aucun fichier n'a été transféré.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Aucun répertoire temporaire n'a été configuré dans le php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Impossible d'écrire le fichier temporaire sur le disque.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Une extension PHP a empêché le transfert du fichier.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Numéro de carte invalide.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Type de carte non supporté ou numéro invalide.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Le numéro IBAN (International Bank Account Number) saisi n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Cette valeur n'est pas un code ISBN-10 valide.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Cette valeur n'est pas un code ISBN-13 valide.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Cette valeur n'est ni un code ISBN-10, ni un code ISBN-13 valide.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Cette valeur n'est pas un code ISSN valide.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Cette valeur n'est pas une devise valide.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Cette valeur doit être égale à {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Cette valeur doit être supérieure à {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Cette valeur doit être supérieure ou égale à {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Cette valeur doit être identique à {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Cette valeur doit être inférieure à {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Cette valeur doit être inférieure ou égale à {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Cette valeur ne doit pas être égale à {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Le rapport largeur/hauteur de l'image est trop grand ({{ ratio }}). Le rapport maximal autorisé est {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Le rapport largeur/hauteur de l'image est trop petit ({{ ratio }}). Le rapport minimal attendu est {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>L'image est carrée ({{ width }}x{{ height }}px). Les images carrées ne sont pas autorisées.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>L'image est au format paysage ({{ width }}x{{ height }}px). Les images au format paysage ne sont pas autorisées.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>L'image est au format portrait ({{ width }}x{{ height }}px). Les images au format portrait ne sont pas autorisées.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Un fichier vide n'est pas autorisé.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Le nom de domaine n'a pas pu être résolu.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Cette valeur ne correspond pas au jeu de caractères {{ charset }} attendu.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Ce n'est pas un code universel d'identification des banques (BIC) valide.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Erreur</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Ceci n'est pas un UUID valide.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.gl.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.gl.xlf
new file mode 100644
index 0000000..ecb7155
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.gl.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Este valor debería ser falso.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Este valor debería ser verdadeiro.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Este valor debería ser de tipo {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Este valor debería estar baleiro.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>O valor seleccionado non é unha opción válida.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Debe seleccionar polo menos {{ limit }} opción.|Debe seleccionar polo menos {{ limit }} opcions.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opcions.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Un ou máis dos valores indicados non son válidos.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Este campo non era esperado.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Este campo falta.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Este valor non é unha data válida.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Este valor non é unha data e hora válidas.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Este valor non é unha dirección de correo electrónico válida.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Non se puido atopar o arquivo.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>O arquivo non se pode ler.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>O arquivo é demasiado grande ({{ size }} {{ suffix }}). O tamaño máximo permitido é {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>O tipo mime do arquivo non é válido ({{ type }}). Os tipos mime válidos son {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Este valor debería ser {{ limit }} ou menos.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Este valor é demasiado longo. Debería ter {{ limit }} carácter ou menos.|Este valor é demasiado longo. Debería ter {{ limit }} caracteres ou menos.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Este valor debería ser {{ limit }} ou máis.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Este valor é demasiado curto. Debería ter {{ limit }} carácter ou máis.|Este valor é demasiado corto. Debería ter {{ limit }} caracteres ou máis.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Este valor non debería estar baleiro.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Este valor non debería ser null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Este valor debería ser null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Este valor non é válido.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Este valor non é unha hora válida.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Este valor non é unha URL válida.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Os dous valores deberían ser iguais.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>O arquivo é demasiado grande. O tamaño máximo permitido é {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>O arquivo é demasiado grande.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>No se puido cargar o arquivo.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Este valor debería ser un número válido.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>O arquivo non é unha imaxe válida.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Isto non é unha dirección IP válida.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Este valor non é un idioma válido.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Este valor non é unha localización válida.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Este valor non é un país válido.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Este valor xa está a ser empregado.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Non se puido determinar o tamaño da imaxe.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>A largura da imaxe é demasiado grande ({{ width }}px). A largura máxima permitida son {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>A largura da imaxe é demasiado pequena ({{ width }}px). A largura mínima requerida son {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>A altura da imaxe é demasiado grande ({{ height }}px). A altura máxima permitida son {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>A altura da imaxe é demasiado pequena ({{ height }}px). A altura mínima requerida son {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Este valor debería ser a contrasinal actual do usuario.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Este valor debería ter exactamente {{ limit }} carácter.|Este valor debería ter exactamente {{ limit }} caracteres.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>O arquivo foi só subido parcialmente.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Non se subiu ningún arquivo.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Ningunha carpeta temporal foi configurada en php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Non se puido escribir o arquivo temporal no disco.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Unha extensión de PHP provocou que a subida fallara.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Esta colección debe conter {{ limit }} elemento ou máis.|Esta colección debe conter {{ limit }} elementos ou máis.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Esta colección debe conter {{ limit }} elemento ou menos.|Esta colección debe conter {{ limit }} elementos ou menos.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Esta colección debe conter exactamente {{ limit }} elemento.|Esta colección debe conter exactamente {{ limit }} elementos.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Número de tarxeta non válido.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipo de tarxeta non soportado ou número de tarxeta non válido.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Este valor non é un International Bank Account Number (IBAN) válido.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Este valor non é un ISBN-10 válido.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Este valor non é un ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Este valor non é nin un ISBN-10 válido nin un ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Este valor non é un ISSN válido.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Este valor non é unha moeda válida.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Este valor debería ser maior que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser maior ou igual que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor debería ser identico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Este valor debería ser menor que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Este valor debería ser menor ou igual que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Este valor non debería ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor non debería ser identico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>A proporción da imaxe é demasiado grande ({{ ratio }}). A proporción máxima permitida é {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>A proporción da é demasiado pequena ({{ ratio }}). A proporción mínima permitida é {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>A imaxe é cadrada ({{ width }}x{{ height }}px). As imáxenes cadradas non están permitidas.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>A imaxe está orientada horizontalmente ({{ width }}x{{ height }}px). As imáxenes orientadas horizontalmente non están permitidas.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>A imaxe está orientada verticalmente ({{ width }}x{{ height }}px). As imáxenes orientadas verticalmente non están permitidas.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Non está permitido un arquivo baleiro.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Non se puido resolver o host.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>A codificación de caracteres para este valor debería ser {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Non é un Código de Identificación Bancaria (BIC) válido.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.he.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.he.xlf
new file mode 100644
index 0000000..6510514
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.he.xlf
@@ -0,0 +1,307 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>הערך צריך להיות שקר.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>הערך צריך להיות אמת.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>הערך צריך להיות מסוג {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>הערך צריך להיות ריק.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>הערך שבחרת אינו חוקי.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>אתה צריך לבחור לפחות {{ limit }} אפשרויות.|אתה צריך לבחור לפחות {{ limit }} אפשרויות.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.|אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>אחד או יותר מהערכים אינו חוקי.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>שדה זה לא היה צפוי</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>שדה זה חסר.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>הערך אינו תאריך חוקי.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>הערך אינו תאריך ושעה חוקיים.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>כתובת המייל אינה תקינה.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>הקובץ לא נמצא.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>לא ניתן לקרוא את הקובץ.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>הקובץ גדול מדי ({{ size }} {{ suffix }}). הגודל המרבי המותר הוא {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>סוג MIME של הקובץ אינו חוקי ({{ type }}). מותרים סוגי MIME {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>הערך צריל להכיל {{ limit }} תווים לכל היותר.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.|הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>הערך צריך להכיל {{ limit }} תווים לפחות.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.|הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>הערך לא אמור להיות ריק.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>הערך לא אמור להיות ריק.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>הערך צריך להיות ריק.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>הערך אינו חוקי.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>הערך אינו זמן תקין.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>זאת אינה כתובת אתר תקינה.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>שני הערכים צריכים להיות שווים.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>הקובץ גדול מדי. הגודל המרבי המותר הוא {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>הקובץ גדול מדי.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>לא ניתן לעלות את הקובץ.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>הערך צריך להיות מספר חוקי.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>הקובץ הזה אינו תמונה תקינה.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>זו אינה כתובת IP חוקית.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>הערך אינו שפה חוקית.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>הערך אינו אזור תקף.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>הערך אינו ארץ חוקית.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>הערך כבר בשימוש.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>לא ניתן לקבוע את גודל התמונה.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>רוחב התמונה גדול מדי ({{ width }}px). הרוחב המקסימלי הוא {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>רוחב התמונה קטן מדי ({{ width }}px). הרוחב המינימלי הוא {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>גובה התמונה גדול מדי ({{ height }}px). הגובה המקסימלי הוא {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>גובה התמונה קטן מדי ({{ height }}px). הגובה המינימלי הוא {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>הערך צריך להיות סיסמת המשתמש הנוכחי.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>הערך צריך להיות בדיוק {{ limit }} תווים.|הערך צריך להיות בדיוק {{ limit }} תווים.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>הקובץ הועלה באופן חלקי.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>הקובץ לא הועלה.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>לא הוגדרה תיקייה זמנית ב php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>לא ניתן לכתוב קובץ זמני לדיסק.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>סיומת PHP גרם להעלאה להיכשל.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>האוסף אמור להכיל {{ limit }} אלמנטים או יותר.|האוסף אמור להכיל {{ limit }} אלמנטים או יותר.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>האוסף אמור להכיל {{ limit }} אלמנטים או פחות.|האוסף אמור להכיל {{ limit }} אלמנטים או פחות.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.|האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>מספר הכרטיס אינו חוקי.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>סוג הכרטיס אינו נתמך או לא חוקי.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>This is not a valid International Bank Account Number (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>This value is not a valid ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>This value is not a valid ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>This value is neither a valid ISBN-10 nor a valid ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>This value is not a valid ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>This value is not a valid currency.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>This value should be equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>This value should be greater than {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>This value should be greater than or equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>This value should be less than {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>This value should be less than or equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>This value should not be equal to {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>An empty file is not allowed.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hr.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hr.xlf
new file mode 100644
index 0000000..126ef90
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hr.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Ova vrijednost treba biti netočna (false).</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Ova vrijednost treba biti točna (true).</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Ova vrijednost treba biti tipa {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Ova vrijednost treba biti prazna.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Ova vrijednost treba biti jedna od ponuđenih.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Izaberite barem {{ limit }} mogućnosti.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Izaberite najviše {{ limit }} mogućnosti.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Jedna ili više danih vrijednosti nije ispravna.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Ovo polje nije očekivalo.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ovo polje nedostaje.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Ova vrijednost nije ispravan datum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ova vrijednost nije ispravan datum-vrijeme.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Ova vrijednost nije ispravna e-mail adresa.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Datoteka ne može biti pronađena.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Datoteka nije čitljiva.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mime tip datoteke nije ispravan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Ova vrijednost treba biti {{ limit }} ili manje.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Ova vrijednost je predugačka. Treba imati {{ limit }} znakova ili manje.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Ova vrijednost treba biti {{ limit }} ili više.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Ova vrijednost je prekratka. Treba imati {{ limit }} znakova ili više.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ova vrijednost ne smije biti prazna.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Ova vrijednost ne smije biti null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Ova vrijednost treba biti null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Ova vrijednost nije ispravna.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ova vrijednost nije ispravno vrijeme.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Ova vrijednost nije ispravan URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Obje vrijednosti trebaju biti jednake.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Ova datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Ova datoteka je prevelika.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Ova datoteka ne može biti prenesena.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Ova vrijednost treba biti ispravan broj.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ova datoteka nije ispravna slika.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Ovo nije ispravna IP adresa.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Ova vrijednost nije ispravan jezik.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Ova vrijednost nije ispravana regionalna oznaka.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Ova vrijednost nije ispravna zemlja.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Ova vrijednost je već iskorištena.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Veličina slike se ne može odrediti.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Širina slike je prevelika ({{ width }}px). Najveća dozvoljena širina je {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Visina slike je prevelika ({{ height }}px). Najveća dozvoljena visina je {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Ova vrijednost treba biti trenutna korisnička lozinka.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Ova vrijednost treba imati točno {{ limit }} znakova.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Datoteka je samo djelomično prenesena.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Niti jedna datoteka nije prenesena.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>U php.ini datoteci nije konfiguriran privremeni folder.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Ne mogu zapisati privremenu datoteku na disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Prijenos datoteke nije uspio zbog PHP ekstenzije.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ova kolekcija treba sadržavati točno {{ limit }} element.|Ova kolekcija treba sadržavati točno {{ limit }} elementa.|Ova kolekcija treba sadržavati točno {{ limit }} elemenata.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Neispravan broj kartice.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Neispravan broj kartice ili tip kartice nije podržan.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Ova vrijednost nije ispravan međunarodni broj bankovnog računa (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ova vrijednost nije ispravan ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ova vrijednost nije ispravan ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ova vrijednost nije ispravan ISBN-10 niti ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ova vrijednost nije ispravan ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ova vrijednost nije ispravna valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ova vrijednost bi trebala biti jednaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ova vrijednost bi trebala biti veća od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ova vrijednost bi trebala biti veća ili jednaka od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ova vrijednost bi trebala biti {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ova vrijednost bi trebala biti manja od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ova vrijednost bi trebala biti manja ili jednaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ova vrijednost ne bi trebala biti {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ova vrijednost ne bi trebala biti {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Omjer slike je prevelik ({{ ratio }}). Dozvoljeni maksimalni omjer je {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Omjer slike je premali ({{ ratio }}). Minimalni očekivani omjer je {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Slika je kvadratnog oblika ({{ width }}x{{ height }}px). Kvadratne slike nisu dozvoljene.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Slika je orijentirana horizontalno ({{ width }}x{{ height }}px). Horizontalno orijentirane slike nisu dozvoljene.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Slika je orijentirana vertikalno ({{ width }}x{{ height }}px). Vertikalno orijentirane slike nisu dozvoljene.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Prazna datoteka nije dozvoljena.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Poslužitelj nije mogao biti razriješen.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Znakovne oznake vrijednosti ne odgovaraju očekivanom {{ charset }} skupu.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Ovo nije validan poslovni identifikacijski broj (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Greška</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hu.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hu.xlf
new file mode 100644
index 0000000..1011d54
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hu.xlf
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Ennek az értéknek hamisnak kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Ennek az értéknek igaznak kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Ennek az értéknek {{ type }} típusúnak kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Ennek az értéknek üresnek kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>A választott érték érvénytelen.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Legalább {{ limit }} értéket kell kiválasztani.|Legalább {{ limit }} értéket kell kiválasztani.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Legfeljebb {{ limit }} értéket lehet kiválasztani.|Legfeljebb {{ limit }} értéket lehet kiválasztani.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>A megadott értékek közül legalább egy érvénytelen.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Nem várt mező.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ez a mező hiányzik.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Ez az érték nem egy érvényes dátum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ez az érték nem egy érvényes időpont.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Ez az érték nem egy érvényes e-mail cím.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>A fájl nem található.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>A fájl nem olvasható.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>A fájl túl nagy ({{ size }} {{ suffix }}). A legnagyobb megengedett méret {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>A fájl MIME típusa érvénytelen ({{ type }}). Az engedélyezett MIME típusok: {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Ez az érték legfeljebb {{ limit }} lehet.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Ez az érték legalább {{ limit }} kell, hogy legyen.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.|Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ez az érték nem lehet üres.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Ez az érték nem lehet null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Ennek az értéknek nullnak kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Ez az érték nem érvényes.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ez az érték nem egy érvényes időpont.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Ez az érték nem egy érvényes URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>A két értéknek azonosnak kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>A fájl túl nagy. A megengedett maximális méret: {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>A fájl túl nagy.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>A fájl nem tölthető fel.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Ennek az értéknek érvényes számnak kell lennie.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ez a fájl nem egy érvényes kép.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Ez az érték nem egy érvényes IP cím.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Ez az érték nem egy érvényes nyelv.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Ez az érték nem egy érvényes területi beállítás.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Ez az érték nem egy érvényes ország.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Ez az érték már használatban van.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>A kép méretét nem lehet megállapítani.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>A kép szélessége túl nagy ({{ width }}px). A megengedett legnagyobb szélesség {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>A kép szélessége túl kicsi ({{ width }}px). Az elvárt legkisebb szélesség {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>A kép magassága túl nagy ({{ height }}px). A megengedett legnagyobb magasság {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>A kép magassága túl kicsi ({{ height }}px). Az elvárt legkisebb magasság {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Ez az érték a felhasználó jelenlegi jelszavával kell megegyezzen.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.|Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>A fájl csak részben lett feltöltve.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nem lett fájl feltöltve.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nincs ideiglenes könyvtár beállítva a php.ini-ben.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Az ideiglenes fájl nem írható a lemezre.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Egy PHP bővítmény miatt a feltöltés nem sikerült.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.|Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Érvénytelen kártyaszám.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nem támogatott kártyatípus vagy érvénytelen kártyaszám.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Érvénytelen nemzetközi bankszámlaszám (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ez az érték nem egy érvényes ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ez az érték nem egy érvényes ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ez az érték nem egy érvényes ISBN-10 vagy ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ez az érték nem egy érvényes ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ez az érték nem egy érvényes pénznem.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ez az érték legyen {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ez az érték nagyobb legyen, mint {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ez az érték nagyobb vagy egyenlő legyen, mint {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ez az érték ugyanolyan legyen, mint {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ez az érték kisebb legyen, mint {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ez az érték kisebb vagy egyenlő legyen, mint {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ez az érték ne legyen {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ez az érték ne legyen ugyanolyan, mint {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>A képarány túl nagy ({{ ratio }}). A megengedett legnagyobb képarány {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>A képarány túl kicsi ({{ ratio }}). A megengedett legkisebb képarány {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>A kép négyzet alakú ({{ width }}x{{ height }}px). A négyzet alakú képek nem engedélyezettek.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>A kép fekvő tájolású ({{ width }}x{{ height }}px). A fekvő tájolású képek nem engedélyezettek.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>A kép álló tájolású ({{ width }}x{{ height }}px). Az álló tájolású képek nem engedélyezettek.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Üres fájl nem megengedett.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Az állomásnevet nem lehet feloldani.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Ez az érték nem az elvárt {{ charset }} karakterkódolást használja.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Érvénytelen nemzetközi bankazonosító kód (BIC/SWIFT).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Hiba</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Érvénytelen egyedi azonosító (UUID).</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hy.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hy.xlf
new file mode 100644
index 0000000..bc0dace
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.hy.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Արժեքը պետք է լինի սխալ։</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Արժեքը պետք է լինի ճիշտ։</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Արժեքը պետք է լինի {{ type }} տեսակի։</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Արժեքը պետք է լինի դատարկ։</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Ձեր ընտրած արժեքը անվավեր ընտրություն է։</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Դուք պետք է ընտրեք ամենաքիչը {{ limit }} տարբերակներ։</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Դուք պետք է ընտրեք ոչ ավելի քան {{ limit }} տարբերակներ։</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Մեկ կամ ավելի տրված արժեքները անվավեր են։</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Այս դաշտը չի սպասվում։</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Այս դաշտը բացակայում է։</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Արժեքը սխալ ամսաթիվ է։</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ամսաթվի և ժամանակի արժեքը անվավեր է։</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Անվավեր էլ֊փոստի արժեք։</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Նիշքը չի գտնվել։</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Նիշքը անընթեռնելի է։</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Նիշքը չափազանց մեծ է ({{ size }} {{ suffix }}): Մաքսիմալ թույլատրելի չափսը՝ {{ limit }} {{ suffix }}։</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>MIME-տեսակը անվավեր է է({{ type }}): Նիշքերի թույլատրելի MIME-տեսակներն են: {{ types }}։</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Արժեքը պետք է լինի {{ limit }} կամ փոքր։</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Արժեքը չափազանց երկար է: Պետք է լինի {{ limit }} կամ ավել սիմվոլներ։</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Արժեքը պետ է լինի {{ limit }} կամ շատ։</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Արժեքը չափազանց կարճ է: Պետք է լինի {{ limit }} կամ ավելի սիմվոլներ։</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Արժեքը չպետք է դատարկ լինի։</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Արժեքը չպետք է լինի null։</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Արժեքը պետք է լինի null։</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Անվավեր արժեք։</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ժամանակի արժեքը անվավեր է։</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Արժեքը URL չէ։</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Երկու արժեքները պետք է նույնը լինեն։</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Նիշքը չափազանց մեծ է: Մաքսիմալ թույլատրելի չափսը {{ limit }} {{ suffix }} է։</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Նիշքը չափազանց մեծ է։</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Նիշքը չի կարող բեռնվել։</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Արժեքը պետք է լինի թիվ։</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This value is not a valid country.</source>
+ <target>Արժեքը պետք է լինի երկիր։</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This file is not a valid image.</source>
+ <target>Նիշքը նկարի վավեր ֆորմատ չէ։</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This is not a valid IP address.</source>
+ <target>Արժեքը վավեր IP հասցե չէ։</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid language.</source>
+ <target>Արժեքը վավեր լեզու չէ։</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid locale.</source>
+ <target>Արժեքը չի հանդիսանում վավեր տեղայնացում։</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Այդ արժեքն արդեն օգտագործվում է։</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Նկարի չափսերը չստացվեց որոշել։</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Նկարի լայնությունը չափազանց մեծ է({{ width }}px). Մաքսիմալ չափն է {{ max_width }}px։</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Նկարի լայնությունը չափազանց փոքր է ({{ width }}px). Մինիմալ չափն է {{ min_ width }}px։</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Նկարի բարձրությունը չափազանց մեծ է ({{ height }}px). Մաքսիմալ չափն է {{ max_height }}px։</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Նկարի բարձրությունը չափազանց փոքր է ({{ height }}px). Մինիմալ չափն է {{ min_height }}px։</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Այս արժեքը պետք է լինի օգտագործողի ներկա ծածկագիրը։</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Այս արժեքը պետք է ունենա ճիշտ {{ limit }} սիմվոլներ։</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Նիշքի մասնակի բեռնման սխալ։</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Նիշքը չի բեռնվել։</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>php.ini նիշքում ժամանակավոր պանակ նշված չէ։</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Ժամանակավոր նիշքը հնարավոր չէ գրել սկավառակի վրա։</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP ֆորմատը դարձել է բեռնման չհաջողման պատճառ։</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Այս հավաքածուն պետք է պաուրակի {{ limit }} կամ ավելի տարրեր։|Այս հավելվածը պետք է պարունակի limit }} տարր կամ ավելին։|Այս հավաքածուն պետք է պարունակի {{ limit }} տարրերին կամ ավելի։</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Այս հավաքածուն պետք է պաուրակի {{ limit }} տարրեր կամ քիչ։|Այս հավաքածուն պետք է պաուրակի {{ limit }} տարր կամ քիչ։|Այս հավաքածուն պետք է պաուրակի {{ limit }} տարրեր կամ քիչ։</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Այս հավաքածուն պետք է պաուրակի ուղիղ {{ limit }} տարր։|Այս հավաքածուն պետք է պաուրակի ուղիղ {{ limit }} տարրեր։|Այս հավաքածուն պետք է պաուրակի {{ limit }} տարրեր։</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Քարտի սխալ համար:</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Չսպասարկվող կամ սխալ քարտի համար:</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Արժեքը վավեր միջազային բանկային հաշվի համար չէ (IBAN)։</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Արժեքը ունի անվավեր ISBN-10 ձևաչափ։</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Արժեքը ունի անվավեր ISBN-13 ձևաչափ։</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Արժեքը չի համապատասխանում ISBN-10 և ISBN-13 ձևաչափերին։</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Արժեքը չի համապաստասխանում ISSN ձևաչափին։</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Արժեքը վավեր տարադրամ չէ։</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Արժեքը պետք է մեծ լինի, քան {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի հավասար կամ մեծ քան {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի ինչպես {{ compared_value_type }} {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի փոքր քան {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի փոքր կամ հավասար {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի հավասար {{ compared_value }}։</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Արժեքը պետք է լինի նունը {{ compared_value_type }} {{ compared_value }}:</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Պատկերի կողմերի հարաբերակցությունը խիստ մեծ է ({{ ratio }}). Մաքսիմալ հարաբերակցությունը՝ {{ max_ratio }}։</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Պատկերի կողմերի հարաբերակցությունը խիստ փոքր է ({{ ratio }}). Մինիմալ հարաբերակցությունը՝ {{ min_ratio }}։</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Պատկերը քառակուսի է({{ width }}x{{ height }}px)։ Քառակուսի նկարներ չեն թույլատրվում։</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Պատկերը ալբոմային ուղղվածության է({{ width }}x{{ height }}px)․ դա չի թույլատրվում։</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Պատկերը պորտրետային ուղղվածության է ({{ width }}x{{ height }}px)․ դա չի թույլատրվում։</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Դատարկ նիշք չի թույլատրվում։</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Հոսթի անունը հնարավոր չի պարզել:</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Արժեքը չի համընկնում {{ charset }} կոդավորման հետ:</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Սա վավեր Business Identifier Code (BIC) չէ։</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.id.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.id.xlf
new file mode 100644
index 0000000..535bdac
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.id.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Nilai ini harus bernilai salah.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Nilai ini harus bernilai benar.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Nilai ini harus bertipe {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Nilai ini harus kosong.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Nilai yang dipilih tidak tepat.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Anda harus memilih paling tidak {{ limit }} pilihan.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Anda harus memilih paling banyak {{ limit }} pilihan.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Satu atau lebih nilai yang diberikan tidak sah.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Ruas ini tidak diharapkan.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ruas ini hilang.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Nilai ini bukan merupakan tanggal yang sah.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Nilai ini bukan merupakan tanggal dan waktu yang sah.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Nilai ini bukan alamat surel yang sah.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Berkas tidak dapat ditemukan.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Berkas tidak dapat dibaca.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Ukuran berkas terlalu besar ({{ size }} {{ suffix }}). Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Jenis berkas ({{ type }}) tidak sah. Jenis berkas yang diizinkan adalah {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Nilai ini harus {{ limit }} atau kurang.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Nilai ini terlalu panjang. Seharusnya {{ limit }} karakter atau kurang.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Nilai ini harus {{ limit }} atau lebih.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Nilai ini terlalu pendek. Seharusnya {{ limit }} karakter atau lebih.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Nilai ini tidak boleh kosong.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Nilai ini tidak boleh 'null'.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Nilai ini harus 'null'.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Nilai ini tidak sah.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Nilai ini bukan merupakan waktu yang sah.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Nilai ini bukan URL yang sah.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Isi keduanya harus sama.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Ukuran berkas terlalu besar. Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Ukuran berkas terlalu besar.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Berkas tidak dapat diunggah.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Nilai ini harus angka yang sah.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Berkas ini tidak termasuk citra.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Ini bukan alamat IP yang sah.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Nilai ini bukan bahasa yang sah.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Nilai ini bukan lokal yang sah.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Nilai ini bukan negara yang sah.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Nilai ini sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Ukuran dari citra tidak bisa dideteksi.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Lebar citra terlalu besar ({{ width }}px). Ukuran lebar maksimum adalah {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Lebar citra terlalu kecil ({{ width }}px). Ukuran lebar minimum yang diharapkan adalah {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Tinggi citra terlalu besar ({{ height }}px). Ukuran tinggi maksimum adalah {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Tinggi citra terlalu kecil ({{ height }}px). Ukuran tinggi minimum yang diharapkan adalah {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Nilai ini harus kata sandi pengguna saat ini.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Nilai ini harus memiliki tepat {{ limit }} karakter.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Berkas hanya terunggah sebagian.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Tidak ada berkas terunggah.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Direktori sementara tidak dikonfiguasi pada php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Tidak dapat menuliskan berkas sementara ke dalam media penyimpanan.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Sebuah ekstensi PHP menyebabkan kegagalan unggah.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Kumpulan ini harus memiliki {{ limit }} elemen atau lebih.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Kumpulan ini harus memiliki kurang dari {{ limit }} elemen.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Kumpulan ini harus memiliki tepat {{ limit }} elemen.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Nomor kartu tidak sah.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Jenis kartu tidak didukung atau nomor kartu tidak sah.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Ini bukan Nomor Rekening Bank Internasional (IBAN) yang sah.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Nilai ini bukan ISBN-10 yang sah.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Nilai ini bukan ISBN-13 yang sah.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Nilai ini bukan ISBN-10 maupun ISBN-13 yang sah.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Nilai ini bukan ISSN yang sah.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Nilai ini bukan mata uang yang sah.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya sama dengan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya lebih dari {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya lebih dari atau sama dengan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya identik dengan {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya kurang dari {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya kurang dari atau sama dengan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya tidak sama dengan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Nilai ini seharusnya tidak identik dengan {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Rasio citra terlalu besar ({{ ratio }}). Rasio maksimum yang diizinkan adalah {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Rasio citra terlalu kecil ({{ ratio }}). Rasio minimum yang diharapkan adalah {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Citra persegi ({{ width }}x{{ height }}px). Citra persegi tidak diizinkan.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Citra berorientasi lanskap ({{ width }}x{{ height }}px). Citra berorientasi lanskap tidak diizinkan.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Citra berorientasi potret ({{ width }}x{{ height }}px). Citra berorientasi potret tidak diizinkan.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Berkas kosong tidak diizinkan.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Host tidak dapat diselesaikan.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Nilai ini tidak memenuhi set karakter {{ charset }} yang diharapkan.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Ini bukan Business Identifier Code (BIC) yang sah.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Galat</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.it.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.it.xlf
new file mode 100644
index 0000000..f195447
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.it.xlf
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Questo valore dovrebbe essere falso.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Questo valore dovrebbe essere vero.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Questo valore dovrebbe essere di tipo {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Questo valore dovrebbe essere vuoto.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Questo valore dovrebbe essere una delle opzioni disponibili.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Si dovrebbe selezionare almeno {{ limit }} opzione.|Si dovrebbero selezionare almeno {{ limit }} opzioni.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Si dovrebbe selezionare al massimo {{ limit }} opzione.|Si dovrebbero selezionare al massimo {{ limit }} opzioni.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Uno o più valori inseriti non sono validi.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Questo campo non è stato previsto.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Questo campo è mancante.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Questo valore non è una data valida.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Questo valore non è una data e ora valida.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Questo valore non è un indirizzo email valido.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Non è stato possibile trovare il file.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Il file non è leggibile.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Il file è troppo grande ({{ size }} {{ suffix }}). La dimensione massima consentita è {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Il mime type del file non è valido ({{ type }}). I tipi permessi sono {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Questo valore dovrebbe essere {{ limit }} o inferiore.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} carattere.|Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} caratteri.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Questo valore dovrebbe essere {{ limit }} o superiore.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} carattere.|Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} caratteri.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Questo valore non dovrebbe essere vuoto.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Questo valore non dovrebbe essere nullo.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Questo valore dovrebbe essere nullo.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Questo valore non è valido.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Questo valore non è un'ora valida.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Questo valore non è un URL valido.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>I due valori dovrebbero essere uguali.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Il file è troppo grande. La dimensione massima è {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Il file è troppo grande.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Il file non può essere caricato.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Questo valore dovrebbe essere un numero.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Questo file non è una immagine valida.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Questo valore non è un indirizzo IP valido.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Questo valore non è una lingua valida.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Questo valore non è una impostazione regionale valida.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Questo valore non è una nazione valida.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Questo valore è già stato utilizzato.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>La dimensione dell'immagine non può essere determinata.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>La larghezza dell'immagine è troppo grande ({{ width }}px). La larghezza massima è di {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>La larghezza dell'immagine è troppo piccola ({{ width }}px). La larghezza minima è di {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>L'altezza dell'immagine è troppo grande ({{ height }}px). L'altezza massima è di {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>L'altezza dell'immagine è troppo piccola ({{ height }}px). L'altezza minima è di {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Questo valore dovrebbe essere la password attuale dell'utente.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Questo valore dovrebbe contenere esattamente {{ limit }} carattere.|Questo valore dovrebbe contenere esattamente {{ limit }} caratteri.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Il file è stato caricato solo parzialmente.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nessun file è stato caricato.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nessuna cartella temporanea è stata configurata nel php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Impossibile scrivere il file temporaneo sul disco.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Un'estensione PHP ha causato il fallimento del caricamento.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Questa collezione dovrebbe contenere almeno {{ limit }} elemento.|Questa collezione dovrebbe contenere almeno {{ limit }} elementi.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Numero di carta non valido.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipo di carta non supportato o numero non valido.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Questo valore non è un IBAN (International Bank Account Number) valido.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Questo valore non è un codice ISBN-10 valido.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Questo valore non è un codice ISBN-13 valido.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Questo valore non è un codice ISBN-10 o ISBN-13 valido.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Questo valore non è un codice ISSN valido.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Questo valore non è una valuta valida.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere uguale a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere maggiore di {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere maggiore o uguale a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere identico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere minore di {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere minore o uguale a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere diverso da {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Questo valore dovrebbe essere diverso da {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Il rapporto di aspetto dell'immagine è troppo grande ({{ ratio }}). Il rapporto massimo consentito è {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Il rapporto di aspetto dell'immagine è troppo piccolo ({{ ratio }}). Il rapporto minimo consentito è {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>L'immagine è quadrata ({{ width }}x{{ height }}px). Le immagini quadrate non sono consentite.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>L'immagine è orizzontale ({{ width }}x{{ height }}px). Le immagini orizzontali non sono consentite.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>L'immagine è verticale ({{ width }}x{{ height }}px). Le immagini verticali non sono consentite.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Un file vuoto non è consentito.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>L'host non può essere risolto.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Questo valore non corrisponde al charset {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Questo valore non è un codice BIC valido.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Errore</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Questo non è un UUID valido.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ja.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ja.xlf
new file mode 100644
index 0000000..0c61d15
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ja.xlf
@@ -0,0 +1,331 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>falseでなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>trueでなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>型は{{ type }}でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>空でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>有効な選択肢ではありません。</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>{{ limit }}個以上選択してください。</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>{{ limit }}個以内で選択してください。</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>無効な選択肢が含まれています。</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>このフィールドは予期されていませんでした。</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>このフィールドは、欠落しています。</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>有効な日付ではありません。</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>有効な日時ではありません。</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>有効なメールアドレスではありません。</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>ファイルが見つかりません。</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>ファイルを読み込めません。</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>ファイルのMIMEタイプが無効です({{ type }})。有効なMIMEタイプは{{ types }}です。</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>{{ limit }}以下でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>値が長すぎます。{{ limit }}文字以内でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>{{ limit }}以上でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>値が短すぎます。{{ limit }}文字以上でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>空であってはなりません。</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>nullであってはなりません。</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>nullでなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>有効な値ではありません。</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>有効な時刻ではありません。</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>有効なURLではありません。</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>2つの値が同じでなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>ファイルのサイズが大きすぎます。有効な最大サイズは{{ limit }} {{ suffix }}です。</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>ファイルのサイズが大きすぎます。</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>ファイルをアップロードできませんでした。</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>有効な数字ではありません。</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>ファイルが画像ではありません。</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>有効なIPアドレスではありません。</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>有効な言語名ではありません。</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>有効なロケールではありません。</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>有効な国名ではありません。</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>既に使用されています。</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>画像のサイズが検出できません。</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>画像の幅が小さすぎます({{ width }}ピクセル)。{{ min_width }}ピクセル以上にしてください。</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>ユーザーの現在のパスワードでなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>ちょうど{{ limit }}文字でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>ファイルのアップロードは完全ではありません。</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>ファイルがアップロードされていません。</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>php.iniで一時フォルダが設定されていません。</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>一時ファイルをディスクに書き込むことができません。</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP拡張によってアップロードに失敗しました。</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>{{ limit }}個以上の要素を含んでなければいけません。</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>要素は{{ limit }}個までです。</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>要素はちょうど{{ limit }}個でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>無効なカード番号です。</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>未対応のカード種類又は無効なカード番号です。</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>有効なIBANコードではありません。</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>有効なISBN-10コードではありません。</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>有効なISBN-13コードではありません。</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>有効なISBN-10コード又はISBN-13コードではありません。</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>有効なISSNコードではありません。</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>有効な貨幣ではありません。</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>{{ compared_value }}と等しくなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>{{ compared_value }}より大きくなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>{{ compared_value }}以上でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>{{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>{{ compared_value }}未満でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>{{ compared_value }}以下でなければなりません。</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>{{ compared_value }}と等しくてはいけません。</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>{{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>画像のアスペクト比が大きすぎます({{ ratio }})。{{ max_ratio }}までにしてください。</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>画像のアスペクト比が小さすぎます({{ ratio }})。{{ min_ratio }}以上にしてください。</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>画像が正方形になっています({{ width }}x{{ height }}ピクセル)。正方形の画像は許可されていません。</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>画像が横向きになっています({{ width }}x{{ height }}ピクセル)。横向きの画像は許可されていません。</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>画像が縦向きになっています({{ width }}x{{ height }}ピクセル)。縦向きの画像は許可されていません。</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>空のファイルは許可されていません。</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>ホストを解決できませんでした。</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>この値は予期される文字コード({{ charset }})と異なります。</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>有効なSWIFTコードではありません。</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>エラー</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>有効なUUIDではありません。</target>
+ </trans-unit>
+ <trans-unit id="84">
+ <source>This value should be a multiple of {{ compared_value }}.</source>
+ <target>{{ compared_value }}の倍数でなければなりません。</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lb.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lb.xlf
new file mode 100644
index 0000000..bdbc9da
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lb.xlf
@@ -0,0 +1,327 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Dëse Wäert sollt falsch sinn.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Dëse Wäert sollt wouer sinn.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Dëse Wäert sollt vum Typ {{ type }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Dëse Wäert sollt eidel sinn.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Dëse Wäert sollt enger vun de Wielméiglechkeeten entspriechen.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Et muss mindestens {{ limit }} Méiglechkeet ausgewielt ginn.|Et musse mindestens {{ limit }} Méiglechkeeten ausgewielt ginn.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Et dierf héchstens {{ limit }} Méiglechkeet ausgewielt ginn.|Et dierfen héchstens {{ limit }} Méiglechkeeten ausgewielt ginn.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Een oder méi vun de Wäerter ass ongëlteg.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>The fields {{ fields }} were not expected.</source>
+ <target>D'Felder {{ fields }} goufen net erwaart.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>The fields {{ fields }} are missing.</source>
+ <target>D'Felder {{ fields }} feelen.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Dëse Wäert entsprécht kenger gëlteger Datumsangab.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Dëse Wäert entsprécht kenger gëlteger Datums- an Zäitangab.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Dëse Wäert ass keng gëlteg Email-Adress.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>De Fichier gouf net fonnt.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>De Fichier ass net liesbar.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>De Fichier ass ze grouss ({{ size }} {{ suffix }}). Déi zougeloosse Maximalgréisst bedréit {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Den Typ vum Fichier ass ongëlteg ({{ type }}). Erlaabten Type sinn {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Dëse Wäert soll méi kleng oder gläich {{ limit }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Dës Zeecheketten ass ze laang. Se sollt héchstens {{ limit }} Zeechen hunn.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Dëse Wäert sollt méi grouss oder gläich {{ limit }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Dës Zeecheketten ass ze kuerz. Se sollt mindestens {{ limit }} Zeechen hunn.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Dëse Wäert sollt net eidel sinn.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Dëst sollt keen Null-Wäert sinn.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Dëst sollt keen Null-Wäert sinn.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Dëse Wäert ass net gëlteg.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Dëse Wäert entsprécht kenger gëlteger Zäitangab.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Dëse Wäert ass keng gëlteg URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Béid Wäerter sollten identesch sinn.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>De fichier ass ze grouss. Déi maximal Gréisst dierf {{ limit }} {{ suffix }} net depasséieren.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>De Fichier ass ze grouss.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>De Fichier konnt net eropgeluede ginn.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Dëse Wäert sollt eng gëlteg Zuel sinn.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Dëse Fichier ass kee gëltegt Bild.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dëst ass keng gëlteg IP-Adress.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Dëse Wäert entsprécht kenger gëlteger Sprooch.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Dëse Wäert entsprécht kengem gëltege Gebittsschema.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Dëse Wäert entsprécht kengem gëltege Land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Dëse Wäert gëtt scho benotzt.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>D'Gréisst vum Bild konnt net detektéiert ginn.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>D'Breet vum Bild ass ze grouss ({{ width }}px). Déi erlaabte maximal Breet ass {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>D'Breet vum Bild ass ze kleng ({{ width }}px). Déi minimal Breet ass {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>D'Héicht vum Bild ass ze grouss ({{ height }}px). Déi erlaabte maximal Héicht ass {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>D'Héicht vum Bild ass ze kleng ({{ height }}px). Déi minimal Héicht ass {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Dëse Wäert sollt dem aktuelle Benotzerpasswuert entspriechen.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Dëse Wäert sollt exakt {{ limit }} Buschtaf hunn.|Dëse Wäert sollt exakt {{ limit }} Buschtawen hunn.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>De Fichier gouf just deelweis eropgelueden.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Et gouf kee Fichier eropgelueden.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Et gouf keen temporären Dossier an der php.ini konfiguréiert oder den temporären Dossier existéiert net.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Den temporäre Fichier kann net gespäichert ginn.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Eng PHP-Erweiderung huet den Upload verhënnert.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Dës Sammlung sollt {{ limit }} oder méi Elementer hunn.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Dës Sammlung sollt {{ limit }} oder manner Elementer hunn.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Dës Sammlung sollt exakt {{ limit }} Element hunn.|Dës Sammlung sollt exakt {{ limit }} Elementer hunn.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ongëlteg Kaartennummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Net ënnerstëtzte Kaartentyp oder ongëlteg Kaartennummer.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Dëst ass keng gëlteg IBAN-Kontonummer.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Dëse Wäert ass keng gëlteg ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Dëse Wäert ass keng gëlteg ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Dëse Wäert ass weder eng gëlteg ISBN-10 nach eng gëlteg ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Dëse Wäert ass keng gëlteg ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Dëse Wäert ass keng gëlteg Währung.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt {{ compared_value }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt méi grouss wéi {{ compared_value }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt méi grouss wéi oder gläich {{ compared_value }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt identesch si mat {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt méi kleng wéi {{ compared_value }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt méi kleng wéi oder gläich {{ compared_value }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt net {{ compared_value }} sinn.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Dëse Wäert sollt net identesch si mat {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>D'Säiteverhältnis vum Bild ass ze grouss ({{ ratio }}). Den erlaabte Maximalwäert ass {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>D'Säiteverhältnis vum Bild ass ze kleng ({{ ratio }}). Den erwaarte Minimalwäert ass {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>D'Bild ass quadratesch ({{ width }}x{{ height }}px). Quadratesch Biller sinn net erlaabt.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>D'Bild ass am Queeschformat ({{ width }}x{{ height }}px). Biller am Queeschformat sinn net erlaabt.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>D'Bild ass am Héichformat ({{ width }}x{{ height }}px). Biller am Héichformat sinn net erlaabt.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>En eidele Fichier ass net erlaabt.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Den Host-Numm konnt net opgeléist ginn.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Dëse Wäert entsprécht net dem erwaarten Zeechesaz {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Dëst ass kee gëltege "Business Identifier Code" (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Feeler</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Dëst ass keng gëlteg UUID.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lt.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lt.xlf
new file mode 100644
index 0000000..60641b5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lt.xlf
@@ -0,0 +1,311 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Reikšmė turi būti neigiama.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Reikšmė turi būti teigiama.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Šios reikšmės tipas turi būti {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Ši reikšmė turi būti tuščia.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Neteisingas pasirinkimas.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Turite pasirinkti bent {{ limit }} variantą.|Turite pasirinkti bent {{ limit }} variantus.|Turite pasirinkti bent {{ limit }} variantų.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Turite pasirinkti ne daugiau kaip {{ limit }} variantą.|Turite pasirinkti ne daugiau kaip {{ limit }} variantus.|Turite pasirinkti ne daugiau kaip {{ limit }} variantų.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Viena ar daugiau įvestų reikšmių yra netinkamos.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Nebuvo tikimasi Šis laukas.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Šiame lauke yra dingęs.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Ši reikšmė nėra data.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ši reikšmė nera data ir laikas.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Ši reikšmė nėra tinkamas el. pašto adresas.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Byla nerasta.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Negalima nuskaityti bylos.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Byla yra per didelė ({{ size }} {{ suffix }}). Maksimalus dydis {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Netinkamas bylos tipas (mime type) ({{ type }}). Galimi bylų tipai {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Reikšmė turi būti {{ limit }} arba mažiau.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Reikšmė turi būti {{ limit }} arba daugiau.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ši reikšmė negali būti tuščia.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Ši reikšmė negali būti null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Ši reikšmė turi būti null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Netinkama reikšmė.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ši reikšmė nėra laikas.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Ši reikšmė nėra tinkamas interneto adresas.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Abi reikšmės turi būti identiškos.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Byla yra per didelė. Maksimalus dydis yra {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Byla per didelė.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Byla negali būti įkelta.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Ši reikšmė turi būti skaičius.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This value is not a valid country.</source>
+ <target>Ši reikšmė nėra tinkama šalis.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This file is not a valid image.</source>
+ <target>Byla nėra paveikslėlis.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This is not a valid IP address.</source>
+ <target>Ši reikšmė nėra tinkamas IP adresas.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid language.</source>
+ <target>Ši reikšmė nėra tinkama kalba.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid locale.</source>
+ <target>Ši reikšmė nėra tinkama lokalė.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Ši reikšmė jau yra naudojama.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Nepavyko nustatyti nuotraukos dydžio.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Nuotraukos plotis per didelis ({{ width }}px). Maksimalus leidžiamas plotis yra {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Nuotraukos plotis per mažas ({{ width }}px). Minimalus leidžiamas plotis yra {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Nuotraukos aukštis per didelis ({{ height }}px). Maksimalus leidžiamas aukštis yra {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Nuotraukos aukštis per mažas ({{ height }}px). Minimalus leidžiamas aukštis yra {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Ši reikšmė turi sutapti su dabartiniu naudotojo slaptažodžiu.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Ši reikšmė turi turėti lygiai {{ limit }} simbolį.|Ši reikšmė turi turėti lygiai {{ limit }} simbolius.|Ši reikšmė turi turėti lygiai {{ limit }} simbolių.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Failas buvo tik dalinai įkeltas.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nebuvo įkelta jokių failų.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nėra sukonfiguruoto jokio laikino katalogo php.ini faile.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Nepavyko išsaugoti laikino failo.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP plėtinys sutrukdė failo įkėlimą ir jis nepavyko.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Sąraše turi būti lygiai {{ limit }} įrašas.|Sąraše turi būti lygiai {{ limit }} įrašai.|Sąraše turi būti lygiai {{ limit }} įrašų.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Klaidingas kortelės numeris.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Kortelės tipas nepalaikomas arba klaidingas kortelės numeris.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Ši reišmė neatitinka tarptautinio banko sąskaitos numerio formato (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ši reikšmė neatitinka ISBN-10 formato.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ši reikšmė neatitinka ISBN-13 formato.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ši reikšmė neatitinka nei ISBN-10, nei ISBN-13 formato.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ši reišmė neatitinka ISSN formato.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Netinkamas valiutos formatas.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ši reikšmė turi būti lygi {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ši reikšmė turi būti didesnė už {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ši reikšmė turi būti didesnė už arba lygi {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ši reikšmė turi būti identiška {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ši reikšmė turi būti mažesnė už {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ši reikšmė turi būti mažesnė už arba lygi {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ši reikšmė neturi būti lygi {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ši reikšmė neturi būti identiška {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Nuotraukos santykis yra per didelis ({{ ratio }}). Didžiausias leistinas santykis yra {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Nuotraukos santykis yra per mažas ({{ ratio }}). Mažiausias leistinas santykis yra {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Nuotrauka yra kvadratinė ({{ width }}x{{ height }}px). Kvadratinės nuotraukos nėra leistinos.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Nuotrauka orientuota į plotį ({{ width }}x{{ height }}px). Nuotraukos orientuotos į plotį nėra leistinos.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Nuotrauka orientuota į aukštį ({{ width }}x{{ height }}px). Nuotraukos orientuotos į aukštį nėra leistinos.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Failas negali būti tuščias.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Klaida</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lv.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lv.xlf
new file mode 100644
index 0000000..2ad19cd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.lv.xlf
@@ -0,0 +1,315 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Šai vērtībai ir jābūt nepatiesai.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Šai vērtībai ir jābūt patiesai.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Šīs vērtības tipam ir jābūt {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Šai vērtībai ir jābūt tukšai.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Vērtība, kuru jūs izvēlējāties nav derīga izvēle.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Jums nav jāveic izvēle.|Jums ir jāveic vismaz {{ limit }} izvēle.|Jums ir jāveic vismaz {{ limit }} izvēles.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Jums nav jāveic izvēle.|Jums ir jāveic ne vairāk kā {{ limit }} izvēle.|Jums ir jāveic ne vairāk kā {{ limit }} izvēles.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Viena vai vairākas no dotajām vērtībām ir nederīgas.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Šis lauks netika gaidīts.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Šis lauks ir pazudis.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Šī vērtība ir nederīgs datums.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Šī vērtība ir nederīgs datums un laiks</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Šī vērtība ir nederīga e-pasta adrese.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Fails nav atrasts.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Fails nav lasāms.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fails ir pārāk liels ({{ size }} {{ suffix }}). Atļautais maksimālais izmērs ir {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Faila mime tips nav derīgs ({{ type }}). Atļautie mime tipi ir {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Šai vērtībai ir jābūt ne vairāk kā {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Šīs vērtības garums ir 0 rakstzīmju.|Šī vērtība ir pārāk gara. Tai būtu jābūt ne vairāk kā {{ limit }} rakstzīmei.|Šī vērtība ir pārāk gara. Tai būtu jābūt ne vairāk kā {{ limit }} rakstzīmēm.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Šai vērtībai ir jābūt ne mazāk kā {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Šīs vērtības garums ir 0 rakstzīmju.|Šī vērtība ir pārāk īsa. Tai būtu jābūt ne mazāk kā {{ limit }} rakstzīmei.|Šī vērtība ir pārāk īsa. Tai būtu jābūt ne mazāk kā {{ limit }} rakstzīmēm.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Šai vērtībai nav jābūt tukšai.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Šai vērtībai nav jābūt null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Šai vērtībai ir jābūt null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Šī vērtība ir nederīga.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Šī vērtība ir nederīgs laiks.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Šī vērtība ir nederīgs URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Abām vērtībām jābūt vienādam.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fails ir pārāk liels. Atļautais maksimālais izmērs ir {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Fails ir pārāk liels.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Failu nevarēja augšupielādēt.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Šai vērtībai ir jābūt derīgam skaitlim.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Šis fails nav derīgs attēls.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Šī nav derīga IP adrese.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Šī vērtība nav derīga valoda.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Šī vērtība nav derīga lokalizācija.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Šī vērtība nav derīga valsts.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Šī vērtība jau tiek izmantota.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Nevar noteikt attēla izmēru.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Attēla platums ir pārāk liels ({{ width }}px). Atļautais maksimālais platums ir {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Attēla platums ir pārāk mazs ({{ width }}px). Minimālais sagaidāmais platums ir {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Attēla augstums ir pārāk liels ({{ height }}px). Atļautais maksimālais augstums ir {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Attēla augstums ir pārāk mazs ({{ height }}px). Minimālais sagaidāmais augstums ir {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Šai vērtībai ir jābūt lietotāja pašreizējai parolei.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Šīs vērtības garums ir 0 rakstzīmju.|Šai vērtībai ir jābūt tieši {{ limit }} rakstzīmei.|Šai vērtībai ir jābūt tieši {{ limit }} rakstzīmēm.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Fails bija tikai daļēji augšupielādēts.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Fails netika augšupielādēts.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Pagaidu mape php.ini failā nav nokonfigurēta.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Nevar ierakstīt pagaidu failu uz diska.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP paplašinājums izraisīja augšupielādes neizdošanos.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Šis krājums satur 0 elementu.|Šim krājumam jāsatur vismaz {{ limit }} elementu.|Šim krājumam jāsatur vismaz {{ limit }} elementus.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Šis krājums satur 0 elementu.|Šim krājumam jāsatur ne vairāk kā {{ limit }} elementu.|Šim krājumam jāsatur ne vairāk kā {{ limit }} elementus.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Šis krājums satur 0 elementu.|Šim krājumam jāsatur tieši {{ limit }} elementu.|Šim krājumam jāsatur tieši {{ limit }} elementus.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Nederīgs kartes numurs.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Neatbalstīts kartes tips vai nederīgs kartes numurs.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Šis nav derīgs starptautisks banku konta numurs (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Šī vērtība nav derīgs ISBN-10 numurs.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Šī vērtība nav derīgs ISBN-13 numurs</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Šī vērtība neatbilst ne derīgam ISBN-10 numuram, ne derīgm ISBN-13 numuram.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Šī vērtība nav derīgs ISSN numurs</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Šī vērtība nav derīga valūta</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Šai vērtībai ir jābūt vienādai ar {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Šai vērtībai ir jābūt lielākai par {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Šai vērtībai ir jābūt lielākai vai vienādai ar {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Šai vērtībai ir jābūt identiskai ar {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Šai vērtībai ir jābūt mazākai par {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>TŠai vērtībai ir jābūt mazākai vai vienādai ar {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Šai vērtībai ir jābūt vienādai ar {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Šai vērtībai nav jābūt identiskai ar {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Attēla attiecība ir pārāk liela ({{ ratio }}). Atļautā maksimālā attiecība ir {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Attēla attiecība ir pārāk maza ({{ ratio }}). Minimālā sagaidāmā attiecība ir {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Šis attēls ir kvadrāts ({{ width }}x{{ height }}px). Kvadrātveida attēli nav atļauti.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Attēls ir orientēts kā ainava ({{ width }}x{{ height }}px). Attēli, kas ir orientēti kā ainavas nav atļauti.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Attēls ir orientēts kā portrets ({{ width }}x{{ height }}px). Attēli, kas ir orientēti kā portreti nav atļauti.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Tukšs fails nav atļauts.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Resursdatora nosaukumu nevar atrisināt.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Šī vērtība neatbilst sagaidāmajai rakstzīmju kopai {{ charset }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.mn.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.mn.xlf
new file mode 100644
index 0000000..4be2198
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.mn.xlf
@@ -0,0 +1,151 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Энэ утга буруу байх ёстой.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Энэ утга үнэн байх ёстой.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Энэ утга {{ type }} -н төрөл байх ёстой.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Энэ утга хоосон байх ёстой.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Сонгосон утга буруу байна.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Хамгийн багадаа {{ limit }} утга сонгогдсон байх ёстой.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Хамгийн ихдээ {{ limit }} утга сонгогдох боломжтой.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Өгөгдсөн нэг эсвэл нэгээс олон утга буруу байна.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Энэ талбар нь хүлээгдэж байсан юм.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Энэ талбар нь алга болсон байна.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Энэ утга буруу date төрөл байна .</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Энэ утга буруу цаг төрөл байна.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>И-майл хаяг буруу байна.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Файл олдсонгүй.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Файл уншигдахуйц биш байна.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файл хэтэрхий том байна ({{ size }} {{ suffix }}). Зөвшөөрөгдөх дээд хэмжээ {{ limit }} {{ suffix }} байна.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Файлын MIME-төрөл нь буруу байна ({{ type }}). Зөвшөөрөгдөх MIME-төрлүүд {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Энэ утга {{ limit }} юмуу эсвэл бага байна.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Энэ утга хэтэрхий урт байна. {{ limit }} тэмдэгтийн урттай юмуу эсвэл бага байна.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Энэ утга {{ limit }} юмуу эсвэл их байна.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Энэ утга хэтэрхий богино байна. {{ limit }} тэмдэгт эсвэл их байна.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Энэ утга хоосон байж болохгүй.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Энэ утга null байж болохгүй.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Энэ утга null байна.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Энэ утга буруу байна.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Энэ утга буруу цаг төрөл байна.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Энэ утга буруу URL байна .</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Хоёр утгууд ижил байх ёстой.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файл хэтэрхий том байна. Зөвшөөрөгдөх дээд хэмжээ нь {{ limit }} {{ suffix }} байна.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Файл хэтэрхий том байна.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Файл upload хийгдсэнгүй.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Энэ утга зөвхөн тоо байна.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This value is not a valid country.</source>
+ <target>Энэ утга үнэн бодит улс биш байна.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This file is not a valid image.</source>
+ <target>Файл зураг биш байна.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This is not a valid IP address.</source>
+ <target>IP хаяг зөв биш байна.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid language.</source>
+ <target>Энэ утга үнэн зөв хэл биш байна .</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nb.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nb.xlf
new file mode 100644
index 0000000..2505765
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nb.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Verdien må være usann.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Verdien må være sann.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Verdien skal ha typen {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Verdien skal være blank.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Den valgte verdien er ikke gyldig.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Du må velge minst {{ limit }} valg.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Du kan maks velge {{ limit }} valg.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>En eller flere av de oppgitte verdiene er ugyldige.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Dette feltet var ikke forventet.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Dette feltet mangler.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Verdien er ikke en gyldig dato.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Verdien er ikke en gyldig dato/tid.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Verdien er ikke en gyldig e-postadresse.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Filen kunne ikke finnes.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Filen er ikke lesbar.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Verdien må være {{ limit }} tegn lang eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Verdien er for lang. Den må ha {{ limit }} tegn eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Verdien må være {{ limit }} eller mer.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Verdien er for kort. Den må ha {{ limit }} tegn eller flere.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Verdien kan ikke være blank.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Verdien kan ikke være tom (null).</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Verdien skal være tom (null).</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Verdien er ugyldig.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Verdien er ikke en gyldig tid.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Verdien er ikke en gyldig URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Verdiene skal være identiske.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen er for stor. Den maksimale størrelsen er {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Filen er for stor.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Filen kunne ikke lastes opp.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Verdien skal være et gyldig tall.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Denne filen er ikke et gyldig bilde.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dette er ikke en gyldig IP adresse.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Verdien er ikke et gyldig språk.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Verdien er ikke en gyldig lokalitet.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Verdien er ikke et gyldig navn på land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Verdien er allerede brukt.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Bildestørrelsen kunne ikke oppdages.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Bildebredden er for stor ({{ width }} piksler). Tillatt maksimumsbredde er {{ max_width }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Bildebredden er for liten ({{ width }} piksler). Forventet minimumsbredde er {{ min_width }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Bildehøyden er for stor ({{ height }} piksler). Tillatt maksimumshøyde er {{ max_height }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Bildehøyden er for liten ({{ height }} piksler). Forventet minimumshøyde er {{ min_height }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Verdien skal være brukerens sitt nåværende passord.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Verdien skal være nøyaktig {{ limit }} tegn.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Filen var kun delvis opplastet.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ingen fil var lastet opp.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Den midlertidige mappen (tmp) er ikke konfigurert i php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan ikke skrive midlertidig fil til disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>En PHP-utvidelse forårsaket en feil under opplasting.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Denne samlingen må inneholde {{ limit }} element eller flere.|Denne samlingen må inneholde {{ limit }} elementer eller flere.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Denne samlingen må inneholde {{ limit }} element eller færre.|Denne samlingen må inneholde {{ limit }} elementer eller færre.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Denne samlingen må inneholde nøyaktig {{ limit }} element.|Denne samlingen må inneholde nøyaktig {{ limit }} elementer.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ugyldig kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Korttypen er ikke støttet eller kortnummeret er ugyldig.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Dette er ikke et gyldig IBAN-nummer.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Verdien er ikke en gyldig ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Verdien er ikke en gyldig ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Verdien er hverken en gyldig ISBN-10 eller ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Verdien er ikke en gyldig ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Verdien er ikke gyldig valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Verdien skal være lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Verdien skal være større enn {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Verdien skal være større enn eller lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Verdien skal være identisk med {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Verdien skal være mindre enn {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Verdien skal være mindre enn eller lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Verdien skal ikke være lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Verdien skal ikke være identisk med {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Bildeforholdet er for stort ({{ ratio }}). Tillatt bildeforhold er maks {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Bildeforholdet er for lite ({{ ratio }}). Forventet bildeforhold er minst {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Bildet er en kvadrat ({{ width }}x{{ height }}px). Kvadratiske bilder er ikke tillatt.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Bildet er i liggende retning ({{ width }}x{{ height }}px). Bilder i liggende retning er ikke tillatt.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Bildet er i stående retning ({{ width }}x{{ height }}px). Bilder i stående retning er ikke tillatt.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Tomme filer er ikke tilatt.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Vertsnavn kunne ikke løses.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Verdien samsvarer ikke med forventet tegnsett {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Dette er ikke en gyldig BIC.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nl.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nl.xlf
new file mode 100644
index 0000000..bee0ab3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nl.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Deze waarde moet onwaar zijn.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Deze waarde moet waar zijn.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Deze waarde moet van het type {{ type }} zijn.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Deze waarde moet leeg zijn.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>De geselecteerde waarde is geen geldige optie.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Selecteer ten minste {{ limit }} optie.|Selecteer ten minste {{ limit }} opties.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Selecteer maximaal {{ limit }} optie.|Selecteer maximaal {{ limit }} opties.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Eén of meer van de ingegeven waarden zijn ongeldig.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Dit veld werd niet verwacht.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Dit veld ontbreekt.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Deze waarde is geen geldige datum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Deze waarde is geen geldige datum en tijd.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Deze waarde is geen geldig e-mailadres.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Het bestand kon niet gevonden worden.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Het bestand is niet leesbaar.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Het bestand is te groot ({{ size }} {{ suffix }}). Toegestane maximum grootte is {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Het mime type van het bestand is ongeldig ({{ type }}). Toegestane mime types zijn {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Deze waarde moet {{ limit }} of minder zijn.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Deze waarde is te lang. Hij mag maximaal {{ limit }} teken bevatten.|Deze waarde is te lang. Hij mag maximaal {{ limit }} tekens bevatten.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Deze waarde moet {{ limit }} of meer zijn.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Deze waarde is te kort. Hij moet tenminste {{ limit }} teken bevatten.|Deze waarde is te kort. Hij moet tenminste {{ limit }} tekens bevatten.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Deze waarde mag niet leeg zijn.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Deze waarde mag niet null zijn.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Deze waarde moet null zijn.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Deze waarde is niet geldig.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Deze waarde is geen geldige tijd.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Deze waarde is geen geldige URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>De twee waarden moeten gelijk zijn.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Het bestand is te groot. Toegestane maximum grootte is {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Het bestand is te groot.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Het bestand kon niet worden geüpload.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Deze waarde moet een geldig getal zijn.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Dit bestand is geen geldige afbeelding.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dit is geen geldig IP-adres.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Deze waarde is geen geldige taal.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Deze waarde is geen geldige locale.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Deze waarde is geen geldig land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Deze waarde wordt al gebruikt.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>De grootte van de afbeelding kon niet bepaald worden.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>De afbeelding is te breed ({{ width }}px). De maximaal toegestane breedte is {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>De afbeelding is niet breed genoeg ({{ width }}px). De minimaal verwachte breedte is {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>De afbeelding is te hoog ({{ height }}px). De maximaal toegestane hoogte is {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>De afbeelding is niet hoog genoeg ({{ height }}px). De minimaal verwachte hoogte is {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Deze waarde moet het huidige wachtwoord van de gebruiker zijn.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Deze waarde moet exact {{ limit }} teken lang zijn.|Deze waarde moet exact {{ limit }} tekens lang zijn.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Het bestand is slechts gedeeltelijk geüpload.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Er is geen bestand geüpload.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Er is geen tijdelijke map geconfigureerd in php.ini, of de gespecificeerde map bestaat niet.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan het tijdelijke bestand niet wegschrijven op disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>De upload is mislukt vanwege een PHP-extensie.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Deze collectie moet {{ limit }} element of meer bevatten.|Deze collectie moet {{ limit }} elementen of meer bevatten.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ongeldig creditcardnummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Niet-ondersteund type creditcard of ongeldig nummer.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Dit is geen geldig internationaal bankrekeningnummer (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Deze waarde is geen geldige ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Deze waarde is geen geldige ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Deze waarde is geen geldige ISBN-10 of ISBN-13 waarde.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Deze waarde is geen geldige ISSN waarde.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Deze waarde is geen geldige valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Deze waarde moet gelijk zijn aan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Deze waarde moet groter zijn dan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Deze waarde moet groter dan of gelijk aan {{ compared_value }} zijn.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Deze waarde moet identiek zijn aan {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Deze waarde moet minder zijn dan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Deze waarde moet minder dan of gelijk aan {{ compared_value }} zijn.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Deze waarde mag niet gelijk zijn aan {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Deze waarde mag niet identiek zijn aan {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>De afbeeldingsverhouding is te groot ({{ ratio }}). Maximale verhouding is {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>De afbeeldingsverhouding is te klein ({{ ratio }}). Minimale verhouding is {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>De afbeelding is vierkant ({{ width }}x{{ height }}px). Vierkante afbeeldingen zijn niet toegestaan.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>De afbeelding is liggend ({{ width }}x{{ height }}px). Liggende afbeeldingen zijn niet toegestaan.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>De afbeelding is staand ({{ width }}x{{ height }}px). Staande afbeeldingen zijn niet toegestaan.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Lege bestanden zijn niet toegestaan.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Deze waarde is niet in de verwachte tekencodering {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Dit is geen geldige bedrijfsidentificatiecode (BIC/SWIFT).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Fout</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>Dit is geen geldige UUID.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nn.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nn.xlf
new file mode 100644
index 0000000..e588133
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.nn.xlf
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Verdien skulle ha vore tom/nei.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Verdien skulla ha vore satt/ja.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Verdien må vere av typen {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Verdien skal vere blank.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Verdien du valde er ikkje gyldig.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Du må gjere minst {{ limit }} val.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Du kan maksimalt gjere {{ limit }} val.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Ein eller fleire av dei opplyste verdiane er ugyldige.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Dette feltet var ikke forventa.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Dette feltet mangler.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Verdien er ikkje ein gyldig dato.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Verdien er ikkje ein gyldig dato og tid.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Verdien er ikkje ei gyldig e-postadresse.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Fila er ikkje funnen.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Fila kan ikkje lesast.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fila er for stor ({{ size }} {{ suffix }}). Maksimal storleik er {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mime-typen av fila er ugyldig ({{ type }}). Tillatne mime-typar er {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Verdien må vere {{ limit }} eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Verdien må vere {{ limit }} eller meir.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Verdien er for kort. Den må ha {{ limit }} teikn eller fleire.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Verdien kan ikkje vere blank.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Verdien kan ikkje vere tom (null).</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Verdien må vere tom (null).</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Verdien er ikkje gyldig.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Verdien er ikkje ei gyldig tidseining.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Verdien er ikkje ein gyldig URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Dei to verdiane må vere like.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fila er for stor. Den maksimale storleiken er {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Fila er for stor.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Fila kunne ikkje bli lasta opp.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Verdien må vere eit gyldig tal.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Fila er ikkje eit gyldig bilete.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dette er ikkje ei gyldig IP-adresse.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Verdien er ikkje eit gyldig språk.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Verdien er ikkje ein gyldig lokalitet (språk/region).</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Verdien er ikkje eit gyldig land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Verdien er allereie i bruk.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Storleiken på biletet kunne ikkje oppdagast.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Biletbreidda er for stor, ({{ width }} pikslar). Tillaten maksimumsbreidde er {{ max_width }} pikslar.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Bilethøgda er for stor, ({{ height }} pikslar). Tillaten maksimumshøgde er {{ max_height }} pikslar.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Verdien må vere brukaren sitt noverande passord.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Verdien må vere nøyaktig {{ limit }} teikn.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Fila vart berre delvis lasta opp.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Inga fil vart lasta opp.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Førebels mappe (tmp) er ikkje konfigurert i php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan ikkje skrive førebels fil til disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Ei PHP-udviding forårsaka feil under opplasting.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ugyldig kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Korttypen er ikkje støtta, eller kortnummeret er ugyldig.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.no.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.no.xlf
new file mode 100644
index 0000000..2505765
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.no.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Verdien må være usann.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Verdien må være sann.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Verdien skal ha typen {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Verdien skal være blank.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Den valgte verdien er ikke gyldig.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Du må velge minst {{ limit }} valg.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Du kan maks velge {{ limit }} valg.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>En eller flere av de oppgitte verdiene er ugyldige.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Dette feltet var ikke forventet.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Dette feltet mangler.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Verdien er ikke en gyldig dato.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Verdien er ikke en gyldig dato/tid.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Verdien er ikke en gyldig e-postadresse.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Filen kunne ikke finnes.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Filen er ikke lesbar.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Verdien må være {{ limit }} tegn lang eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Verdien er for lang. Den må ha {{ limit }} tegn eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Verdien må være {{ limit }} eller mer.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Verdien er for kort. Den må ha {{ limit }} tegn eller flere.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Verdien kan ikke være blank.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Verdien kan ikke være tom (null).</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Verdien skal være tom (null).</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Verdien er ugyldig.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Verdien er ikke en gyldig tid.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Verdien er ikke en gyldig URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Verdiene skal være identiske.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen er for stor. Den maksimale størrelsen er {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Filen er for stor.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Filen kunne ikke lastes opp.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Verdien skal være et gyldig tall.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Denne filen er ikke et gyldig bilde.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Dette er ikke en gyldig IP adresse.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Verdien er ikke et gyldig språk.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Verdien er ikke en gyldig lokalitet.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Verdien er ikke et gyldig navn på land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Verdien er allerede brukt.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Bildestørrelsen kunne ikke oppdages.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Bildebredden er for stor ({{ width }} piksler). Tillatt maksimumsbredde er {{ max_width }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Bildebredden er for liten ({{ width }} piksler). Forventet minimumsbredde er {{ min_width }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Bildehøyden er for stor ({{ height }} piksler). Tillatt maksimumshøyde er {{ max_height }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Bildehøyden er for liten ({{ height }} piksler). Forventet minimumshøyde er {{ min_height }} piksler.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Verdien skal være brukerens sitt nåværende passord.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Verdien skal være nøyaktig {{ limit }} tegn.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Filen var kun delvis opplastet.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ingen fil var lastet opp.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Den midlertidige mappen (tmp) er ikke konfigurert i php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan ikke skrive midlertidig fil til disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>En PHP-utvidelse forårsaket en feil under opplasting.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Denne samlingen må inneholde {{ limit }} element eller flere.|Denne samlingen må inneholde {{ limit }} elementer eller flere.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Denne samlingen må inneholde {{ limit }} element eller færre.|Denne samlingen må inneholde {{ limit }} elementer eller færre.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Denne samlingen må inneholde nøyaktig {{ limit }} element.|Denne samlingen må inneholde nøyaktig {{ limit }} elementer.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ugyldig kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Korttypen er ikke støttet eller kortnummeret er ugyldig.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Dette er ikke et gyldig IBAN-nummer.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Verdien er ikke en gyldig ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Verdien er ikke en gyldig ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Verdien er hverken en gyldig ISBN-10 eller ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Verdien er ikke en gyldig ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Verdien er ikke gyldig valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Verdien skal være lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Verdien skal være større enn {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Verdien skal være større enn eller lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Verdien skal være identisk med {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Verdien skal være mindre enn {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Verdien skal være mindre enn eller lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Verdien skal ikke være lik {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Verdien skal ikke være identisk med {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Bildeforholdet er for stort ({{ ratio }}). Tillatt bildeforhold er maks {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Bildeforholdet er for lite ({{ ratio }}). Forventet bildeforhold er minst {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Bildet er en kvadrat ({{ width }}x{{ height }}px). Kvadratiske bilder er ikke tillatt.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Bildet er i liggende retning ({{ width }}x{{ height }}px). Bilder i liggende retning er ikke tillatt.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Bildet er i stående retning ({{ width }}x{{ height }}px). Bilder i stående retning er ikke tillatt.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Tomme filer er ikke tilatt.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Vertsnavn kunne ikke løses.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Verdien samsvarer ikke med forventet tegnsett {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Dette er ikke en gyldig BIC.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pl.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pl.xlf
new file mode 100644
index 0000000..e7ad1ec
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pl.xlf
@@ -0,0 +1,331 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Ta wartość powinna być fałszem.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Ta wartość powinna być prawdą.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Ta wartość powinna być typu {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Ta wartość powinna być pusta.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Ta wartość powinna być jedną z podanych opcji.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Powinieneś wybrać co najmniej {{ limit }} opcję.|Powinieneś wybrać co najmniej {{ limit }} opcje.|Powinieneś wybrać co najmniej {{ limit }} opcji.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Powinieneś wybrać maksymalnie {{ limit }} opcję.|Powinieneś wybrać maksymalnie {{ limit }} opcje.|Powinieneś wybrać maksymalnie {{ limit }} opcji.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Jedna lub więcej z podanych wartości jest nieprawidłowa.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Tego pola się nie spodziewano.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Tego pola brakuje.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Ta wartość nie jest prawidłową datą.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ta wartość nie jest prawidłową datą i czasem.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Ta wartość nie jest prawidłowym adresem email.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Plik nie mógł zostać odnaleziony.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Nie można odczytać pliku.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Plik jest za duży ({{ size }} {{ suffix }}). Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Nieprawidłowy typ mime pliku ({{ type }}). Dozwolone typy mime to {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Ta wartość powinna wynosić {{ limit }} lub mniej.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Ta wartość powinna wynosić {{ limit }} lub więcej.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ta wartość nie powinna być pusta.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Ta wartość nie powinna być nullem.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Ta wartość powinna być nullem.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Ta wartość jest nieprawidłowa.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ta wartość nie jest prawidłowym czasem.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Ta wartość nie jest prawidłowym adresem URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Obie wartości powinny być równe.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Plik jest za duży. Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Plik jest za duży.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Plik nie mógł być wgrany.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Ta wartość powinna być prawidłową liczbą.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ten plik nie jest obrazem.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>To nie jest prawidłowy adres IP.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Ta wartość nie jest prawidłowym językiem.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Ta wartość nie jest prawidłową lokalizacją.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Ta wartość nie jest prawidłową nazwą kraju.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Ta wartość jest już wykorzystywana.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Nie można wykryć rozmiaru obrazka.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Szerokość obrazka jest zbyt duża ({{ width }}px). Maksymalna dopuszczalna szerokość to {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Szerokość obrazka jest zbyt mała ({{ width }}px). Oczekiwana minimalna szerokość to {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Wysokość obrazka jest zbyt duża ({{ height }}px). Maksymalna dopuszczalna wysokość to {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Wysokość obrazka jest zbyt mała ({{ height }}px). Oczekiwana minimalna wysokość to {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Ta wartość powinna być aktualnym hasłem użytkownika.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Ta wartość powinna mieć dokładnie {{ limit }} znak.|Ta wartość powinna mieć dokładnie {{ limit }} znaki.|Ta wartość powinna mieć dokładnie {{ limit }} znaków.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Plik został wgrany tylko częściowo.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Żaden plik nie został wgrany.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nie skonfigurowano folderu tymczasowego w php.ini, lub skonfigurowany folder nie istnieje.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Nie można zapisać pliku tymczasowego na dysku.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Rozszerzenie PHP spowodowało błąd podczas wgrywania.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ten zbiór powinien zawierać {{ limit }} lub więcej elementów.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ten zbiór powinien zawierać {{ limit }} lub mniej elementów.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ten zbiór powinien zawierać dokładnie {{ limit }} element.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementy.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementów.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Nieprawidłowy numer karty.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nieobsługiwany rodzaj karty lub nieprawidłowy numer karty.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Nieprawidłowy międzynarodowy numer rachunku bankowego (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ta wartość nie jest prawidłowym numerem ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ta wartość nie jest prawidłowym numerem ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ta wartość nie jest prawidłowym numerem ISBN-10 ani ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ta wartość nie jest prawidłowym numerem ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ta wartość nie jest prawidłową walutą.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ta wartość powinna być równa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ta wartość powinna być większa niż {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ta wartość powinna być większa bądź równa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ta wartość powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ta wartość powinna być mniejsza niż {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ta wartość powinna być mniejsza bądź równa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ta wartość nie powinna być równa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ta wartość nie powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Proporcje obrazu są zbyt duże ({{ ratio }}). Maksymalne proporcje to {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Proporcje obrazu są zbyt małe ({{ ratio }}). Minimalne proporcje to {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Obraz jest kwadratem ({{ width }}x{{ height }}px). Kwadratowe obrazy nie są akceptowane.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Obraz jest panoramiczny ({{ width }}x{{ height }}px). Panoramiczne zdjęcia nie są akceptowane.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Obraz jest portretowy ({{ width }}x{{ height }}px). Portretowe zdjęcia nie są akceptowane.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Plik nie może być pusty.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Nazwa hosta nie została rozpoznana.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Ta wartość nie pasuje do oczekiwanego zestawu znaków {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Ta wartość nie jest poprawnym kodem BIC (Business Identifier Code).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Błąd</target>
+ </trans-unit>
+ <trans-unit id="83">
+ <source>This is not a valid UUID.</source>
+ <target>To nie jest poprawne UUID.</target>
+ </trans-unit>
+ <trans-unit id="84">
+ <source>This value should be a multiple of {{ compared_value }}.</source>
+ <target>Ta wartość powinna być wielokrotnością {{ compared_value }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt.xlf
new file mode 100644
index 0000000..0561c04
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt.xlf
@@ -0,0 +1,311 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Este valor deveria ser falso.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Este valor deveria ser verdadeiro.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Este valor deveria ser do tipo {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Este valor deveria ser vazio.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>O valor selecionado não é uma opção válida.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Você deveria selecionar {{ limit }} opção no mínimo.|Você deveria selecionar {{ limit }} opções no mínimo.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Você deve selecionar, no máximo {{ limit }} opção.|Você deve selecionar, no máximo {{ limit }} opções.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Um ou mais dos valores introduzidos não são válidos.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Este campo não era esperado.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Este campo está faltando.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Este valor não é uma data válida.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Este valor não é uma data-hora válida.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Este valor não é um endereço de e-mail válido.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>O arquivo não pôde ser encontrado.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>O arquivo não pôde ser lido.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Este valor deveria ser {{ limit }} ou menor.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>O valor é muito longo. Deveria ter {{ limit }} caracteres ou menos.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Este valor deveria ser {{ limit }} ou mais.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>O valor é muito curto. Deveria de ter {{ limit }} caractere ou mais.|O valor é muito curto. Deveria de ter {{ limit }} caracteres ou mais.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Este valor não deveria ser branco/vazio.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Este valor não deveria ser nulo.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Este valor deveria ser nulo.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Este valor não é válido.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Este valor não é uma hora válida.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Este valor não é um URL válido.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Os dois valores deveriam ser iguais.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>O ficheiro é muito grande.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Não foi possível carregar o ficheiro.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Este valor deveria de ser um número válido.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Este ficheiro não é uma imagem.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Este endereço de IP não é válido.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Este valor não é uma linguagem válida.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Este valor não é um 'locale' válido.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Este valor não é um País válido.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Este valor já está a ser usado.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>O tamanho da imagem não foi detetado.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>A largura da imagem ({{ width }}px) é muito grande. A largura máxima da imagem é: {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>A largura da imagem ({{ width }}px) é muito pequena. A largura miníma da imagem é de: {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>A altura da imagem ({{ height }}px) é muito grande. A altura máxima da imagem é de: {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>A altura da imagem ({{ height }}px) é muito pequena. A altura miníma da imagem é de: {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Este valor deveria de ser a password atual do utilizador.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Este valor tem de ter exatamente {{ limit }} carateres.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Só foi enviado parte do ficheiro.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nenhum ficheiro foi enviado.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Não existe nenhum directório temporária configurado no ficheiro php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Não foi possível escrever ficheiros temporários no disco.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Uma extensão PHP causou a falha no envio.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Número de cartão inválido.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipo de cartão não suportado ou número de cartão inválido.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Este não é um Número Internacional de Conta Bancária (IBAN) válido.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Este valor não é um ISBN-10 válido.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Este valor não é um ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Este valor não é um ISBN-10 ou ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Este valor não é um ISSN válido.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Este não é um valor monetário válido.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Este valor deve ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Este valor deve ser superior a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Este valor deve ser igual ou superior a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Este valor deve ser inferior a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Este valor deve ser igual ou inferior a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Este valor não deve ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>O formato da imagem é muito grande ({{ ratio }}). O formato máximo é {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>O formato da imagem é muito pequeno ({{ ratio }}). O formato mínimo esperado é {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>A imagem é um quadrado ({{ width }}x{{ height }}px). Imagens quadradas não são permitidas.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>A imagem está orientada à paisagem ({{ width }}x{{ height }}px). Imagens orientadas à paisagem não são permitidas.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>A imagem está orientada ao retrato ({{ width }}x{{ height }}px). Imagens orientadas ao retrato não são permitidas.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Ficheiro vazio não é permitido.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Erro</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt_BR.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt_BR.xlf
new file mode 100644
index 0000000..b617062
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.pt_BR.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Este valor deve ser falso.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Este valor deve ser verdadeiro.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Este valor deve ser do tipo {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Este valor deve ser vazio.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>O valor selecionado não é uma opção válida.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Você deve selecionar, no mínimo, {{ limit }} opção.|Você deve selecionar, no mínimo, {{ limit }} opções.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Você deve selecionar, no máximo, {{ limit }} opção.|Você deve selecionar, no máximo, {{ limit }} opções.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Um ou mais valores informados são inválidos.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Este campo não era esperado.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Este campo está ausente.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Este valor não é uma data válida.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Este valor não é uma data e hora válida.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Este valor não é um endereço de e-mail válido.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>O arquivo não foi encontrado.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>O arquivo não pode ser lido.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Este valor deve ser {{ limit }} ou menos.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Este valor é muito longo. Deve ter {{ limit }} caractere ou menos.|Este valor é muito longo. Deve ter {{ limit }} caracteres ou menos.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Este valor deve ser {{ limit }} ou mais.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Este valor é muito curto. Deve ter {{ limit }} caractere ou mais.|Este valor é muito curto. Deve ter {{ limit }} caracteres ou mais.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Este valor não deve ser vazio.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Este valor não deve ser nulo.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Este valor deve ser nulo.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Este valor não é válido.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Este valor não é uma hora válida.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Este valor não é uma URL válida.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Os dois valores devem ser iguais.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>O arquivo é muito grande.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>O arquivo não pode ser enviado.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Este valor deve ser um número válido.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Este arquivo não é uma imagem válida.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Este não é um endereço de IP válido.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Este valor não é um idioma válido.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Este valor não é uma localidade válida.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Este valor não é um país válido.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Este valor já está sendo usado.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>O tamanho da imagem não pode ser detectado.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>A largura da imagem é muito grande ({{ width }}px). A largura máxima permitida é de {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>A largura da imagem é muito pequena ({{ width }}px). A largura mínima esperada é de {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>A altura da imagem é muito grande ({{ height }}px). A altura máxima permitida é de {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>A altura da imagem é muito pequena ({{ height }}px). A altura mínima esperada é de {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Este valor deve ser a senha atual do usuário.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Este valor deve ter exatamente {{ limit }} caractere.|Este valor deve ter exatamente {{ limit }} caracteres.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>O arquivo foi enviado apenas parcialmente.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nenhum arquivo foi enviado.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nenhum diretório temporário foi configurado no php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Não foi possível escrever o arquivo temporário no disco.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Uma extensão PHP fez com que o envio falhasse.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Número de cartão inválido.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipo de cartão não suportado ou número de cartão inválido.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Este não é um Número Internacional de Conta Bancária (IBAN) válido.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Este valor não é um ISBN-10 válido.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Este valor não é um ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Este valor não é um ISBN-10 e nem um ISBN-13 válido.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Este valor não é um ISSN válido.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Este não é um valor monetário válido.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Este valor deve ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Este valor deve ser maior que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Este valor deve ser maior ou igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Este valor deve ser menor que {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Este valor deve ser menor ou igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Este valor não deve ser igual a {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>A proporção da imagem é muito grande ({{ ratio }}). A proporção máxima permitida é {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>A proporção da imagem é muito pequena ({{ ratio }}). A proporção mínima esperada é {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>A imagem está num formato quadrado ({{ width }}x{{ height }}px). Imagens com formato quadrado não são permitidas.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>A imagem está orientada à paisagem ({{ width }}x{{ height }}px). Imagens orientadas à paisagem não são permitidas.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>A imagem está orientada ao retrato ({{ width }}x{{ height }}px). Imagens orientadas ao retrato não são permitidas.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Arquivo vazio não é permitido.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>O host não pôde ser resolvido.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Este valor não corresponde ao charset {{ charset }} esperado.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Este não é um Código Identificador Bancário (BIC) válido.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ro.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ro.xlf
new file mode 100644
index 0000000..63af470
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ro.xlf
@@ -0,0 +1,287 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Această valoare ar trebui să fie falsă (false).</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Această valoare ar trebui să fie adevărată (true).</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Această valoare ar trebui să fie de tipul {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Această valoare ar trebui sa fie goală.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Valoarea selectată nu este o opțiune validă.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Trebuie să selectați cel puțin {{ limit }} opțiune.|Trebuie să selectați cel puțin {{ limit }} opțiuni.|Trebuie să selectați cel puțin {{ limit }} de opțiuni</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Trebuie să selectați cel mult {{ limit }} opțiune.|Trebuie să selectați cel mult {{ limit }} opțiuni.|Trebuie să selectați cel mult {{ limit }} de opțiuni.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Una sau mai multe dintre valorile furnizate sunt invalide.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Acest câmp nu era de aşteptat.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Acest câmp este lipsă.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Această valoare nu reprezintă o dată validă.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Această valoare nu reprezintă o dată și oră validă.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Această valoare nu reprezintă o adresă de e-mail validă.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Fișierul nu a putut fi găsit.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Fișierul nu poate fi citit.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fișierul este prea mare ({{ size }} {{ suffix }}). Dimensiunea maximă permisă este {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Tipul fișierului este invalid ({{ type }}). Tipurile permise de fișiere sunt ({{ types }}).</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Această valoare ar trebui să fie cel mult {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caracter.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caractere.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} de caractere.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Această valoare ar trebui să fie cel puțin {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caracter.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caractere.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} de caractere.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Această valoare nu ar trebui să fie goală.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Această valoare nu ar trebui să fie nulă (null).</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Această valoare ar trebui să fie nulă (null).</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Această valoare nu este validă.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Această valoare nu reprezintă o oră validă.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Această valoare nu reprezintă un URL (link) valid.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Cele două valori ar trebui să fie egale.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Fișierul este prea mare. Mărimea maximă permisă este {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Fișierul este prea mare.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Fișierul nu a putut fi încărcat.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Această valoare nu reprezintă un număr valid.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Acest fișier nu este o imagine validă.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Această valoare nu este o adresă IP validă.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Această valoare nu reprezintă o limbă corectă.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Această valoare nu reprezintă un dialect (o limbă) corect.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Această valoare nu este o țară validă.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Această valoare este folosită deja.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Mărimea imaginii nu a putut fi detectată.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Lățimea imaginii este prea mare ({{ width }}px). Lățimea maximă permisă este de {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Lățimea imaginii este prea mică ({{ width }}px). Lățimea minimă permisă este de {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Înălțimea imaginii este prea mare ({{ height }}px). Înălțimea maximă permisă este de {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Înălțimea imaginii este prea mică ({{ height }}px). Înălțimea minimă permisă este de {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Această valoare trebuie să fie parola curentă a utilizatorului.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Această valoare trebuie să conțină exact {{ limit }} caracter.|Această valoare trebuie să conțină exact {{ limit }} caractere.|Această valoare trebuie să conțină exact {{ limit }} de caractere.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Fișierul a fost încărcat parțial.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nu a fost încărcat nici un fișier.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Nu este configurat nici un director temporar in php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Nu a fost posibilă scrierea fișierului temporar pe disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>O extensie PHP a prevenit încărcarea cu succes a fișierului.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Această colecție trebuie să conțină cel puțin {{ limit }} element.|Această colecție trebuie să conțină cel puțin {{ limit }} elemente.|Această colecție trebuie să conțină cel puțin {{ limit }} de elemente.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Această colecție trebuie să conțină cel mult {{ limit }} element.|Această colecție trebuie să conțină cel mult {{ limit }} elemente.|Această colecție trebuie să conțină cel mult {{ limit }} de elemente.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Această colecție trebuie să conțină {{ limit }} element.|Această colecție trebuie să conțină {{ limit }} elemente.|Această colecție trebuie să conțină {{ limit }} de elemente.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Numărul card invalid.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Tipul sau numărul cardului nu sunt valide.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Acesta nu este un cod IBAN (International Bank Account Number) valid.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Această valoare nu este un cod ISBN-10 valid.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Această valoare nu este un cod ISBN-13 valid.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Această valoare nu este un cod ISBN-10 sau ISBN-13 valid.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Această valoare nu este un cod ISSN valid.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Această valoare nu este o monedă validă.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Această valoare trebuie să fie egală cu {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Această valoare trebuie să fie mai mare de {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Această valoare trebuie să fie mai mare sau egală cu {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Această valoare trebuie identică cu {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Această valoare trebuie să fie mai mică de {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Această valoare trebuie să fie mai mică sau egală cu {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Această valoare nu trebuie să fie egală cu {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Această valoare nu trebuie să fie identică cu {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Eroare</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ru.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ru.xlf
new file mode 100644
index 0000000..11bfead
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.ru.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Значение должно быть ложным.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Значение должно быть истинным.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Тип значения должен быть {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Значение должно быть пустым.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Выбранное Вами значение недопустимо.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Вы должны выбрать хотя бы {{ limit }} вариант.|Вы должны выбрать хотя бы {{ limit }} варианта.|Вы должны выбрать хотя бы {{ limit }} вариантов.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Вы должны выбрать не более чем {{ limit }} вариант.|Вы должны выбрать не более чем {{ limit }} варианта.|Вы должны выбрать не более чем {{ limit }} вариантов.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Одно или несколько заданных значений недопустимо.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Это поле не ожидалось.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Это поле отсутствует.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Значение не является правильной датой.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Значение даты и времени недопустимо.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Значение адреса электронной почты недопустимо.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Файл не может быть найден.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Файл не может быть прочитан.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файл слишком большой ({{ size }} {{ suffix }}). Максимально допустимый размер {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>MIME-тип файла недопустим ({{ type }}). Допустимы MIME-типы файлов {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Значение должно быть {{ limit }} или меньше.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Значение слишком длинное. Должно быть равно {{ limit }} символу или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Значение должно быть {{ limit }} или больше.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Значение слишком короткое. Должно быть равно {{ limit }} символу или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Значение не должно быть пустым.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Значение не должно быть null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Значение должно быть null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Значение недопустимо.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Значение времени недопустимо.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Значение не является допустимым URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Оба значения должны быть одинаковыми.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файл слишком большой. Максимально допустимый размер {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Файл слишком большой.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Файл не может быть загружен.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Значение должно быть числом.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This value is not a valid country.</source>
+ <target>Значение не является допустимой страной.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This file is not a valid image.</source>
+ <target>Файл не является допустимым форматом изображения.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This is not a valid IP address.</source>
+ <target>Значение не является допустимым IP адресом.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid language.</source>
+ <target>Значение не является допустимым языком.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid locale.</source>
+ <target>Значение не является допустимой локалью.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Это значение уже используется.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Не удалось определить размер изображения.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Ширина изображения слишком велика ({{ width }}px). Максимально допустимая ширина {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Ширина изображения слишком мала ({{ width }}px). Минимально допустимая ширина {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Высота изображения слишком велика ({{ height }}px). Максимально допустимая высота {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Высота изображения слишком мала ({{ height }}px). Минимально допустимая высота {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Значение должно быть текущим паролем пользователя.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Значение должно быть равно {{ limit }} символу.|Значение должно быть равно {{ limit }} символам.|Значение должно быть равно {{ limit }} символам.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Файл был загружен только частично.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Файл не был загружен.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Не настроена временная директория в php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Невозможно записать временный файл на диск.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Расширение PHP вызвало ошибку при загрузке.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Эта коллекция должна содержать {{ limit }} элемент или больше.|Эта коллекция должна содержать {{ limit }} элемента или больше.|Эта коллекция должна содержать {{ limit }} элементов или больше.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Неверный номер карты.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Неподдерживаемый тип или неверный номер карты.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Значение не является допустимым международным номером банковского счета (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Значение имеет неверный формат ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Значение имеет неверный формат ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Значение не соответствует форматам ISBN-10 и ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Значение не соответствует формату ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Некорректный формат валюты.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Значение должно быть равно {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Значение должно быть больше чем {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Значение должно быть больше или равно {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Значение должно быть идентичным {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Значение должно быть меньше чем {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Значение должно быть меньше или равно {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Значение не должно быть равно {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Значение не должно быть идентичным {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Соотношение сторон изображения слишком велико ({{ ratio }}). Максимальное соотношение сторон {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Соотношение сторон изображения слишком мало ({{ ratio }}). Минимальное соотношение сторон {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Изображение квадратное ({{ width }}x{{ height }}px). Квадратные изображения не разрешены.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Изображение в альбомной ориентации ({{ width }}x{{ height }}px). Изображения в альбомной ориентации не разрешены.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Изображение в портретной ориентации ({{ width }}x{{ height }}px). Изображения в портретной ориентации не разрешены.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Пустые файлы не разрешены.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Имя хоста не может быть разрешено.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Значение не совпадает с ожидаемой {{ charset }} кодировкой.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Ошибка</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sk.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sk.xlf
new file mode 100644
index 0000000..8ddb66d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sk.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Táto hodnota by mala byť nastavená na false.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Táto hodnota by mala byť nastavená na true.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Táto hodnota by mala byť typu {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Táto hodnota by mala byť prázdna.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Táto hodnota by mala byť jednou z poskytnutých možností.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Mali by ste vybrať minimálne {{ limit }} možnosť.|Mali by ste vybrať minimálne {{ limit }} možnosti.|Mali by ste vybrať minimálne {{ limit }} možností.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Mali by ste vybrať najviac {{ limit }} možnosť.|Mali by ste vybrať najviac {{ limit }} možnosti.|Mali by ste vybrať najviac {{ limit }} možností.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Niektoré z uvedených hodnôt sú neplatné.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Toto pole sa neočakáva.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Toto pole chýba.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Tato hodnota nemá platný formát dátumu.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Táto hodnota nemá platný formát dátumu a času.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Táto hodnota nie je platná emailová adresa.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Súbor sa nenašiel.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Súbor nie je čitateľný.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Súbor je príliš veľký ({{ size }} {{ suffix }}). Maximálna povolená veľkosť je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Súbor typu ({{ type }}) nie je podporovaný. Podporované typy sú {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Táto hodnota by mala byť {{ limit }} alebo menej.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znak.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znaky.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znakov.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Táto hodnota by mala byť viac ako {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znak.|Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znaky.|Táto hodnota je príliš krátka. Minimálny počet znakov je {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Táto hodnota by mala byť vyplnená.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Táto hodnota by nemala byť null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Táto hodnota by mala byť null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Táto hodnota nie je platná.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Tato hodnota nemá správny formát času.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Táto hodnota nie je platnou URL adresou.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Tieto dve hodnoty by mali byť rovnaké.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Súbor je príliš veľký. Maximálna povolená veľkosť je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Súbor je príliš veľký.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Súbor sa nepodarilo nahrať.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Táto hodnota by mala byť číslo.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Tento súbor nie je obrázok.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Toto nie je platná IP adresa.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Tento jazyk neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Táto lokalizácia neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Táto krajina neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Táto hodnota sa už používa.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Nepodarilo sa zistiť rozmery obrázku.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Obrázok je príliš široký ({{ width }}px). Maximálna povolená šírka obrázku je {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Obrázok je príliš úzky ({{ width }}px). Minimálna šírka obrázku by mala byť {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>>Obrázok je príliš vysoký ({{ height }}px). Maximálna povolená výška obrázku je {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Obrázok je príliš nízky ({{ height }}px). Minimálna výška obrázku by mala byť {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Táto hodnota by mala byť aktuálne heslo používateľa.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Táto hodnota by mala mať presne {{ limit }} znak.|Táto hodnota by mala mať presne {{ limit }} znaky.|Táto hodnota by mala mať presne {{ limit }} znakov.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Bola nahraná len časť súboru.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Žiadny súbor nebol nahraný.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>V php.ini nie je nastavená cesta k adresáru pre dočasné súbory.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Dočasný súbor sa nepodarilo zapísať na disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Rozšírenie PHP zabránilo nahraniu súboru.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Táto kolekcia by mala obsahovať aspoň {{ limit }} prvok alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvky alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvkov alebo viac.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Táto kolekcia by mala maximálne {{ limit }} prvok.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvky.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvkov.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Táto kolekcia by mala obsahovať presne {{ limit }} prvok.|Táto kolekcia by mala obsahovať presne {{ limit }} prvky.|Táto kolekcia by mala obsahovať presne {{ limit }} prvkov.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Neplatné číslo karty.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nepodporovaný typ karty alebo neplatné číslo karty.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Toto je neplatný IBAN.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Táto hodnota je neplatné ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Táto hodnota je neplatné ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Táto hodnota nie je platné ISBN-10 ani ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Táto hodnota nie je platné ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Táto hodnota nie je platná mena.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Táto hodnota by mala byť rovná {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Táto hodnota by mala byť väčšia ako {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Táto hodnota by mala byť väčšia alebo rovná {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Táto hodnota by mala byť typu {{ compared_value_type }} a zároveň by mala byť rovná {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Táto hodnota by mala byť menšia ako {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Táto hodnota by mala byť menšia alebo rovná {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Táto hodnota by nemala byť rovná {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Táto hodnota by nemala byť typu {{ compared_value_type }} a zároveň by nemala byť rovná {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Pomer strán obrázku je príliš veľký ({{ ratio }}). Maximálny povolený pomer strán obrázku je {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Pomer strán obrázku je príliš malý ({{ ratio }}). Minimálny povolený pomer strán obrázku je {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Strany obrázku sú štvorcové ({{ width }}x{{ height }}px). Štvorcové obrázky nie sú povolené.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Obrázok je orientovaný na šírku ({{ width }}x{{ height }}px). Obrázky orientované na šírku nie sú povolené.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Obrázok je orientovaný na výšku ({{ width }}x{{ height }}px). Obrázky orientované na výšku nie sú povolené.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Súbor nesmie byť prázdny.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Hostiteľa nebolo možné rozpoznať.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Táto hodnota nezodpovedá očakávanej znakovej sade {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Táto hodnota nie je platný identifikačný kód podniku (BIC).</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sl.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sl.xlf
new file mode 100644
index 0000000..6f5fd98
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sl.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Vrednost bi morala biti nepravilna (false).</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Vrednost bi morala biti pravilna (true).</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Vrednost mora biti naslednjega tipa {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Vrednost mora biti prazna.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Vrednost, ki ste jo izbrali, ni veljavna možnost.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Izbrati morate vsaj {{ limit }} možnost.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Izberete lahko največ {{ limit }} možnost.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Ena ali več podanih vrednosti ni veljavnih.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>To polje ni bilo pričakovati.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>To polje manjka.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Ta vrednost ni veljaven datum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ta vrednost ni veljaven datum in čas.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Ta vrednost ni veljaven e-poštni naslov.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Datoteke ni mogoče najti.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Datoteke ni mogoče prebrati.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Največja dovoljena velikost je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mime tip datoteke je neveljaven ({{ type }}). Dovoljeni mime tipi so {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Ta vrednost bi morala biti {{ limit }} ali manj.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Ta vrednost je predolga. Morala bi imeti {{ limit }} znak ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znaka ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znake ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znakov ali manj.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Ta vrednost bi morala biti {{ limit }} ali več.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Ta vrednost je prekratka. Morala bi imeti {{ limit }} znak ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znaka ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znake ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znakov ali več.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ta vrednost ne bi smela biti prazna.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Ta vrednost ne bi smela biti nedefinirana (null).</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Ta vrednost bi morala biti nedefinirana (null).</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Ta vrednost ni veljavna.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ta vrednost ni veljaven čas.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Ta vrednost ni veljaven URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Ti dve vrednosti bi morali biti enaki.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Datoteka je prevelika. Največja dovoljena velikost je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Datoteka je prevelika.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Datoteke ni bilo mogoče naložiti.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Ta vrednost bi morala biti veljavna številka.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ta datoteka ni veljavna slika.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>To ni veljaven IP naslov.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Ta vrednost ni veljaven jezik.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Ta vrednost ni veljavna lokalnost.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Ta vrednost ni veljavna država.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Ta vrednost je že uporabljena.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Velikosti slike ni bilo mogoče zaznati.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Širina slike je preširoka ({{ width }}px). Največja dovoljena širina je {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Širina slike je premajhna ({{ width }}px). Najmanjša predvidena širina je {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Višina slike je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Višina slike je premajhna ({{ height }}px). Najmanjša predvidena višina je {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Ta vrednost bi morala biti trenutno uporabnikovo geslo.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Ta vrednost bi morala imeti točno {{ limit }} znak.|Ta vrednost bi morala imeti točno {{ limit }} znaka.|Ta vrednost bi morala imeti točno {{ limit }} znake.|Ta vrednost bi morala imeti točno {{ limit }} znakov.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Datoteka je bila le delno naložena.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nobena datoteka ni bila naložena.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Začasna mapa ni nastavljena v php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Začasne datoteke ni bilo mogoče zapisati na disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP razširitev je vzrok, da nalaganje ni uspelo.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ta zbirka bi morala vsebovati {{ limit }} element ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali več.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali več.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ta zbirka bi morala vsebovati {{ limit }} element ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali manj.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Neveljavna številka kartice.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nepodprti tip kartice ali neveljavna številka kartice.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>To ni veljavna mednarodna številka bančnega računa (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Neveljavna vrednost po ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Neveljavna vrednost po ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Neveljavna vrednost po ISBN-10 ali po ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Neveljavna vrednost ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ta vrednost ni veljavna valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ta vrednost bi morala biti enaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ta vrednost bi morala biti večja od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ta vrednost bi morala biti večja ali enaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ta vrednost bi morala biti identična {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ta vrednost bi morala biti manjša od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ta vrednost bi morala biti manjša ali enaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ta vrednost ne bi smela biti enaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ta vrednost ne bi smela biti identična {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Razmerje slike je preveliko ({{ ratio }}). Največje dovoljeno razmerje je {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Razmerje slike je premajhno ({{ ratio }}). Najmanjše pričakovano razmerje je {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Slika je kvadrat ({{ width }}x{{ height }}px). Kvadratne slike niso dovoljene.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Slika je ležeče usmerjena ({{ width }}x{{ height }}px). Ležeče usmerjene slike niso dovoljene.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Slika je pokončno usmerjena ({{ width }}x{{ height }}px). Pokončno usmerjene slike niso dovoljene.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Prazna datoteka ni dovoljena.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Gostitelja ni bilo mogoče prepoznati.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Ta vrednost se ne ujema s pričakovanim naborom znakov {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>To ni veljavna identifikacijska koda podjetja (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Napaka</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sq.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sq.xlf
new file mode 100644
index 0000000..ffc8ccf
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sq.xlf
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Kjo vlerë duhet të jetë e pavërtetë (false).</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Kjo vlerë duhet të jetë e vërtetë (true).</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Kjo vlerë duhet të jetë e llojit {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Kjo vlerë duhet të jetë e zbrazët.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Vlera që keni zgjedhur nuk është alternativë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Një apo më shumë nga vlerat e dhëna nuk janë të sakta.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Kjo fushë nuk pritej.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Kjo fushë është zhdukur.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Kjo vlerë nuk është datë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Kjo vlerë nuk është datë-kohë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Kjo vlerë nuk është e-mail adresë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>File nuk mund të gjindej.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>File nuk është i lexueshëm.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Kjo vlerë duhet të jetë {{ limit }} ose më pak.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Kjo vlerë duhet të jetë {{ limit }} ose më shumë.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Kjo vlerë nuk duhet të jetë e zbrazët.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Kjo vlerë nuk duhet të jetë null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Kjo vlerë duhet të jetë null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Kjo vlerë nuk është e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Kjo vlerë nuk është kohë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Kjo vlerë nuk është URL e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Këto dy vlera duhet të jenë të barabarta.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Ky file është shumë i madh. Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Ky file është shumë i madh.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Ky file nuk mund të ngarkohet.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Kjo vlerë duhet të jetë numër i vlefshëm.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ky file nuk është imazh i vlefshëm.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Kjo vlerë nuk është IP adresë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Kjo vlerë nuk është gjuhë e vlefshme.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Kjo vlerë nuk është përcaktim rajonal i vlefshëm.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Kjo vlerë nuk është shtet i vlefshëm.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Kjo vlerë është tashmë në përdorim.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Madhësia e këtij imazhi nuk mund të zbulohet.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Gjerësia e imazhit është shumë e madhe ({{ width }}px). Gjerësia maksimale e lejuar është {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Gjerësia e imazhit është shumë e vogël ({{ width }}px). Gjerësia minimale e pritur është {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Gjatësia e imazhit është shumë e madhe ({{ height }}px). Gjatësia maksimale e lejuar është {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Gjatësia e imazhit është shumë e vogël ({{ height }}px). Gjatësia minimale e pritur është {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Kjo vlerë duhet të jetë fjalëkalimi aktual i përdoruesit.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Ky file është ngarkuar pjesërisht.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Nuk është ngarkuar ndonjë file.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Asnjë folder i përkohshëm nuk është konfiguruar në php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Nuk mund të shkruhet file i përkohshëm në disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Numër kartele i pavlefshëm.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Lloj kartele i pambështetur ose numër kartele i pavlefshëm.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf
new file mode 100644
index 0000000..81f5210
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf
@@ -0,0 +1,303 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Вредност треба да буде нетачна.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Вредност треба да буде тачна.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Вредност треба да буде типа {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Вредност треба да буде празна.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Вредност треба да буде једна од понуђених.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Изаберите бар {{ limit }} могућност.|Изаберите бар {{ limit }} могућности.|Изаберите бар {{ limit }} могућности.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Изаберите највише {{ limit }} могућност.|Изаберите највише {{ limit }} могућности.|Изаберите највише {{ limit }} могућности.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Једна или више вредности је невалидна.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Ово поље не очекује.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ово поље недостаје.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Вредност није валидан датум.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Вредност није валидан датум-време.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Вредност није валидна адреса електронске поште.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Датотека не може бити пронађена.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Датотека није читљива.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Датотека је превелика ({{ size }} {{ suffix }}). Највећа дозвољена величина је {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Миме тип датотеке није валидан ({{ type }}). Дозвољени миме типови су {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Вредност треба да буде {{ limit }} или мање.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Вредност је предугачка. Треба да има {{ limit }} карактер или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Вредност треба да буде {{ limit }} или више.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Вредност је прекратка. Треба да има {{ limit }} карактер или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Вредност не треба да буде празна.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Вредност не треба да буде null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Вредност треба да буде null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Вредност је невалидна.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Вредност није валидно време.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Вредност није валидан URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Обе вредности треба да буду једнаке.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Датотека је превелика. Највећа дозвољена величина је {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Датотека је превелика.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Датотека не може бити отпремљена.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Вредност треба да буде валидан број.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ова датотека није валидна слика.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Ово није валидна ИП адреса.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Вредност није валидан језик.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Вредност није валидан локал.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Вредност није валидна земља.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Вредност је већ искоришћена.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Величина слике не може бити одређена.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Ширина слике је превелика ({{ width }}px). Најећа дозвољена ширина је {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Ширина слике је премала ({{ width }}px). Најмања дозвољена ширина је {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Висина слике је превелика ({{ height }}px). Најећа дозвољена висина је {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Висина слике је премала ({{ height }}px). Најмања дозвољена висина је {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Вредност треба да буде тренутна корисничка лозинка.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Вредност треба да има тачно {{ limit }} карактер.|Вредност треба да има тачно {{ limit }} карактера.|Вредност треба да има тачно {{ limit }} карактера.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Датотека је само парцијално отпремљена.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Датотека није отпремљена.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Привремени директоријум није конфигурисан у php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Немогуће писање привремене датотеке на диск.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP екстензија је проузроковала неуспех отпремања датотеке.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Невалидан број картице.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Невалидан број картице или тип картице није подржан.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Ово није валидан међународни број банковног рачуна (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ово није валидан ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ово није валидан ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ово није валидан ISBN-10 или ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ово није валидан ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ово није валидна валута.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ова вредност треба да буде {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ова вредност треба да буде већа од {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ова вредност треба да буде већа или једнака {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ова вредност треба да буде идентична са {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ова вредност треба да буде мања од {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ова вредност треба да буде мања или једнака {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ова вредност не треба да буде једнака {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ова вредност не треба да буде идентична са {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Размера ове слике је превелика ({{ ratio }}). Максимална дозвољена размера је {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Размера ове слике је премала ({{ ratio }}). Минимална очекивана размера је {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Слика је квадратна ({{ width }}x{{ height }}px). Квадратне слике нису дозвољене.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Слика је оријентације пејзажа ({{ width }}x{{ height }}px). Пејзажна оријентација слика није дозвољена.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Слика је оријантације портрета ({{ width }}x{{ height }}px). Портретна оријентација слика није дозвољена.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Latn.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Latn.xlf
new file mode 100644
index 0000000..60c093a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sr_Latn.xlf
@@ -0,0 +1,303 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Vrednost treba da bude netačna.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Vrednost treba da bude tačna.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Vrednost treba da bude tipa {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Vrednost treba da bude prazna.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Vrednost treba da bude jedna od ponuđenih.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Jedna ili više vrednosti je nevalidna.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Ovo polje ne očekuje.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ovo polje nedostaje.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Vrednost nije validan datum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Vrednost nije validan datum-vreme.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Vrednost nije validna adresa elektronske pošte.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Datoteka ne može biti pronađena.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Datoteka nije čitljiva.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Vrednost treba da bude {{ limit }} ili manje.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Vrednost treba da bude {{ limit }} ili više.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Vrednost ne treba da bude prazna.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Vrednost ne treba da bude null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Vrednost treba da bude null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Vrednost je nevalidna.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Vrednost nije validno vreme.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Vrednost nije validan URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Obe vrednosti treba da budu jednake.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Datoteka je prevelika.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Datoteka ne može biti otpremljena.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Vrednost treba da bude validan broj.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ova datoteka nije validna slika.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Ovo nije validna IP adresa.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Vrednost nije validan jezik.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Vrednost nije validan lokal.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Vrednost nije validna zemlja.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Vrednost je već iskorišćena.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Veličina slike ne može biti određena.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Vrednost treba da bude trenutna korisnička lozinka.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Datoteka je samo parcijalno otpremljena.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Datoteka nije otpremljena.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Privremeni direktorijum nije konfigurisan u php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Nemoguće pisanje privremene datoteke na disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP ekstenzija je prouzrokovala neuspeh otpremanja datoteke.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Nevalidan broj kartice.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Nevalidan broj kartice ili tip kartice nije podržan.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Ovo nije validan međunarodni broj bankovnog računa (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ovo nije validan ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ovo nije validan ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ovo nije validan ISBN-10 ili ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ovo nije validan ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ovo nije validna valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ova vrednost treba da bude {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ova vrednost treba da bude veća od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ova vrednost treba da bude veća ili jednaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ova vrednost treba da bude identična sa {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ova vrednost treba da bude manja od {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ova vrednost treba da bude manja ili jednaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ova vrednost ne treba da bude jednaka {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ova vrednost ne treba da bude identična sa {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Razmera ove slike je prevelika ({{ ratio }}). Maksimalna dozvoljena razmera je {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Razmera ove slike je premala ({{ ratio }}). Minimalna očekivana razmera je {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Slika je kvadratna ({{ width }}x{{ height }}px). Kvadratne slike nisu dozvoljene.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Slika je orijentacije pejzaža ({{ width }}x{{ height }}px). Pejzažna orijentacija slika nije dozvoljena.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Slika je orijantacije portreta ({{ width }}x{{ height }}px). Portretna orijentacija slika nije dozvoljena.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sv.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sv.xlf
new file mode 100644
index 0000000..40dd63e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.sv.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Värdet ska vara falskt.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Värdet ska vara sant.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Värdet ska vara av typen {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Värdet ska vara tomt.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Värdet ska vara ett av de givna valen.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Du måste välja minst {{ limit }} val.|Du måste välja minst {{ limit }} val.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Du kan som mest välja {{ limit }} val.|Du kan som mest välja {{ limit }} val.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Ett eller fler av de angivna värdena är ogiltigt.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Det här fältet förväntades inte.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Det här fältet saknas.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Värdet är inte ett giltigt datum.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Värdet är inte ett giltigt datum med tid.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Värdet är inte en giltig e-postadress.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Filen kunde inte hittas.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Filen är inte läsbar.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen är för stor ({{ size }} {{ suffix }}). Största tillåtna storlek är {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Filens MIME-typ ({{ type }}) är ogiltig. De tillåtna typerna är {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Värdet ska vara {{ limit }} eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.|Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Värdet ska vara {{ limit }} eller mer.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.|Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Värdet kan inte vara tomt.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Värdet kan inte vara null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Värdet ska vara null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Värdet är inte giltigt.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Värdet är inte en giltig tid.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Värdet är inte en giltig URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>De två värdena måste vara lika.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Filen är för stor. Tillåten maximal storlek är {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Filen är för stor.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Filen kunde inte laddas upp.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Värdet ska vara ett giltigt nummer.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Filen är ingen giltig bild.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Det här är inte en giltig IP-adress.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Värdet är inte ett giltigt språk.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Värdet är inte en giltig plats.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Värdet är inte ett giltigt land.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Värdet används redan.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Det gick inte att fastställa storleken på bilden.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Bildens bredd är för stor ({{ width }}px). Tillåten maximal bredd är {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Bildens bredd är för liten ({{ width }}px). Minsta förväntade bredd är {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Bildens höjd är för stor ({{ height }}px). Tillåten maximal bredd är {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Bildens höjd är för liten ({{ height }}px). Minsta förväntade höjd är {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Värdet ska vara användarens nuvarande lösenord.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Värdet ska ha exakt {{ limit }} tecken.|Värdet ska ha exakt {{ limit }} tecken.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Filen laddades bara upp delvis.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Ingen fil laddades upp.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Det finns ingen temporär mapp konfigurerad i php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Kan inte skriva temporär fil till disken.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>En PHP extension gjorde att uppladdningen misslyckades.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Den här samlingen ska innehålla {{ limit }} element eller mer.|Den här samlingen ska innehålla {{ limit }} element eller mer.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Den här samlingen ska innehålla {{ limit }} element eller mindre.|Den här samlingen ska innehålla {{ limit }} element eller mindre.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Den här samlingen ska innehålla exakt {{ limit }} element.|Den här samlingen ska innehålla exakt {{ limit }} element.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Ogiltigt kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Okänd korttyp eller ogiltigt kortnummer.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Det här är inte en giltig International Bank Account Number (IBANK).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Värdet är inte en giltig ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Värdet är inte en giltig ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Värdet är varken en giltig ISBN-10 eller en giltig ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Värdet är inte en giltig ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Värdet är inte en giltig valuta.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Värdet ska vara detsamma som {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Värdet ska vara större än {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Värdet ska bara större än eller detsamma som {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Värdet ska vara identiskt till {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Värdet ska vara mindre än {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Värdet ska vara mindre än eller detsamma som {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Värdet ska inte vara detsamma som {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Värdet ska inte vara identiskt med {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Förhållandet mellan bildens bredd och höjd är för stort ({{ ratio }}). Högsta tillåtna förhållande är {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Förhållandet mellan bildens bredd och höjd är för litet ({{ ratio }}). Minsta tillåtna förhållande är {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Bilden är kvadratisk ({{ width }}x{{ height }}px). Kvadratiska bilder tillåts inte.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Bilden är landskapsorienterad ({{ width }}x{{ height }}px). Landskapsorienterade bilder tillåts inte.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Bilden är porträttsorienterad ({{ width }}x{{ height }}px). Porträttsorienterade bilder tillåts inte.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>En tom fil är inte tillåten.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Värddatorn kunde inte hittas.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Detta värde har inte den förväntade teckenkodningen {{ charset }}.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Detta är inte en giltig BIC-kod.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Fel</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.th.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.th.xlf
new file mode 100644
index 0000000..d5b5703
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.th.xlf
@@ -0,0 +1,303 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>ค่านี้ควรจะเป็น false</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>ค่านี้ควรจะเป็น true</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>ค่านี้ควรจะเป็นชนิด {{ type }}</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>ควรจะเป็นค่าว่าง</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>คุณเลือกค่าที่ไม่ตรงกับตัวเลือก</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>คุณต้องเลือกอย่างน้อย {{ limit }} ตัวเลือก</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>คุณเลือกได้มากที่สุด {{ limit }} ตัวเลือก</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>มีบางค่าที่ส่งมาไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>ฟิลด์นี้ที่ไม่ได้คาดหวัง</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>ฟิลด์นี้จะหายไป</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>ค่าของวันที่ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>ค่าของวันที่และเวลาไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>ค่าของอีเมล์ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>ไม่พบไฟล์</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>ไฟล์ไม่อยู่ในสถานะที่สามารถอ่านได้</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>ไฟล์ใหญ่เกิน ({{ size }} {{ suffix }}) อนุญาตให้ใหญ่ที่สุดได้ไม่เกิน {{ limit }} {{ suffix }}</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Mime type ของไฟล์ไม่ถูกต้อง ({{ type }}) Mime types ที่อนุญาตคือ {{ types }}</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>ค่านี้ควรจะเป็น {{ limit }} หรือน้อยกว่านั้น</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>ค่านี้ยาวเกินไป ควรจะมีแค่ {{ limit }} ตัวอักษรหรือน้อยกว่านั้น</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>ค่านี้ควรจะมี {{ limit }} หรือมากกว่านั้น</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>ค่านี้สั้นเกินไป ควรจะมี {{ limit }} ตัวอักษรหรือมากกว่านั้น</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>ค่านี้ไม่ควรเป็นค่าว่าง</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>ค่านี้ไม่ควรเป็นค่า null</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>ค่านี้ควรเป็นค่า null</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>ค่านี้ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>ค่าของเวลาไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>ค่าของ URL ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>ค่าทั้งสองค่าควรจะเหมือนกัน</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>ขนาดไฟล์ใหญ่เกินไป อนุญาตให้ไฟล์ขนาดใหญ่ได้ไม่เกิน {{ limit }} {{ suffix }}</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>ขนาดไฟล์ใหญ่เกินไป</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>ไม่สามารถอัปโหลดไฟล์ได้</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>ค่าของตัวเลขไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>ไฟล์นี้ไม่ใช่ไฟล์รูปภาพ</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>ค่าของ IP ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>ค่าของภาษาไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>ค่าของภูมิภาค (Locale) ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>ค่าของประเทศไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Tค่านี้ถูกใช้งานไปแล้ว</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>ไม่สามารถตรวจสอบขนาดไฟล์ของภาพได้</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>ความกว้างของภาพเกินขนาด ({{ width }}px) อนุญาตให้กว้างได้มากที่สุด {{ max_width }}px</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>ความกว้างของภาพไม่ได้ขนาด ({{ width }}px) อนุญาตให้สั้นที่สุด {{ min_width }}px</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>ความสูงของภาพเกินขนาด ({{ height }}px) อนุญาตให้สูงได้มากที่สุด {{ max_height }}px</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>ความสูงของภาพไม่ได้ขนาด ({{ height }}px) อนุญาตให้สูงอย่างน้อยที่สุด {{ min_height }}px</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>ค่านี้ควรจะเป็นรหัสผ่านปัจจุบันของผู้ใช้</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>ค่านี้ควรจะมีความยาว {{ limit }} ตัวอักษร</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>อัปโหลดไฟล์ได้เพียงบางส่วนเท่านั้น</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>ไม่มีไฟล์ใดถูกอัปโหลด</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>ไม่พบไฟล์ temp ควรจะกำหนดใน php.ini</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>ไม่สามารถเขียน temp ไฟล์ลงดิสก์ได้</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>PHP extension เกี่ยวกับการอัปโหลดมีปัญหา</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>คอเล็กชั่นนี้ควรจะประกอบไปด้วยอ่างน้อย {{ limit }} สมาชิก</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>คอเล็กชั่นนี้ไม่ควรมีสมาชิกเกิน {{ limit }}</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>คอเล็กชั่นนี้ควรจะมีสมาชิก {{ limit }} เท่านั้น</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>หมายเลขบัตรไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>ไม่รู้จักประเภทของบัตร หรือหมายเลขบัตรไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>นี่ไม่ถูกต้องตาม International Bank Account Number (IBAN)</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>ค่านี้ไม่ถูกต้องตาม ISBN-10</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>ค่านี้ไม่ถูกต้องตาม ISBN-13</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>ค่านี้ไม่ถูกต้องตามทั้ง ISBN-10 และ ISBN-13</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>ค่านี้ไม่ถุกต้องตาม ISSN</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>ค่านี้ไม่ถูกต้องตามสกุลเงิน</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>ค่านี้ไม่ตรงกับ {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>ค่านี้ควรจะมากกว่า {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>ค่านี้ควรจะมากกว่าหรือตรงกับ {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>ค่านี้ควรจะเหมือนกันกับ {{ compared_value_type }} {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>ค่านี้ควรจะน้อยกว่า {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>ค่านี้ควรจะน้อยกว่าหรือเท่ากับ {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>ค่านี้ไม่ควรเท่ากันกับ {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>ค่านี้ไม่ควรเหมือนกันกับ {{ compared_value_type }} {{ compared_value }}</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>สัดส่วนของภาพใหญ่เกิน ({{ ratio }}) สามารถมีขนาดใหญ่ที่สุดได้ {{ max_ratio }}</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>สัดส่วนของภาพเล็กเกิน ({{ ratio }}) สามารถมีขนาดเล็กที่สุดได้ {{ min_ratio }}</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>รูปภาพเป็นจุตรัส ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นสี่เหลี่ยมจตุรัส</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>ภาพนี้เป็นแนวนอน ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นแนวนอน</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>ภาพนี้เป็นแนวตั้ง ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นแนวตั้ง</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.tl.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.tl.xlf
new file mode 100644
index 0000000..75dc329
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.tl.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Ang halaga nito ay dapat na huwad.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Ang halaga nito ay dapat totoo.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Ang halaga nito ay dapat sa uri {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Ang halaga nito ay dapat walang laman.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Ang halaga ng iyong pinili ay hindi balidong pagpili.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Kailangan mong pumili ng pinakamababang {{ limit }} ng pagpilian.|Kailangan mong pumili ng pinakamababang {{ limit }} ng mga pagpipilian.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Kailangan mong pumili ng pinakamataas {{ limit }} ng pagpipilian.|Kailangan mong pumili ng pinakamataas {{ limit }} ng mga pagpipilian.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Isa o higit pang mga halaga na binigay ay hindi balido.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Ang larangang ito ay hindi inaasahan.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Ang patlang na ito ay nawawala.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Ang halagang ito ay hindi balidong petsa.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Ang halagang ito ay hindi wastong petsa/oras.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Ang halagang ito ay hindi balidong address ng email.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Ang file na ito ay hindi makita.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Ang file na ito ay hindi mabasa.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Ang file na ito ay masyadong malaki ({{ size }} {{ suffix }}). Ang pinakamalaking sukat {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Ang uri ng file ng mime ay hindi balido ({{ type }}).Ang mga pinapayagang uri ng mime ay ang {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Ang halaga nito ay dapat na {{ limit }} or maliit pa.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Ang halaga nito ay masyadong mahaba.Ito ay dapat na {{ limit }} karakter o maliit pa.|Ang halaga nito ay masyadong mahaba. Ito ay dapat na {{ limit }} mga karakter o maliit pa.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Ang halaga nito ay dapat na {{ limit }} o mas marami pa.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Ang halaga nito ay masyadong maliit. Ito ay dapat na {{ limit }} karakter o marami pa.|Ang halaga nito ay masyadong maliit. Ito ay dapat na {{ limit }} mga karakter o marami pa.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Ang halaga na ito ay dapat na may laman.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Meron dapt itong halaga.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Wala dapat itong halaga.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Hindi balido ang halagang ito.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Ang halagang ito ay hindi wastong oras.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Hindi ito isang balidong URL.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Ang dalwang halaga ay dapat magkapareha.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Ang file ay masyadong malaki. Ang pinapayagan halaga lamang ay {{ limit}} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Ang file na ito ay masyadong malaki.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Ang file na ito ay hindi ma-upload.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Ang halaga nito ay dapat na wastong numero.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Ang file na ito ay hindi wastong imahe.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Ito ay hindi wastong IP address.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Ang halaga na ito ay hindi balidong wika.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Ito ay isang hindi wastong locale na halaga.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>ng halaga na ito ay hindi wastong bansa.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Ang halaga na ito ay ginamit na.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Ang sukat ng imahe ay hindi madetect.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Ang lapad ng imahe ay masyadong malaki ({{ width }}px). Ang pinapayagang lapay ay {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Ang lapad ng imahe ay masyadong maliit ({{ width }}px). Ang pinakamaliit na pinapayagang lapad ay {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Ang haba ng imahe ay masyadong mataas ({{ height }}px). Ang pinakmataas na haba ay {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Ang haba ng imahe ay masyadong maliit ({{ height }}px). Ang inaasahang haba ay {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Ang halagang ito ay dapat na password ng kasalukuyang gumagamit.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Ang halagang ito ay dapat na eksakto sa {{ limit}} karakter.|Ang halagang ito ay dapat na eksakto sa {{ limit }} mga karakter.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Ang file na ito ay kahalating na upload lamang.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Walang na upload na file.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Walang temporaryong folder ang naayos sa php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Temporaryong hindi makasulat ng file sa disk.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Ang dahilan ng pagkabigo ng pagupload ng files ay isang extension ng PHP.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} elemento o marami pa.|Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} mga elemento o marami pa.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} elemento o maliit pa.|Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} mga elemento o maliit pa.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ang koleksyong ito ay magkaroon ng eksaktong {{ limit }} elemento.|Ang koleksyong ito ay magkaroon ng eksaktong {{ limit }} mga elemento.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Hindi wastong numero ng kard.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Hindi supportadong uri ng kard o hindi wastong numero ng kard.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Ito ay hindi isang balidong International Bank Account Number (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Ang halagang ito ay hindi balidong SBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Ang halagang ito ay hindi balidong ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Ang halagang ito ay pwdeng isang balidong ISBN-10 o isang balidong ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Ang halangang ito ay hindi isang balidong ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Ang halagang ito ay hindi balidong pera.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Ito ay hindi dapat magkapareho sa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Ang halagang ito ay dapat tataas sa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Ang halagang ito ay dapat mas mataas o magkapareha sa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ang halagang ito ay dapat kapareha ng {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Ang halagang ito ay dapat mas maliit sa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Ang halagang ito ay dapat mas mmaliit o magkapareha sa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Ang halagang ito ay hindi dapat magkapareha sa {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Ang halagang ito ay hindi dapat magkapareha sa {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Ang ratio ng imahe ay masyadong malaki ({{ ratio }}). Ang pinakamalaking ratio ay {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>ng ratio ng imahe ay masyadong maliit ({{ ratio }}). Ang pinamaliit na ratio ay {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Ang imahe ay kwadrado ({{ width }}x{{ height }}px). Ang mga kwadradong imahe ay hindi pwede.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Ang orientasyon ng imahe ay nakalandscape ({{ width }}x{{ height }}px). Ang mga imaheng nakalandscape ang orientasyon ay hindi pwede.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Ang orientasyon ng imahe ay nakaportrait ({{ width }}x{{ height }}px). PAng mga imaheng nakaportrait ang orientasyon ay hindi pwede.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Ang file na walang laman ay hindi pwede.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Hindi maresolba ang host.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Ang halaga ay hindi kapareha sa inaasahang {{ charset }} set ng karater.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Ito ay hindi isang balidong Business Identifier Code (BIC).</target>
+ </trans-unit>
+ </body>
+ </file>
+ </xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.tr.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.tr.xlf
new file mode 100644
index 0000000..5e19e3e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.tr.xlf
@@ -0,0 +1,231 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Bu değer olumsuz olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Bu değer olumlu olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Bu değerin tipi {{ type }} olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Bu değer boş olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Seçtiğiniz değer geçerli bir seçenek değil.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>En az {{ limit }} seçenek belirtmelisiniz.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>En çok {{ limit }} seçenek belirtmelisiniz.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Verilen değerlerden bir veya daha fazlası geçersiz.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Bu alan beklenen olmadı.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Bu alan, eksik</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Bu değer doğru bir tarih biçimi değildir.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Bu değer doğru bir tarihsaat biçimi değildir.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Bu değer doğru bir e-mail adresi değildir.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Dosya bulunamadı.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Dosya okunabilir değil.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Dosya çok büyük ({{ size }} {{ suffix }}). İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Dosyanın mime tipi geçersiz ({{ type }}). İzin verilen mime tipleri {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Bu değer {{ limit }} ve altında olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Bu değer çok uzun. {{ limit }} karakter veya daha az olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Bu değer {{ limit }} veya daha fazla olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Bu değer çok kısa. {{ limit }} karakter veya daha fazla olmaldır.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Bu değer boş bırakılmamalıdır.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Bu değer boş bırakılmamalıdır.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Bu değer boş bırakılmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Bu değer geçerli değil.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Bu değer doğru bir saat değil.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Bu değer doğru bir URL değil.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>İki değer eşit olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Dosya çok büyük. İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Dosya çok büyük.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Dosya yüklenemiyor.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Bu değer geçerli bir rakam olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Bu dosya geçerli bir resim değildir.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Bu geçerli bir IP adresi değildir.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Bu değer geçerli bir lisan değil.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Bu değer geçerli bir yer değildir.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Bu değer geçerli bir ülke değildir.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Bu değer şu anda kullanımda.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Resmin boyutu saptanamıyor.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Resmin genişliği çok büyük ({{ width }}px). İzin verilen en büyük genişlik {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Resmin genişliği çok küçük ({{ width }}px). En az {{ min_width }}px olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Resmin yüksekliği çok büyük ({{ height }}px). İzin verilen en büyük yükseklik {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Resmin yüksekliği çok küçük ({{ height }}px). En az {{ min_height }}px olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Bu değer kullanıcının şu anki şifresi olmalıdır.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Bu değer tam olarak {{ limit }} karakter olmaldır.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Dosya sadece kısmen yüklendi.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Hiçbir dosya yüklenmedi.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>php.ini içerisinde geçici dizin tanımlanmadı.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Geçici dosya diske yazılamıyor.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Bir PHP eklentisi dosyanın yüklemesini başarısız kıldı.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Bu derlem {{ limit }} veya daha çok eleman içermelidir.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Bu derlem {{ limit }} veya daha az eleman içermelidir.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Bu derlem {{ limit }} eleman içermelidir.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Geçersiz kart numarası.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Desteklenmeyen kart tipi veya geçersiz kart numarası.</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Hata</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.uk.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.uk.xlf
new file mode 100644
index 0000000..6a92801
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.uk.xlf
@@ -0,0 +1,323 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Значення повинно бути Ні.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Значення повинно бути Так.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Тип значення повинен бути {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Значення повинно бути пустим.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Обране вами значення недопустиме.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Ви повинні обрати хоча б {{ limit }} варіант.|Ви повинні обрати хоча б {{ limit }} варіанти.|Ви повинні обрати хоча б {{ limit }} варіантів.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Ви повинні обрати не більше ніж {{ limit }} варіантів.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Одне або кілька заданих значень є недопустимі.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Це поле не очікується.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Це поле не вистачає.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Дане значення не є вірною датою.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Дане значення дати та часу недопустиме.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Значення адреси электронної пошти недопустиме.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Файл не знайдено.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Файл не читається.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файл занадто великий ({{ size }} {{ suffix }}). Дозволений максимальний розмір {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>MIME-тип файлу недопустимий ({{ type }}). Допустимі MIME-типи файлів {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Значення повинно бути {{ limit }} або менше.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Значення занадто довге. Повинно бути рівне {{ limit }} символу або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Значення повинно бути {{ limit }} або більше.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Значення занадто коротке. Повинно бути рівне {{ limit }} символу або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Значення не повинно бути пустим.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Значення не повинно бути null.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Значення повинно бути null.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Значення недопустиме.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Значення часу недопустиме.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Значення URL недопустиме.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Обидва занчення повинні бути одинаковими.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Файл занадто великий. Максимальний допустимий розмір {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Файл занадто великий.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Файл не можливо завантажити.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Значення має бути допустимим числом.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Цей файл не є допустимим форматом зображення.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Це некоректна IP адреса.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Це некоректна мова.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Це некоректна локалізація.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Це некоректна країна.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Це значення вже використовується.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Не вдалося визначити розмір зображення.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Ширина зображення занадто велика ({{ width }}px). Максимально допустима ширина {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Ширина зображення занадто мала ({{ width }}px). Мінімально допустима ширина {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Висота зображення занадто велика ({{ height }}px). Максимально допустима висота {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Висота зображення занадто мала ({{ height }}px). Мінімально допустима висота {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Значення має бути поточним паролем користувача.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Значення повиино бути рівним {{ limit }} символу.|Значення повиино бути рівним {{ limit }} символам.|Значення повиино бути рівним {{ limit }} символам.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Файл був завантажений лише частково.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Файл не був завантажений.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Не налаштована тимчасова директорія в php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Неможливо записати тимчасовий файл на диск.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Розширення PHP викликало помилку при завантаженні.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Ця колекція повинна містити {{ limit }} елемент чи більше.|Ця колекція повинна містити {{ limit }} елемента чи більше.|Ця колекція повинна містити {{ limit }} елементів чи більше.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Ця колекція повинна містити {{ limit }} елемент чи менше.|Ця колекція повинна містити {{ limit }} елемента чи менше.|Ця колекція повинна містити {{ limit }} елементов чи менше.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Ця колекція повинна містити рівно {{ limit }} елемент.|Ця колекція повинна містити рівно {{ limit }} елемента.|Ця колекція повинна містити рівно {{ limit }} елементів.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Невірний номер карти.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Непідтримуваний тип карти або невірний номер карти.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Це не дійсний міжнародний номер банківського рахунку (IBAN).</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Значення не у форматі ISBN-10.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Значення не у форматі ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Значення не відповідає форматам ISBN-10 та ISBN-13.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Значення має невірний формат ISSN.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Значення має невірний формат валюти.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Значення повинно дорівнювати {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Значення має бути більше ніж {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Значення має бути більше або дорівнювати {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Значення має бути ідентичним {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Значення повинно бути менше ніж {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Значення повинно бути менше або дорівнювати {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Значення не повинно дорівнювати {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Значення не повинно бути ідентичним {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>Співвідношення сторін зображення занадто велике ({{ ratio }}). Максимальне співвідношення сторін {{ max_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>Співвідношення сторін зображення занадто мало ({{ ratio }}). Мінімальне співвідношення сторін {{ min_ratio }}.</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>Зображення квадратне ({{ width }}x{{ height }}px). Квадратні зображення не дозволені.</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>Зображення альбомної орієнтації ({{ width }}x{{ height }}px). Зображення альбомної орієнтації не дозволені.</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>Зображення в портретній орієнтації ({{ width }}x{{ height }}px). Зображення в портретної орієнтації не дозволені.</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>Порожні файли не дозволені.</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>Ім'я хоста не знайдено.</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>Значення не збігається з очікуваним {{ charset }} кодуванням.</target>
+ </trans-unit>
+ <trans-unit id="81">
+ <source>This is not a valid Business Identifier Code (BIC).</source>
+ <target>Це не дійсний банківський код (BIC).</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>Помилка</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.vi.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.vi.xlf
new file mode 100644
index 0000000..e1833c7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.vi.xlf
@@ -0,0 +1,283 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>Giá trị này phải là sai.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>Giá trị này phải là đúng.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>Giá trị này phải là kiểu {{ type }}.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>Giá trị này phải rỗng.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>Giá trị bạn vừa chọn không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>Bạn phải chọn ít nhất {{ limit }} lựa chọn.|Bạn phải chọn ít nhất {{ limit }} lựa chọn.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>Bạn phải chọn nhiều nhất {{ limit }} lựa chọn.|Bạn phải chọn nhiều nhất {{ limit }} lựa chọn.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>Một hoặc nhiều giá trị được chọn không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>Lĩnh vực này không được dự kiến.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>Lĩnh vực này là mất tích.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>Giá trị không phải là ngày hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>Giá trị không phải là ngày tháng hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>Giá trị này không phải là email hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>Tập tin không tìm thấy.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>Tập tin không thể đọc được.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Tập tin quá lớn ({{ size }} {{ suffix }}). Kích thước tối đa cho phép {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>Kiểu mime của tập tin không hợp lệ ({{ type }}). Kiểu hợp lệ là {{ types }}.</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>Giá trị phải bằng hoặc nhỏ hơn {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.|Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>Giá trị phải lớn hơn hoặc bằng {{ limit }}.</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.|Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>Giá trị không được phép để trống.</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>Giá trị không được phép rỗng.</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>Giá trị phải rỗng.</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>Giá trị không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>Giá trị không phải là thời gian hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>Giá trị không phải là địa chỉ URL hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>Hai giá trị phải bằng nhau.</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>Tập tin quá lớn. Kích thước tối đa cho phép là {{ limit }} {{ suffix }}.</target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>Tập tin quá lớn.</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>Tập tin không thể tải lên.</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>Giá trị phải là con số.</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This file is not a valid image.</source>
+ <target>Tập tin không phải là hình ảnh.</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This is not a valid IP address.</source>
+ <target>Địa chỉ IP không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This value is not a valid language.</source>
+ <target>Giá trị không phải là ngôn ngữ hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid locale.</source>
+ <target>Giá trị không phải là một bản địa địa phương hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid country.</source>
+ <target>Giá trị không phải là nước hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>Giá trị đã được sử dụng.</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>Kích thước của hình ảnh không thể xác định.</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>Chiều rộng của hình quá lớn ({{ width }}px). Chiều rộng tối đa phải là {{ max_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>Chiều rộng của hình quá thấp ({{ width }}px). Chiều rộng tối thiểu phải là {{ min_width }}px.</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>Chiều cao của hình quá cao ({{ height }}px). Chiều cao tối đa phải là {{ max_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>Chiều cao của hình quá thấp ({{ height }}px). Chiều cao tối thiểu phải là {{ min_height }}px.</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>Giá trị này phải là mật khẩu hiện tại của người dùng.</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>Giá trị phải có chính xác {{ limit }} kí tự.|Giá trị phải có chính xác {{ limit }} kí tự.</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>Tập tin chỉ được tải lên một phần.</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>Tập tin không được tải lên.</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>Thư mục tạm không được định nghĩa trong php.ini.</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>Không thể ghi tập tin tạm ra đĩa.</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>Một PHP extension đã phá hỏng quá trình tải lên của tập tin.</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>Danh sách phải chứa chính xác {{ limit }} thành phần.|Danh sách phải chứa chính xác {{ limit }} thành phần.</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>Số thẻ không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>Thẻ không được hỗ trợ hoặc số thẻ không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>Giá trị không phải là International Bank Account Number (IBAN) hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>Giá trị không phải là ISBN-10 hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>Giá trị không phải là ISBN-13 hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>Giá trị không phải là ISBN-10 hoặc ISBN-13 hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>Giá trị không là ISSN hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>Giá trị không phải là đơn vi tiền tệ hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>Giá trị phải bằng {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>Giá trị phải lớn hơn {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>Giá trị phải lớn hơn hoặc bằng {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Giá trị phải giống {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>Giá trị phải bé hơn {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>Giá trị không được phép nhỏ hơn hoặc bằng {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>Giá trị không được phép bằng {{ compared_value }}.</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>Giá trị không được phép giống như {{ compared_value_type }} {{ compared_value }}.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_CN.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_CN.xlf
new file mode 100644
index 0000000..d4ed03d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_CN.xlf
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>该变量的值应为 false 。</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>该变量的值应为 true 。</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>该变量的类型应为 {{ type }} 。</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>该变量值应为空。</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>选定变量的值不是有效的选项。</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>您至少要选择 {{ limit }} 个选项。</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>您最多能选择 {{ limit }} 个选项。</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>一个或者多个给定的值无效。</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>此字段是多余的。</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>此字段缺失。</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>该值不是一个有效的日期(date)。</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>该值不是一个有效的日期时间(datetime)。</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>该值不是一个有效的邮件地址。</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>文件未找到。</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>文件不可读。</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>文件太大 ({{ size }} {{ suffix }})。文件大小不可以超过 {{ limit }} {{ suffix }} 。</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>无效的文件类型 ({{ type }}) 。允许的文件类型有 {{ types }} 。</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>这个变量的值应该小于或等于 {{ limit }}。</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>字符串太长,长度不可超过 {{ limit }} 个字符。</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>该变量的值应该大于或等于 {{ limit }}。</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>字符串太短,长度不可少于 {{ limit }} 个字符。</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>该变量不应为空。</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>该变量不应为 null 。</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>该变量应为空 null 。</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>该变量值无效 。</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>该值不是一个有效的时间。</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>该值不是一个有效的 URL 。</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>这两个变量的值应该相等。</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>文件太大,文件大小不可以超过 {{ limit }} {{ suffix }}。 </target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>文件太大。</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>无法上传此文件。</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>该值应该为有效的数字。</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This value is not a valid country.</source>
+ <target>该值不是有效的国家名。</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This file is not a valid image.</source>
+ <target>该文件不是有效的图片。</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This is not a valid IP address.</source>
+ <target>该值不是有效的IP地址。</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid language.</source>
+ <target>该值不是有效的语言名。</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid locale.</source>
+ <target>该值不是有效的区域值(locale)。</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>该值已经被使用。</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>不能解析图片大小。</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>图片太宽 ({{ width }}px),最大宽度为 {{ max_width }}px 。</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>图片宽度不够 ({{ width }}px),最小宽度为 {{ min_width }}px 。</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>图片太高 ({{ height }}px),最大高度为 {{ max_height }}px 。</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>图片高度不够 ({{ height }}px),最小高度为 {{ min_height }}px 。</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>该变量的值应为用户当前的密码。</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>该变量应为 {{ limit }} 个字符。</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>该文件的上传不完整。</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>没有上传任何文件。</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>php.ini 里没有配置临时文件目录。</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>临时文件写入磁盘失败。</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>某个 PHP 扩展造成上传失败。</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>该集合最少应包含 {{ limit }} 个元素。</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>该集合最多包含 {{ limit }} 个元素。</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>该集合应包含 {{ limit }} 个元素 element 。</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>无效的信用卡号。</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>不支持的信用卡类型或无效的信用卡号。</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>该值不是有效的国际银行帐号(IBAN)。</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>该值不是有效的10位国际标准书号(ISBN-10)。</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>该值不是有效的13位国际标准书号(ISBN-13)。</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>该值不是有效的国际标准书号(ISBN-10 或 ISBN-13)。</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>该值不是有效的国际标准期刊号(ISSN)。</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>该值不是有效的货币名(currency)。</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>该值应等于 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>该值应大于 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>该值应大于或等于 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>该值应与 {{ compared_value_type }} {{ compared_value }} 相同。</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>该值应小于 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>该值应小于或等于 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>该值不应先等于 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>该值不应与 {{ compared_value_type }} {{ compared_value }} 相同。</target>
+ </trans-unit>
+ <trans-unit id="73">
+ <source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
+ <target>图片宽高比太大 ({{ ratio }})。允许的最大宽高比为 {{ max_ratio }}。</target>
+ </trans-unit>
+ <trans-unit id="74">
+ <source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
+ <target>图片宽高比太小 ({{ ratio }})。允许的最大宽高比为 {{ min_ratio }}。</target>
+ </trans-unit>
+ <trans-unit id="75">
+ <source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
+ <target>图片是方形的 ({{ width }}x{{ height }}px)。不允许使用方形的图片。</target>
+ </trans-unit>
+ <trans-unit id="76">
+ <source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
+ <target>图片是横向的 ({{ width }}x{{ height }}px)。不允许使用横向的图片。</target>
+ </trans-unit>
+ <trans-unit id="77">
+ <source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
+ <target>图片是纵向的 ({{ width }}x{{ height }}px)。不允许使用纵向的图片。</target>
+ </trans-unit>
+ <trans-unit id="78">
+ <source>An empty file is not allowed.</source>
+ <target>不允许使用空文件。</target>
+ </trans-unit>
+ <trans-unit id="79">
+ <source>The host could not be resolved.</source>
+ <target>主机名无法解析。</target>
+ </trans-unit>
+ <trans-unit id="80">
+ <source>This value does not match the expected {{ charset }} charset.</source>
+ <target>该值不符合 {{ charset }} 编码。</target>
+ </trans-unit>
+ <trans-unit id="82">
+ <source>Error</source>
+ <target>错误</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_TW.xlf b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_TW.xlf
new file mode 100644
index 0000000..d9d5f2f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Resources/translations/validators.zh_TW.xlf
@@ -0,0 +1,283 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>This value should be false.</source>
+ <target>該變數的值應為 false 。</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>This value should be true.</source>
+ <target>該變數的值應為 true 。</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>This value should be of type {{ type }}.</source>
+ <target>該變數的類型應為 {{ type }} 。</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>This value should be blank.</source>
+ <target>該變數應為空。</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>The value you selected is not a valid choice.</source>
+ <target>選定變數的值不是有效的選項。</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
+ <target>您至少要選擇 {{ limit }} 個選項。</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
+ <target>您最多能選擇 {{ limit }} 個選項。</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>One or more of the given values is invalid.</source>
+ <target>一個或者多個給定的值無效。</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>This field was not expected.</source>
+ <target>此字段是沒有預料到。</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>This field is missing.</source>
+ <target>此字段缺失。</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>This value is not a valid date.</source>
+ <target>該值不是一個有效的日期(date)。</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>This value is not a valid datetime.</source>
+ <target>該值不是一個有效的日期時間(datetime)。</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>This value is not a valid email address.</source>
+ <target>該值不是一個有效的郵件地址。</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>The file could not be found.</source>
+ <target>找不到檔案。</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>The file is not readable.</source>
+ <target>無法讀取檔案。</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>檔案太大 ({{ size }} {{ suffix }})。檔案大小不可以超過 {{ limit }} {{ suffix }} 。</target>
+ </trans-unit>
+ <trans-unit id="17">
+ <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
+ <target>無效的檔案類型 ({{ type }}) 。允許的檔案類型有 {{ types }} 。</target>
+ </trans-unit>
+ <trans-unit id="18">
+ <source>This value should be {{ limit }} or less.</source>
+ <target>這個變數的值應該小於或等於 {{ limit }}。</target>
+ </trans-unit>
+ <trans-unit id="19">
+ <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
+ <target>字串太長,長度不可超過 {{ limit }} 個字元。</target>
+ </trans-unit>
+ <trans-unit id="20">
+ <source>This value should be {{ limit }} or more.</source>
+ <target>該變數的值應該大於或等於 {{ limit }}。</target>
+ </trans-unit>
+ <trans-unit id="21">
+ <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
+ <target>字串太短,長度不可少於 {{ limit }} 個字元。</target>
+ </trans-unit>
+ <trans-unit id="22">
+ <source>This value should not be blank.</source>
+ <target>該變數不應為空白。</target>
+ </trans-unit>
+ <trans-unit id="23">
+ <source>This value should not be null.</source>
+ <target>該值不應為 null 。</target>
+ </trans-unit>
+ <trans-unit id="24">
+ <source>This value should be null.</source>
+ <target>該值應為 null 。</target>
+ </trans-unit>
+ <trans-unit id="25">
+ <source>This value is not valid.</source>
+ <target>無效的數值 。</target>
+ </trans-unit>
+ <trans-unit id="26">
+ <source>This value is not a valid time.</source>
+ <target>該值不是一個有效的時間。</target>
+ </trans-unit>
+ <trans-unit id="27">
+ <source>This value is not a valid URL.</source>
+ <target>該值不是一個有效的 URL 。</target>
+ </trans-unit>
+ <trans-unit id="31">
+ <source>The two values should be equal.</source>
+ <target>這兩個變數的值應該相等。</target>
+ </trans-unit>
+ <trans-unit id="32">
+ <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
+ <target>檔案太大,檔案大小不可以超過 {{ limit }} {{ suffix }}。 </target>
+ </trans-unit>
+ <trans-unit id="33">
+ <source>The file is too large.</source>
+ <target>檔案太大。</target>
+ </trans-unit>
+ <trans-unit id="34">
+ <source>The file could not be uploaded.</source>
+ <target>無法上傳此檔案。</target>
+ </trans-unit>
+ <trans-unit id="35">
+ <source>This value should be a valid number.</source>
+ <target>該值應該為有效的數字。</target>
+ </trans-unit>
+ <trans-unit id="36">
+ <source>This value is not a valid country.</source>
+ <target>該值不是有效的國家名。</target>
+ </trans-unit>
+ <trans-unit id="37">
+ <source>This file is not a valid image.</source>
+ <target>該檔案不是有效的圖片。</target>
+ </trans-unit>
+ <trans-unit id="38">
+ <source>This is not a valid IP address.</source>
+ <target>該值不是有效的IP地址。</target>
+ </trans-unit>
+ <trans-unit id="39">
+ <source>This value is not a valid language.</source>
+ <target>該值不是有效的語言名。</target>
+ </trans-unit>
+ <trans-unit id="40">
+ <source>This value is not a valid locale.</source>
+ <target>該值不是有效的區域值(locale)。</target>
+ </trans-unit>
+ <trans-unit id="41">
+ <source>This value is already used.</source>
+ <target>該值已經被使用。</target>
+ </trans-unit>
+ <trans-unit id="42">
+ <source>The size of the image could not be detected.</source>
+ <target>不能解析圖片大小。</target>
+ </trans-unit>
+ <trans-unit id="43">
+ <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
+ <target>圖片太寬 ({{ width }}px),最大寬度為 {{ max_width }}px 。</target>
+ </trans-unit>
+ <trans-unit id="44">
+ <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
+ <target>圖片寬度不夠 ({{ width }}px),最小寬度為 {{ min_width }}px 。</target>
+ </trans-unit>
+ <trans-unit id="45">
+ <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
+ <target>圖片太高 ({{ height }}px),最大高度為 {{ max_height }}px 。</target>
+ </trans-unit>
+ <trans-unit id="46">
+ <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
+ <target>圖片高度不夠 ({{ height }}px),最小高度為 {{ min_height }}px 。</target>
+ </trans-unit>
+ <trans-unit id="47">
+ <source>This value should be the user's current password.</source>
+ <target>該變數的值應為用戶目前的密碼。</target>
+ </trans-unit>
+ <trans-unit id="48">
+ <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
+ <target>該變數應為 {{ limit }} 個字元。</target>
+ </trans-unit>
+ <trans-unit id="49">
+ <source>The file was only partially uploaded.</source>
+ <target>該檔案的上傳不完整。</target>
+ </trans-unit>
+ <trans-unit id="50">
+ <source>No file was uploaded.</source>
+ <target>沒有上傳任何檔案。</target>
+ </trans-unit>
+ <trans-unit id="51">
+ <source>No temporary folder was configured in php.ini.</source>
+ <target>php.ini 裡沒有配置臨時目錄。</target>
+ </trans-unit>
+ <trans-unit id="52">
+ <source>Cannot write temporary file to disk.</source>
+ <target>暫存檔寫入磁碟失敗。</target>
+ </trans-unit>
+ <trans-unit id="53">
+ <source>A PHP extension caused the upload to fail.</source>
+ <target>某個 PHP 擴展造成上傳失敗。</target>
+ </trans-unit>
+ <trans-unit id="54">
+ <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
+ <target>該集合最少應包含 {{ limit }} 個元素。</target>
+ </trans-unit>
+ <trans-unit id="55">
+ <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
+ <target>該集合最多包含 {{ limit }} 個元素。</target>
+ </trans-unit>
+ <trans-unit id="56">
+ <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
+ <target>該集合應包含 {{ limit }} 個元素 element 。</target>
+ </trans-unit>
+ <trans-unit id="57">
+ <source>Invalid card number.</source>
+ <target>無效的信用卡號。</target>
+ </trans-unit>
+ <trans-unit id="58">
+ <source>Unsupported card type or invalid card number.</source>
+ <target>不支援的信用卡類型或無效的信用卡號。</target>
+ </trans-unit>
+ <trans-unit id="59">
+ <source>This is not a valid International Bank Account Number (IBAN).</source>
+ <target>該值不是有效的國際銀行帳號(IBAN)。</target>
+ </trans-unit>
+ <trans-unit id="60">
+ <source>This value is not a valid ISBN-10.</source>
+ <target>該值不是有效的10位國際標準書號(ISBN-10)。</target>
+ </trans-unit>
+ <trans-unit id="61">
+ <source>This value is not a valid ISBN-13.</source>
+ <target>該值不是有效的13位國際標準書號(ISBN-13)。</target>
+ </trans-unit>
+ <trans-unit id="62">
+ <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
+ <target>該值不是有效的國際標準書號(ISBN-10 或 ISBN-13)。</target>
+ </trans-unit>
+ <trans-unit id="63">
+ <source>This value is not a valid ISSN.</source>
+ <target>該值不是有效的國際標準期刊號(ISSN)。</target>
+ </trans-unit>
+ <trans-unit id="64">
+ <source>This value is not a valid currency.</source>
+ <target>該值不是有效的貨幣名(currency)。</target>
+ </trans-unit>
+ <trans-unit id="65">
+ <source>This value should be equal to {{ compared_value }}.</source>
+ <target>該值應等於 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="66">
+ <source>This value should be greater than {{ compared_value }}.</source>
+ <target>該值應大於 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="67">
+ <source>This value should be greater than or equal to {{ compared_value }}.</source>
+ <target>該值應大於或等於 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="68">
+ <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>該值應與 {{ compared_value_type }} {{ compared_value }} 相同。</target>
+ </trans-unit>
+ <trans-unit id="69">
+ <source>This value should be less than {{ compared_value }}.</source>
+ <target>該值應小於 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="70">
+ <source>This value should be less than or equal to {{ compared_value }}.</source>
+ <target>該值應小於或等於 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="71">
+ <source>This value should not be equal to {{ compared_value }}.</source>
+ <target>該值應不等於 {{ compared_value }} 。</target>
+ </trans-unit>
+ <trans-unit id="72">
+ <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
+ <target>該值不應與 {{ compared_value_type }} {{ compared_value }} 相同。</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/public/system/storage/vendor/symfony/validator/Tests/ConstraintTest.php b/public/system/storage/vendor/symfony/validator/Tests/ConstraintTest.php
new file mode 100644
index 0000000..a057414
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/ConstraintTest.php
@@ -0,0 +1,245 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintC;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValue;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValueAsDefault;
+
+class ConstraintTest extends TestCase
+{
+ public function testSetProperties()
+ {
+ $constraint = new ConstraintA(array(
+ 'property1' => 'foo',
+ 'property2' => 'bar',
+ ));
+
+ $this->assertEquals('foo', $constraint->property1);
+ $this->assertEquals('bar', $constraint->property2);
+ }
+
+ public function testSetNotExistingPropertyThrowsException()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\InvalidOptionsException');
+
+ new ConstraintA(array(
+ 'foo' => 'bar',
+ ));
+ }
+
+ public function testMagicPropertiesAreNotAllowed()
+ {
+ $constraint = new ConstraintA();
+
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\InvalidOptionsException');
+
+ $constraint->foo = 'bar';
+ }
+
+ public function testInvalidAndRequiredOptionsPassed()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\InvalidOptionsException');
+
+ new ConstraintC(array(
+ 'option1' => 'default',
+ 'foo' => 'bar',
+ ));
+ }
+
+ public function testSetDefaultProperty()
+ {
+ $constraint = new ConstraintA('foo');
+
+ $this->assertEquals('foo', $constraint->property2);
+ }
+
+ public function testSetDefaultPropertyDoctrineStyle()
+ {
+ $constraint = new ConstraintA(array('value' => 'foo'));
+
+ $this->assertEquals('foo', $constraint->property2);
+ }
+
+ public function testSetDefaultPropertyDoctrineStylePlusOtherProperty()
+ {
+ $constraint = new ConstraintA(array('value' => 'foo', 'property1' => 'bar'));
+
+ $this->assertEquals('foo', $constraint->property2);
+ $this->assertEquals('bar', $constraint->property1);
+ }
+
+ public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue()
+ {
+ $constraint = new ConstraintWithValueAsDefault(array('value' => 'foo'));
+
+ $this->assertEquals('foo', $constraint->value);
+ $this->assertNull($constraint->property);
+ }
+
+ public function testDontSetDefaultPropertyIfValuePropertyExists()
+ {
+ $constraint = new ConstraintWithValue(array('value' => 'foo'));
+
+ $this->assertEquals('foo', $constraint->value);
+ $this->assertNull($constraint->property);
+ }
+
+ public function testSetUndefinedDefaultProperty()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+
+ new ConstraintB('foo');
+ }
+
+ public function testRequiredOptionsMustBeDefined()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\MissingOptionsException');
+
+ new ConstraintC();
+ }
+
+ public function testRequiredOptionsPassed()
+ {
+ $constraint = new ConstraintC(array('option1' => 'default'));
+
+ $this->assertSame('default', $constraint->option1);
+ }
+
+ public function testGroupsAreConvertedToArray()
+ {
+ $constraint = new ConstraintA(array('groups' => 'Foo'));
+
+ $this->assertEquals(array('Foo'), $constraint->groups);
+ }
+
+ public function testAddDefaultGroupAddsGroup()
+ {
+ $constraint = new ConstraintA(array('groups' => 'Default'));
+ $constraint->addImplicitGroupName('Foo');
+ $this->assertEquals(array('Default', 'Foo'), $constraint->groups);
+ }
+
+ public function testAllowsSettingZeroRequiredPropertyValue()
+ {
+ $constraint = new ConstraintA(0);
+ $this->assertEquals(0, $constraint->property2);
+ }
+
+ public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray()
+ {
+ $constraint = new ConstraintB(array());
+
+ $this->assertSame(array(Constraint::PROPERTY_CONSTRAINT, Constraint::CLASS_CONSTRAINT), $constraint->getTargets());
+ }
+
+ public function testGetTargetsCanBeString()
+ {
+ $constraint = new ClassConstraint();
+
+ $this->assertEquals('class', $constraint->getTargets());
+ }
+
+ public function testGetTargetsCanBeArray()
+ {
+ $constraint = new ConstraintA();
+
+ $this->assertEquals(array('property', 'class'), $constraint->getTargets());
+ }
+
+ public function testSerialize()
+ {
+ $constraint = new ConstraintA(array(
+ 'property1' => 'foo',
+ 'property2' => 'bar',
+ ));
+
+ $restoredConstraint = unserialize(serialize($constraint));
+
+ $this->assertEquals($constraint, $restoredConstraint);
+ }
+
+ public function testSerializeInitializesGroupsOptionToDefault()
+ {
+ $constraint = new ConstraintA(array(
+ 'property1' => 'foo',
+ 'property2' => 'bar',
+ ));
+
+ $constraint = unserialize(serialize($constraint));
+
+ $expected = new ConstraintA(array(
+ 'property1' => 'foo',
+ 'property2' => 'bar',
+ 'groups' => 'Default',
+ ));
+
+ $this->assertEquals($expected, $constraint);
+ }
+
+ public function testSerializeKeepsCustomGroups()
+ {
+ $constraint = new ConstraintA(array(
+ 'property1' => 'foo',
+ 'property2' => 'bar',
+ 'groups' => 'MyGroup',
+ ));
+
+ $constraint = unserialize(serialize($constraint));
+
+ $this->assertSame(array('MyGroup'), $constraint->groups);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\InvalidArgumentException
+ */
+ public function testGetErrorNameForUnknownCode()
+ {
+ Constraint::getErrorName(1);
+ }
+
+ public function testOptionsAsDefaultOption()
+ {
+ $constraint = new ConstraintA($options = array('value1'));
+
+ $this->assertEquals($options, $constraint->property2);
+
+ $constraint = new ConstraintA($options = array('value1', 'property1' => 'value2'));
+
+ $this->assertEquals($options, $constraint->property2);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\InvalidOptionsException
+ * @expectedExceptionMessage The options "0", "5" do not exist
+ */
+ public function testInvalidOptions()
+ {
+ new ConstraintA(array('property2' => 'foo', 'bar', 5 => 'baz'));
+ }
+
+ public function testOptionsWithInvalidInternalPointer()
+ {
+ $options = array('property1' => 'foo');
+ next($options);
+ next($options);
+
+ $constraint = new ConstraintA($options);
+
+ $this->assertEquals('foo', $constraint->property1);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationListTest.php b/public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationListTest.php
new file mode 100644
index 0000000..a35a1cd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationListTest.php
@@ -0,0 +1,135 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\ConstraintViolation;
+use Symfony\Component\Validator\ConstraintViolationList;
+
+class ConstraintViolationListTest extends TestCase
+{
+ protected $list;
+
+ protected function setUp()
+ {
+ $this->list = new ConstraintViolationList();
+ }
+
+ protected function tearDown()
+ {
+ $this->list = null;
+ }
+
+ public function testInit()
+ {
+ $this->assertCount(0, $this->list);
+ }
+
+ public function testInitWithViolations()
+ {
+ $violation = $this->getViolation('Error');
+ $this->list = new ConstraintViolationList(array($violation));
+
+ $this->assertCount(1, $this->list);
+ $this->assertSame($violation, $this->list[0]);
+ }
+
+ public function testAdd()
+ {
+ $violation = $this->getViolation('Error');
+ $this->list->add($violation);
+
+ $this->assertCount(1, $this->list);
+ $this->assertSame($violation, $this->list[0]);
+ }
+
+ public function testAddAll()
+ {
+ $violations = array(
+ 10 => $this->getViolation('Error 1'),
+ 20 => $this->getViolation('Error 2'),
+ 30 => $this->getViolation('Error 3'),
+ );
+ $otherList = new ConstraintViolationList($violations);
+ $this->list->addAll($otherList);
+
+ $this->assertCount(3, $this->list);
+
+ $this->assertSame($violations[10], $this->list[0]);
+ $this->assertSame($violations[20], $this->list[1]);
+ $this->assertSame($violations[30], $this->list[2]);
+ }
+
+ public function testIterator()
+ {
+ $violations = array(
+ 10 => $this->getViolation('Error 1'),
+ 20 => $this->getViolation('Error 2'),
+ 30 => $this->getViolation('Error 3'),
+ );
+
+ $this->list = new ConstraintViolationList($violations);
+
+ // indices are reset upon adding -> array_values()
+ $this->assertSame(array_values($violations), iterator_to_array($this->list));
+ }
+
+ public function testArrayAccess()
+ {
+ $violation = $this->getViolation('Error');
+ $this->list[] = $violation;
+
+ $this->assertSame($violation, $this->list[0]);
+ $this->assertArrayHasKey(0, $this->list);
+
+ unset($this->list[0]);
+
+ $this->assertArrayNotHasKey(0, $this->list);
+
+ $this->list[10] = $violation;
+
+ $this->assertSame($violation, $this->list[10]);
+ $this->assertArrayHasKey(10, $this->list);
+ }
+
+ public function testToString()
+ {
+ $this->list = new ConstraintViolationList(array(
+ $this->getViolation('Error 1', 'Root'),
+ $this->getViolation('Error 2', 'Root', 'foo.bar'),
+ $this->getViolation('Error 3', 'Root', '[baz]'),
+ $this->getViolation('Error 4', '', 'foo.bar'),
+ $this->getViolation('Error 5', '', '[baz]'),
+ ));
+
+ $expected = <<<'EOF'
+Root:
+ Error 1
+Root.foo.bar:
+ Error 2
+Root[baz]:
+ Error 3
+foo.bar:
+ Error 4
+[baz]:
+ Error 5
+
+EOF;
+
+ $this->assertEquals($expected, (string) $this->list);
+ }
+
+ protected function getViolation($message, $root = null, $propertyPath = null)
+ {
+ return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationTest.php b/public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationTest.php
new file mode 100644
index 0000000..cef4782
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/ConstraintViolationTest.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\ConstraintViolation;
+
+class ConstraintViolationTest extends TestCase
+{
+ public function testToStringHandlesArrays()
+ {
+ $violation = new ConstraintViolation(
+ 'Array',
+ '{{ value }}',
+ array('{{ value }}' => array(1, 2, 3)),
+ 'Root',
+ 'property.path',
+ null
+ );
+
+ $expected = <<<'EOF'
+Root.property.path:
+ Array
+EOF;
+
+ $this->assertSame($expected, (string) $violation);
+ }
+
+ public function testToStringHandlesArrayRoots()
+ {
+ $violation = new ConstraintViolation(
+ '42 cannot be used here',
+ 'this is the message template',
+ array(),
+ array('some_value' => 42),
+ 'some_value',
+ null
+ );
+
+ $expected = <<<'EOF'
+Array.some_value:
+ 42 cannot be used here
+EOF;
+
+ $this->assertSame($expected, (string) $violation);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php
new file mode 100644
index 0000000..d593aac
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php
@@ -0,0 +1,192 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Intl\Util\IntlTestHelper;
+use Symfony\Component\Validator\Constraint;
+
+class ComparisonTest_Class
+{
+ protected $value;
+
+ public function __construct($value)
+ {
+ $this->value = $value;
+ }
+
+ public function __toString()
+ {
+ return (string) $this->value;
+ }
+}
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+abstract class AbstractComparisonValidatorTestCase extends AbstractConstraintValidatorTest
+{
+ protected static function addPhp5Dot5Comparisons(array $comparisons)
+ {
+ if (\PHP_VERSION_ID < 50500) {
+ return $comparisons;
+ }
+
+ $result = $comparisons;
+
+ // Duplicate all tests involving DateTime objects to be tested with
+ // DateTimeImmutable objects as well
+ foreach ($comparisons as $comparison) {
+ $add = false;
+
+ foreach ($comparison as $i => $value) {
+ if ($value instanceof \DateTime) {
+ $comparison[$i] = new \DateTimeImmutable(
+ $value->format('Y-m-d H:i:s.u e'),
+ $value->getTimezone()
+ );
+ $add = true;
+ } elseif ('DateTime' === $value) {
+ $comparison[$i] = 'DateTimeImmutable';
+ $add = true;
+ }
+ }
+
+ if ($add) {
+ $result[] = $comparison;
+ }
+ }
+
+ return $result;
+ }
+
+ public function provideInvalidConstraintOptions()
+ {
+ return array(
+ array(null),
+ array(array()),
+ );
+ }
+
+ /**
+ * @dataProvider provideInvalidConstraintOptions
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testThrowsConstraintExceptionIfNoValueOrProperty($options)
+ {
+ $this->createConstraint($options);
+ }
+
+ /**
+ * @dataProvider provideAllValidComparisons
+ *
+ * @param mixed $dirtyValue
+ * @param mixed $comparisonValue
+ */
+ public function testValidComparisonToValue($dirtyValue, $comparisonValue)
+ {
+ $constraint = $this->createConstraint(array('value' => $comparisonValue));
+
+ $this->validator->validate($dirtyValue, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @return array
+ */
+ public function provideAllValidComparisons()
+ {
+ // The provider runs before setUp(), so we need to manually fix
+ // the default timezone
+ $this->setDefaultTimezone('UTC');
+
+ $comparisons = self::addPhp5Dot5Comparisons($this->provideValidComparisons());
+
+ $this->restoreDefaultTimezone();
+
+ return $comparisons;
+ }
+
+ /**
+ * @return array
+ */
+ abstract public function provideValidComparisons();
+
+ /**
+ * @dataProvider provideAllInvalidComparisons
+ *
+ * @param mixed $dirtyValue
+ * @param mixed $dirtyValueAsString
+ * @param mixed $comparedValue
+ * @param mixed $comparedValueString
+ * @param string $comparedValueType
+ */
+ public function testInvalidComparisonToValue($dirtyValue, $dirtyValueAsString, $comparedValue, $comparedValueString, $comparedValueType)
+ {
+ // Conversion of dates to string differs between ICU versions
+ // Make sure we have the correct version loaded
+ if ($dirtyValue instanceof \DateTime || $dirtyValue instanceof \DateTimeInterface) {
+ IntlTestHelper::requireIntl($this, '57.1');
+
+ if (\PHP_VERSION_ID < 50304 && !(\extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) {
+ $this->markTestSkipped('Intl supports formatting DateTime objects since 5.3.4');
+ }
+ }
+
+ $constraint = $this->createConstraint(array('value' => $comparedValue));
+ $constraint->message = 'Constraint Message';
+
+ $this->validator->validate($dirtyValue, $constraint);
+
+ $this->buildViolation('Constraint Message')
+ ->setParameter('{{ value }}', $dirtyValueAsString)
+ ->setParameter('{{ compared_value }}', $comparedValueString)
+ ->setParameter('{{ compared_value_type }}', $comparedValueType)
+ ->setCode($this->getErrorCode())
+ ->assertRaised();
+ }
+
+ /**
+ * @return array
+ */
+ public function provideAllInvalidComparisons()
+ {
+ // The provider runs before setUp(), so we need to manually fix
+ // the default timezone
+ $this->setDefaultTimezone('UTC');
+
+ $comparisons = self::addPhp5Dot5Comparisons($this->provideInvalidComparisons());
+
+ $this->restoreDefaultTimezone();
+
+ return $comparisons;
+ }
+
+ /**
+ * @return array
+ */
+ abstract public function provideInvalidComparisons();
+
+ /**
+ * @param array|null $options Options for the constraint
+ *
+ * @return Constraint
+ */
+ abstract protected function createConstraint(array $options = null);
+
+ /**
+ * @return string|null
+ */
+ protected function getErrorCode()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractConstraintValidatorTest.php
new file mode 100644
index 0000000..fe505c0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AbstractConstraintValidatorTest.php
@@ -0,0 +1,441 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\Assert;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\ConstraintValidatorInterface;
+use Symfony\Component\Validator\ConstraintViolation;
+use Symfony\Component\Validator\Context\ExecutionContext;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Context\LegacyExecutionContext;
+use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\PropertyMetadata;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class AbstractConstraintValidatorTest extends TestCase
+{
+ /**
+ * @var ExecutionContextInterface
+ */
+ protected $context;
+
+ /**
+ * @var ConstraintValidatorInterface
+ */
+ protected $validator;
+
+ protected $group;
+ protected $metadata;
+ protected $object;
+ protected $value;
+ protected $root;
+ protected $propertyPath;
+ protected $constraint;
+ protected $defaultTimezone;
+
+ protected function setUp()
+ {
+ $this->group = 'MyGroup';
+ $this->metadata = null;
+ $this->object = null;
+ $this->value = 'InvalidValue';
+ $this->root = 'root';
+ $this->propertyPath = 'property.path';
+
+ // Initialize the context with some constraint so that we can
+ // successfully build a violation.
+ $this->constraint = new NotNull();
+
+ $this->context = $this->createContext();
+ $this->validator = $this->createValidator();
+ $this->validator->initialize($this->context);
+
+ \Locale::setDefault('en');
+
+ $this->setDefaultTimezone('UTC');
+ }
+
+ protected function tearDown()
+ {
+ $this->restoreDefaultTimezone();
+ }
+
+ protected function setDefaultTimezone($defaultTimezone)
+ {
+ // Make sure this method can not be called twice before calling
+ // also restoreDefaultTimezone()
+ if (null === $this->defaultTimezone) {
+ $this->defaultTimezone = date_default_timezone_get();
+ date_default_timezone_set($defaultTimezone);
+ }
+ }
+
+ protected function restoreDefaultTimezone()
+ {
+ if (null !== $this->defaultTimezone) {
+ date_default_timezone_set($this->defaultTimezone);
+ $this->defaultTimezone = null;
+ }
+ }
+
+ protected function createContext()
+ {
+ $translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
+ $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
+ $contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock();
+
+ switch ($this->getApiVersion()) {
+ case Validation::API_VERSION_2_5:
+ $context = new ExecutionContext(
+ $validator,
+ $this->root,
+ $translator
+ );
+ break;
+ case Validation::API_VERSION_2_4:
+ case Validation::API_VERSION_2_5_BC:
+ $context = new LegacyExecutionContext(
+ $validator,
+ $this->root,
+ $this->getMockBuilder('Symfony\Component\Validator\MetadataFactoryInterface')->getMock(),
+ $translator
+ );
+ break;
+ default:
+ throw new \RuntimeException('Invalid API version');
+ }
+
+ $context->setGroup($this->group);
+ $context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
+ $context->setConstraint($this->constraint);
+
+ $validator->expects($this->any())
+ ->method('inContext')
+ ->with($context)
+ ->will($this->returnValue($contextualValidator));
+
+ return $context;
+ }
+
+ /**
+ * @param mixed $message
+ * @param array $parameters
+ * @param string $propertyPath
+ * @param string $invalidValue
+ * @param null $plural
+ * @param null $code
+ *
+ * @return ConstraintViolation
+ *
+ * @deprecated to be removed in Symfony 3.0. Use {@link buildViolation()} instead.
+ */
+ protected function createViolation($message, array $parameters = array(), $propertyPath = 'property.path', $invalidValue = 'InvalidValue', $plural = null, $code = null)
+ {
+ return new ConstraintViolation(
+ null,
+ $message,
+ $parameters,
+ $this->root,
+ $propertyPath,
+ $invalidValue,
+ $plural,
+ $code,
+ $this->constraint
+ );
+ }
+
+ protected function setGroup($group)
+ {
+ $this->group = $group;
+ $this->context->setGroup($group);
+ }
+
+ protected function setObject($object)
+ {
+ $this->object = $object;
+ $this->metadata = \is_object($object)
+ ? new ClassMetadata(\get_class($object))
+ : null;
+
+ $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
+ }
+
+ protected function setProperty($object, $property)
+ {
+ $this->object = $object;
+ $this->metadata = \is_object($object)
+ ? new PropertyMetadata(\get_class($object), $property)
+ : null;
+
+ $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
+ }
+
+ protected function setValue($value)
+ {
+ $this->value = $value;
+ $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
+ }
+
+ protected function setRoot($root)
+ {
+ $this->root = $root;
+ $this->context = $this->createContext();
+ $this->validator->initialize($this->context);
+ }
+
+ protected function setPropertyPath($propertyPath)
+ {
+ $this->propertyPath = $propertyPath;
+ $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
+ }
+
+ protected function expectNoValidate()
+ {
+ $validator = $this->context->getValidator()->inContext($this->context);
+ $validator->expects($this->never())
+ ->method('atPath');
+ $validator->expects($this->never())
+ ->method('validate');
+ }
+
+ protected function expectValidateAt($i, $propertyPath, $value, $group)
+ {
+ $validator = $this->context->getValidator()->inContext($this->context);
+ $validator->expects($this->at(2 * $i))
+ ->method('atPath')
+ ->with($propertyPath)
+ ->will($this->returnValue($validator));
+ $validator->expects($this->at(2 * $i + 1))
+ ->method('validate')
+ ->with($value, $this->logicalOr(null, array(), $this->isInstanceOf('\Symfony\Component\Validator\Constraints\Valid')), $group);
+ }
+
+ protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null)
+ {
+ $contextualValidator = $this->context->getValidator()->inContext($this->context);
+ $contextualValidator->expects($this->at(2 * $i))
+ ->method('atPath')
+ ->with($propertyPath)
+ ->will($this->returnValue($contextualValidator));
+ $contextualValidator->expects($this->at(2 * $i + 1))
+ ->method('validate')
+ ->with($value, $constraints, $group);
+ }
+
+ protected function assertNoViolation()
+ {
+ $this->assertSame(0, $violationsCount = \count($this->context->getViolations()), sprintf('0 violation expected. Got %u.', $violationsCount));
+ }
+
+ /**
+ * @param mixed $message
+ * @param array $parameters
+ * @param string $propertyPath
+ * @param string $invalidValue
+ * @param null $plural
+ * @param null $code
+ *
+ * @deprecated To be removed in Symfony 3.0. Use
+ * {@link buildViolation()} instead.
+ */
+ protected function assertViolation($message, array $parameters = array(), $propertyPath = 'property.path', $invalidValue = 'InvalidValue', $plural = null, $code = null)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0. Use the buildViolation() method instead.', E_USER_DEPRECATED);
+
+ $this->buildViolation($message)
+ ->setParameters($parameters)
+ ->atPath($propertyPath)
+ ->setInvalidValue($invalidValue)
+ ->setCode($code)
+ ->setPlural($plural)
+ ->assertRaised();
+ }
+
+ /**
+ * @param array $expected
+ *
+ * @deprecated To be removed in Symfony 3.0. Use
+ * {@link buildViolation()} instead.
+ */
+ protected function assertViolations(array $expected)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0. Use the buildViolation() method instead.', E_USER_DEPRECATED);
+
+ $violations = $this->context->getViolations();
+
+ $this->assertCount(\count($expected), $violations);
+
+ $i = 0;
+
+ foreach ($expected as $violation) {
+ $this->assertEquals($violation, $violations[$i++]);
+ }
+ }
+
+ /**
+ * @param $message
+ *
+ * @return ConstraintViolationAssertion
+ */
+ protected function buildViolation($message)
+ {
+ return new ConstraintViolationAssertion($this->context, $message, $this->constraint);
+ }
+
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ abstract protected function createValidator();
+}
+
+/**
+ * @internal
+ */
+class ConstraintViolationAssertion
+{
+ /**
+ * @var LegacyExecutionContextInterface
+ */
+ private $context;
+
+ /**
+ * @var ConstraintViolationAssertion[]
+ */
+ private $assertions;
+
+ private $message;
+ private $parameters = array();
+ private $invalidValue = 'InvalidValue';
+ private $propertyPath = 'property.path';
+ private $translationDomain;
+ private $plural;
+ private $code;
+ private $constraint;
+ private $cause;
+
+ public function __construct(LegacyExecutionContextInterface $context, $message, Constraint $constraint = null, array $assertions = array())
+ {
+ $this->context = $context;
+ $this->message = $message;
+ $this->constraint = $constraint;
+ $this->assertions = $assertions;
+ }
+
+ public function atPath($path)
+ {
+ $this->propertyPath = $path;
+
+ return $this;
+ }
+
+ public function setParameter($key, $value)
+ {
+ $this->parameters[$key] = $value;
+
+ return $this;
+ }
+
+ public function setParameters(array $parameters)
+ {
+ $this->parameters = $parameters;
+
+ return $this;
+ }
+
+ public function setTranslationDomain($translationDomain)
+ {
+ $this->translationDomain = $translationDomain;
+
+ return $this;
+ }
+
+ public function setInvalidValue($invalidValue)
+ {
+ $this->invalidValue = $invalidValue;
+
+ return $this;
+ }
+
+ public function setPlural($number)
+ {
+ $this->plural = $number;
+
+ return $this;
+ }
+
+ public function setCode($code)
+ {
+ $this->code = $code;
+
+ return $this;
+ }
+
+ public function setCause($cause)
+ {
+ $this->cause = $cause;
+
+ return $this;
+ }
+
+ public function buildNextViolation($message)
+ {
+ $assertions = $this->assertions;
+ $assertions[] = $this;
+
+ return new self($this->context, $message, $this->constraint, $assertions);
+ }
+
+ public function assertRaised()
+ {
+ $expected = array();
+ foreach ($this->assertions as $assertion) {
+ $expected[] = $assertion->getViolation();
+ }
+ $expected[] = $this->getViolation();
+
+ $violations = iterator_to_array($this->context->getViolations());
+
+ Assert::assertSame($expectedCount = \count($expected), $violationsCount = \count($violations), sprintf('%u violation(s) expected. Got %u.', $expectedCount, $violationsCount));
+
+ reset($violations);
+
+ foreach ($expected as $violation) {
+ Assert::assertEquals($violation, current($violations));
+ next($violations);
+ }
+ }
+
+ private function getViolation()
+ {
+ return new ConstraintViolation(
+ null,
+ $this->message,
+ $this->parameters,
+ $this->context->getRoot(),
+ $this->propertyPath,
+ $this->invalidValue,
+ $this->plural,
+ $this->code,
+ $this->constraint,
+ $this->cause
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/AllTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AllTest.php
new file mode 100644
index 0000000..25e71a1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AllTest.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\All;
+use Symfony\Component\Validator\Constraints\Valid;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class AllTest extends TestCase
+{
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectNonConstraints()
+ {
+ new All(array(
+ 'foo',
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectValidConstraint()
+ {
+ new All(array(
+ new Valid(),
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/AllValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AllValidatorTest.php
new file mode 100644
index 0000000..57dd600
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/AllValidatorTest.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\All;
+use Symfony\Component\Validator\Constraints\AllValidator;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Range;
+use Symfony\Component\Validator\Validation;
+
+class AllValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new AllValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new All(new Range(array('min' => 4))));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testThrowsExceptionIfNotTraversable()
+ {
+ $this->validator->validate('foo.barbar', new All(new Range(array('min' => 4))));
+ }
+
+ /**
+ * @dataProvider getValidArguments
+ */
+ public function testWalkSingleConstraint($array)
+ {
+ $constraint = new Range(array('min' => 4));
+
+ $i = 0;
+
+ foreach ($array as $key => $value) {
+ $this->expectValidateValueAt($i++, '['.$key.']', $value, array($constraint));
+ }
+
+ $this->validator->validate($array, new All($constraint));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getValidArguments
+ */
+ public function testWalkMultipleConstraints($array)
+ {
+ $constraint1 = new Range(array('min' => 4));
+ $constraint2 = new NotNull();
+
+ $constraints = array($constraint1, $constraint2);
+
+ $i = 0;
+
+ foreach ($array as $key => $value) {
+ $this->expectValidateValueAt($i++, '['.$key.']', $value, array($constraint1, $constraint2));
+ }
+
+ $this->validator->validate($array, new All($constraints));
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidArguments()
+ {
+ return array(
+ array(array(5, 6, 7)),
+ array(new \ArrayObject(array(5, 6, 7))),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/BicValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/BicValidatorTest.php
new file mode 100644
index 0000000..0646e44
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/BicValidatorTest.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Bic;
+use Symfony\Component\Validator\Constraints\BicValidator;
+
+class BicValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function createValidator()
+ {
+ return new BicValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Bic());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Bic());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getValidBics
+ */
+ public function testValidBics($bic)
+ {
+ $this->validator->validate($bic, new Bic());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidBics()
+ {
+ // http://formvalidation.io/validators/bic/
+ return array(
+ array('ASPKAT2LXXX'),
+ array('ASPKAT2L'),
+ array('DSBACNBXSHA'),
+ array('UNCRIT2B912'),
+ array('DABADKKK'),
+ array('RZOOAT2L303'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidBics
+ */
+ public function testInvalidBics($bic, $code)
+ {
+ $constraint = new Bic(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($bic, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$bic.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidBics()
+ {
+ return array(
+ array('DEUTD', Bic::INVALID_LENGTH_ERROR),
+ array('ASPKAT2LXX', Bic::INVALID_LENGTH_ERROR),
+ array('ASPKAT2LX', Bic::INVALID_LENGTH_ERROR),
+ array('ASPKAT2LXXX1', Bic::INVALID_LENGTH_ERROR),
+ array('DABADKK', Bic::INVALID_LENGTH_ERROR),
+ array('1SBACNBXSHA', Bic::INVALID_BANK_CODE_ERROR),
+ array('RZ00AT2L303', Bic::INVALID_BANK_CODE_ERROR),
+ array('D2BACNBXSHA', Bic::INVALID_BANK_CODE_ERROR),
+ array('DS3ACNBXSHA', Bic::INVALID_BANK_CODE_ERROR),
+ array('DSB4CNBXSHA', Bic::INVALID_BANK_CODE_ERROR),
+ array('DEUT12HH', Bic::INVALID_COUNTRY_CODE_ERROR),
+ array('DSBAC6BXSHA', Bic::INVALID_COUNTRY_CODE_ERROR),
+ array('DSBA5NBXSHA', Bic::INVALID_COUNTRY_CODE_ERROR),
+
+ // branch code error
+ array('THISSVAL1D]', Bic::INVALID_CHARACTERS_ERROR),
+
+ // location code error
+ array('DEUTDEF]', Bic::INVALID_CHARACTERS_ERROR),
+
+ // lower case values are invalid
+ array('DeutAT2LXXX', Bic::INVALID_CASE_ERROR),
+ array('DEUTAT2lxxx', Bic::INVALID_CASE_ERROR),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/BlankValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/BlankValidatorTest.php
new file mode 100644
index 0000000..17d8bfb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/BlankValidatorTest.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Blank;
+use Symfony\Component\Validator\Constraints\BlankValidator;
+use Symfony\Component\Validator\Validation;
+
+class BlankValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new BlankValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Blank());
+
+ $this->assertNoViolation();
+ }
+
+ public function testBlankIsValid()
+ {
+ $this->validator->validate('', new Blank());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidValues
+ */
+ public function testInvalidValues($value, $valueAsString)
+ {
+ $constraint = new Blank(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $valueAsString)
+ ->setCode(Blank::NOT_BLANK_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidValues()
+ {
+ return array(
+ array('foobar', '"foobar"'),
+ array(0, '0'),
+ array(false, 'false'),
+ array(1234, '1234'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CallbackValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CallbackValidatorTest.php
new file mode 100644
index 0000000..e87c9c4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CallbackValidatorTest.php
@@ -0,0 +1,351 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\CallbackValidator;
+use Symfony\Component\Validator\ExecutionContextInterface;
+use Symfony\Component\Validator\Validation;
+
+class CallbackValidatorTest_Class
+{
+ public static function validateCallback($object, ExecutionContextInterface $context)
+ {
+ $context->addViolation('Callback message', array('{{ value }}' => 'foobar'));
+
+ return false;
+ }
+}
+
+class CallbackValidatorTest_Object
+{
+ public function validate(ExecutionContextInterface $context)
+ {
+ $context->addViolation('My message', array('{{ value }}' => 'foobar'));
+
+ return false;
+ }
+
+ public static function validateStatic($object, ExecutionContextInterface $context)
+ {
+ $context->addViolation('Static message', array('{{ value }}' => 'baz'));
+
+ return false;
+ }
+}
+
+class CallbackValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new CallbackValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Callback());
+
+ $this->assertNoViolation();
+ }
+
+ public function testSingleMethod()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback('validate');
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testSingleMethodExplicitName()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array('callback' => 'validate'));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testSingleStaticMethod()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback('validateStatic');
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('Static message')
+ ->setParameter('{{ value }}', 'baz')
+ ->assertRaised();
+ }
+
+ public function testClosure()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(function ($object, ExecutionContextInterface $context) {
+ $context->addViolation('My message', array('{{ value }}' => 'foobar'));
+
+ return false;
+ });
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testClosureNullObject()
+ {
+ $constraint = new Callback(function ($object, ExecutionContextInterface $context) {
+ $context->addViolation('My message', array('{{ value }}' => 'foobar'));
+
+ return false;
+ });
+
+ $this->validator->validate(null, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testClosureExplicitName()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array(
+ 'callback' => function ($object, ExecutionContextInterface $context) {
+ $context->addViolation('My message', array('{{ value }}' => 'foobar'));
+
+ return false;
+ },
+ ));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testArrayCallable()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array(__CLASS__.'_Class', 'validateCallback'));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('Callback message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testArrayCallableNullObject()
+ {
+ $constraint = new Callback(array(__CLASS__.'_Class', 'validateCallback'));
+
+ $this->validator->validate(null, $constraint);
+
+ $this->buildViolation('Callback message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ public function testArrayCallableExplicitName()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array(
+ 'callback' => array(__CLASS__.'_Class', 'validateCallback'),
+ ));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('Callback message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacySingleMethodBc()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array('validate'));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacySingleMethodBcExplicitName()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array('methods' => array('validate')));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyMultipleMethodsBc()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array('validate', 'validateStatic'));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->buildNextViolation('Static message')
+ ->setParameter('{{ value }}', 'baz')
+ ->assertRaised();
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyMultipleMethodsBcExplicitName()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array(
+ 'methods' => array('validate', 'validateStatic'),
+ ));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('My message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->buildNextViolation('Static message')
+ ->setParameter('{{ value }}', 'baz')
+ ->assertRaised();
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacySingleStaticMethodBc()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array(
+ array(__CLASS__.'_Class', 'validateCallback'),
+ ));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('Callback message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacySingleStaticMethodBcExplicitName()
+ {
+ $object = new CallbackValidatorTest_Object();
+ $constraint = new Callback(array(
+ 'methods' => array(array(__CLASS__.'_Class', 'validateCallback')),
+ ));
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('Callback message')
+ ->setParameter('{{ value }}', 'foobar')
+ ->assertRaised();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testExpectValidMethods()
+ {
+ $object = new CallbackValidatorTest_Object();
+
+ $this->validator->validate($object, new Callback(array('callback' => array('foobar'))));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testExpectValidCallbacks()
+ {
+ $object = new CallbackValidatorTest_Object();
+
+ $this->validator->validate($object, new Callback(array('callback' => array('foo', 'bar'))));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ * @group legacy
+ */
+ public function testLegacyExpectEitherCallbackOrMethods()
+ {
+ $object = new CallbackValidatorTest_Object();
+
+ $this->validator->validate($object, new Callback(array(
+ 'callback' => 'validate',
+ 'methods' => array('validateStatic'),
+ )));
+ }
+
+ public function testConstraintGetTargets()
+ {
+ $constraint = new Callback(array());
+ $targets = array(Constraint::CLASS_CONSTRAINT, Constraint::PROPERTY_CONSTRAINT);
+
+ $this->assertEquals($targets, $constraint->getTargets());
+ }
+
+ // Should succeed. Needed when defining constraints as annotations.
+ public function testNoConstructorArguments()
+ {
+ $constraint = new Callback();
+
+ $this->assertSame(array(Constraint::CLASS_CONSTRAINT, Constraint::PROPERTY_CONSTRAINT), $constraint->getTargets());
+ }
+
+ public function testAnnotationInvocationSingleValued()
+ {
+ $constraint = new Callback(array('value' => 'validateStatic'));
+
+ $this->assertEquals(new Callback('validateStatic'), $constraint);
+ }
+
+ public function testAnnotationInvocationMultiValued()
+ {
+ $constraint = new Callback(array('value' => array(__CLASS__.'_Class', 'validateCallback')));
+
+ $this->assertEquals(new Callback(array(__CLASS__.'_Class', 'validateCallback')), $constraint);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CardSchemeValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CardSchemeValidatorTest.php
new file mode 100644
index 0000000..22c9644
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CardSchemeValidatorTest.php
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\CardScheme;
+use Symfony\Component\Validator\Constraints\CardSchemeValidator;
+use Symfony\Component\Validator\Validation;
+
+class CardSchemeValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new CardSchemeValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new CardScheme(array('schemes' => array())));
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new CardScheme(array('schemes' => array())));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getValidNumbers
+ */
+ public function testValidNumbers($scheme, $number)
+ {
+ $this->validator->validate($number, new CardScheme(array('schemes' => $scheme)));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidNumbers
+ */
+ public function testInvalidNumbers($scheme, $number, $code)
+ {
+ $constraint = new CardScheme(array(
+ 'schemes' => $scheme,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($number, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', \is_string($number) ? '"'.$number.'"' : $number)
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getValidNumbers()
+ {
+ return array(
+ array('AMEX', '378282246310005'),
+ array('AMEX', '371449635398431'),
+ array('AMEX', '378734493671000'),
+ array('AMEX', '347298508610146'),
+ array('CHINA_UNIONPAY', '6228888888888888'),
+ array('CHINA_UNIONPAY', '62288888888888888'),
+ array('CHINA_UNIONPAY', '622888888888888888'),
+ array('CHINA_UNIONPAY', '6228888888888888888'),
+ array('DINERS', '30569309025904'),
+ array('DINERS', '36088894118515'),
+ array('DINERS', '38520000023237'),
+ array('DISCOVER', '6011111111111117'),
+ array('DISCOVER', '6011000990139424'),
+ array('INSTAPAYMENT', '6372476031350068'),
+ array('INSTAPAYMENT', '6385537775789749'),
+ array('INSTAPAYMENT', '6393440808445746'),
+ array('JCB', '3530111333300000'),
+ array('JCB', '3566002020360505'),
+ array('JCB', '213112345678901'),
+ array('JCB', '180012345678901'),
+ array('LASER', '6304678107004080'),
+ array('LASER', '6706440607428128629'),
+ array('LASER', '6771656738314582216'),
+ array('MAESTRO', '6759744069209'),
+ array('MAESTRO', '5020507657408074712'),
+ array('MAESTRO', '5612559223580173965'),
+ array('MAESTRO', '6759744069209'),
+ array('MAESTRO', '6594371785970435599'),
+ array('MASTERCARD', '5555555555554444'),
+ array('MASTERCARD', '5105105105105100'),
+ array('MASTERCARD', '2221005555554444'),
+ array('MASTERCARD', '2230000000000000'),
+ array('MASTERCARD', '2300000000000000'),
+ array('MASTERCARD', '2699999999999999'),
+ array('MASTERCARD', '2709999999999999'),
+ array('MASTERCARD', '2720995105105100'),
+ array('VISA', '4111111111111111'),
+ array('VISA', '4012888888881881'),
+ array('VISA', '4222222222222'),
+ array('VISA', '4917610000000000003'),
+ array(array('AMEX', 'VISA'), '4111111111111111'),
+ array(array('AMEX', 'VISA'), '378282246310005'),
+ array(array('JCB', 'MASTERCARD'), '5105105105105100'),
+ array(array('VISA', 'MASTERCARD'), '5105105105105100'),
+ );
+ }
+
+ public function getInvalidNumbers()
+ {
+ return array(
+ array('VISA', '42424242424242424242', CardScheme::INVALID_FORMAT_ERROR),
+ array('AMEX', '357298508610146', CardScheme::INVALID_FORMAT_ERROR),
+ array('DINERS', '31569309025904', CardScheme::INVALID_FORMAT_ERROR),
+ array('DINERS', '37088894118515', CardScheme::INVALID_FORMAT_ERROR),
+ array('INSTAPAYMENT', '6313440808445746', CardScheme::INVALID_FORMAT_ERROR),
+ array('CHINA_UNIONPAY', '622888888888888', CardScheme::INVALID_FORMAT_ERROR),
+ array('CHINA_UNIONPAY', '62288888888888888888', CardScheme::INVALID_FORMAT_ERROR),
+ array('AMEX', '30569309025904', CardScheme::INVALID_FORMAT_ERROR), // DINERS number
+ array('AMEX', 'invalid', CardScheme::NOT_NUMERIC_ERROR), // A string
+ array('AMEX', 0, CardScheme::INVALID_FORMAT_ERROR), // a lone number
+ array('AMEX', '0', CardScheme::INVALID_FORMAT_ERROR), // a lone number
+ array('AMEX', '000000000000', CardScheme::INVALID_FORMAT_ERROR), // a lone number
+ array('DINERS', '3056930', CardScheme::INVALID_FORMAT_ERROR), // only first part of the number
+ array('DISCOVER', '1117', CardScheme::INVALID_FORMAT_ERROR), // only last 4 digits
+ array('MASTERCARD', '2721001234567890', CardScheme::INVALID_FORMAT_ERROR), // Not assigned yet
+ array('MASTERCARD', '2220991234567890', CardScheme::INVALID_FORMAT_ERROR), // Not assigned yet
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/ChoiceValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ChoiceValidatorTest.php
new file mode 100644
index 0000000..b515b84
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ChoiceValidatorTest.php
@@ -0,0 +1,304 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Choice;
+use Symfony\Component\Validator\Constraints\ChoiceValidator;
+use Symfony\Component\Validator\Validation;
+
+function choice_callback()
+{
+ return array('foo', 'bar');
+}
+
+class ChoiceValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new ChoiceValidator();
+ }
+
+ public static function staticCallback()
+ {
+ return array('foo', 'bar');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectArrayIfMultipleIsTrue()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array('foo', 'bar'),
+ 'multiple' => true,
+ ));
+
+ $this->validator->validate('asdf', $constraint);
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Choice(array('choices' => array('foo', 'bar'))));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testChoicesOrCallbackExpected()
+ {
+ $this->validator->validate('foobar', new Choice());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testValidCallbackExpected()
+ {
+ $this->validator->validate('foobar', new Choice(array('callback' => 'abcd')));
+ }
+
+ public function testValidChoiceArray()
+ {
+ $constraint = new Choice(array('choices' => array('foo', 'bar')));
+
+ $this->validator->validate('bar', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidChoiceCallbackFunction()
+ {
+ $constraint = new Choice(array('callback' => __NAMESPACE__.'\choice_callback'));
+
+ $this->validator->validate('bar', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidChoiceCallbackClosure()
+ {
+ $constraint = new Choice(array('callback' => function () {
+ return array('foo', 'bar');
+ }));
+
+ $this->validator->validate('bar', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidChoiceCallbackStaticMethod()
+ {
+ $constraint = new Choice(array('callback' => array(__CLASS__, 'staticCallback')));
+
+ $this->validator->validate('bar', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidChoiceCallbackContextMethod()
+ {
+ // search $this for "staticCallback"
+ $this->setObject($this);
+
+ $constraint = new Choice(array('callback' => 'staticCallback'));
+
+ $this->validator->validate('bar', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testMultipleChoices()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array('foo', 'bar', 'baz'),
+ 'multiple' => true,
+ ));
+
+ $this->validator->validate(array('baz', 'bar'), $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testInvalidChoice()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array('foo', 'bar'),
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate('baz', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"baz"')
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testInvalidChoiceEmptyChoices()
+ {
+ $constraint = new Choice(array(
+ // May happen when the choices are provided dynamically, e.g. from
+ // the DB or the model
+ 'choices' => array(),
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate('baz', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"baz"')
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testInvalidChoiceMultiple()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array('foo', 'bar'),
+ 'multipleMessage' => 'myMessage',
+ 'multiple' => true,
+ ));
+
+ $this->validator->validate(array('foo', 'baz'), $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"baz"')
+ ->setInvalidValue('baz')
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testTooFewChoices()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array('foo', 'bar', 'moo', 'maa'),
+ 'multiple' => true,
+ 'min' => 2,
+ 'minMessage' => 'myMessage',
+ ));
+
+ $value = array('foo');
+
+ $this->setValue($value);
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ limit }}', 2)
+ ->setInvalidValue($value)
+ ->setPlural(2)
+ ->setCode(Choice::TOO_FEW_ERROR)
+ ->assertRaised();
+ }
+
+ public function testTooManyChoices()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array('foo', 'bar', 'moo', 'maa'),
+ 'multiple' => true,
+ 'max' => 2,
+ 'maxMessage' => 'myMessage',
+ ));
+
+ $value = array('foo', 'bar', 'moo');
+
+ $this->setValue($value);
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ limit }}', 2)
+ ->setInvalidValue($value)
+ ->setPlural(2)
+ ->setCode(Choice::TOO_MANY_ERROR)
+ ->assertRaised();
+ }
+
+ public function testNonStrict()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array(1, 2),
+ 'strict' => false,
+ ));
+
+ $this->validator->validate('2', $constraint);
+ $this->validator->validate(2, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testStrictAllowsExactValue()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array(1, 2),
+ 'strict' => true,
+ ));
+
+ $this->validator->validate(2, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testStrictDisallowsDifferentType()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array(1, 2),
+ 'strict' => true,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate('2', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"2"')
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testNonStrictWithMultipleChoices()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array(1, 2, 3),
+ 'multiple' => true,
+ 'strict' => false,
+ ));
+
+ $this->validator->validate(array('2', 3), $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testStrictWithMultipleChoices()
+ {
+ $constraint = new Choice(array(
+ 'choices' => array(1, 2, 3),
+ 'multiple' => true,
+ 'strict' => true,
+ 'multipleMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate(array(2, '3'), $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"3"')
+ ->setInvalidValue('3')
+ ->setCode(Choice::NO_SUCH_CHOICE_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionTest.php
new file mode 100644
index 0000000..b5fbf6c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionTest.php
@@ -0,0 +1,113 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\Constraints\Email;
+use Symfony\Component\Validator\Constraints\Optional;
+use Symfony\Component\Validator\Constraints\Required;
+use Symfony\Component\Validator\Constraints\Valid;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CollectionTest extends TestCase
+{
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectInvalidFieldsOption()
+ {
+ new Collection(array(
+ 'fields' => 'foo',
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectNonConstraints()
+ {
+ new Collection(array(
+ 'foo' => 'bar',
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectValidConstraint()
+ {
+ new Collection(array(
+ 'foo' => new Valid(),
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectValidConstraintWithinOptional()
+ {
+ new Collection(array(
+ 'foo' => new Optional(new Valid()),
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectValidConstraintWithinRequired()
+ {
+ new Collection(array(
+ 'foo' => new Required(new Valid()),
+ ));
+ }
+
+ public function testAcceptOptionalConstraintAsOneElementArray()
+ {
+ $collection1 = new Collection(array(
+ 'fields' => array(
+ 'alternate_email' => array(
+ new Optional(new Email()),
+ ),
+ ),
+ ));
+
+ $collection2 = new Collection(array(
+ 'fields' => array(
+ 'alternate_email' => new Optional(new Email()),
+ ),
+ ));
+
+ $this->assertEquals($collection1, $collection2);
+ }
+
+ public function testAcceptRequiredConstraintAsOneElementArray()
+ {
+ $collection1 = new Collection(array(
+ 'fields' => array(
+ 'alternate_email' => array(
+ new Required(new Email()),
+ ),
+ ),
+ ));
+
+ $collection2 = new Collection(array(
+ 'fields' => array(
+ 'alternate_email' => new Required(new Email()),
+ ),
+ ));
+
+ $this->assertEquals($collection1, $collection2);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php
new file mode 100644
index 0000000..a3c4b33
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+class CollectionValidatorArrayObjectTest extends CollectionValidatorTest
+{
+ public function prepareTestData(array $contents)
+ {
+ return new \ArrayObject($contents);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayTest.php
new file mode 100644
index 0000000..7517d0c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorArrayTest.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+class CollectionValidatorArrayTest extends CollectionValidatorTest
+{
+ public function prepareTestData(array $contents)
+ {
+ return $contents;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php
new file mode 100644
index 0000000..3d4c296
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Tests\Fixtures\CustomArrayObject;
+
+class CollectionValidatorCustomArrayObjectTest extends CollectionValidatorTest
+{
+ public function prepareTestData(array $contents)
+ {
+ return new CustomArrayObject($contents);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorTest.php
new file mode 100644
index 0000000..0376814
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CollectionValidatorTest.php
@@ -0,0 +1,389 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\Constraints\CollectionValidator;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Optional;
+use Symfony\Component\Validator\Constraints\Range;
+use Symfony\Component\Validator\Constraints\Required;
+use Symfony\Component\Validator\Validation;
+
+abstract class CollectionValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new CollectionValidator();
+ }
+
+ abstract protected function prepareTestData(array $contents);
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Collection(array('fields' => array(
+ 'foo' => new Range(array('min' => 4)),
+ ))));
+
+ $this->assertNoViolation();
+ }
+
+ public function testFieldsAsDefaultOption()
+ {
+ $constraint = new Range(array('min' => 4));
+
+ $data = $this->prepareTestData(array('foo' => 'foobar'));
+
+ $this->expectValidateValueAt(0, '[foo]', $data['foo'], array($constraint));
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => $constraint,
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testThrowsExceptionIfNotTraversable()
+ {
+ $this->validator->validate('foobar', new Collection(array('fields' => array(
+ 'foo' => new Range(array('min' => 4)),
+ ))));
+ }
+
+ public function testWalkSingleConstraint()
+ {
+ $constraint = new Range(array('min' => 4));
+
+ $array = array(
+ 'foo' => 3,
+ 'bar' => 5,
+ );
+
+ $i = 0;
+
+ foreach ($array as $key => $value) {
+ $this->expectValidateValueAt($i++, '['.$key.']', $value, array($constraint));
+ }
+
+ $data = $this->prepareTestData($array);
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ 'bar' => $constraint,
+ ),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testWalkMultipleConstraints()
+ {
+ $constraints = array(
+ new Range(array('min' => 4)),
+ new NotNull(),
+ );
+
+ $array = array(
+ 'foo' => 3,
+ 'bar' => 5,
+ );
+
+ $i = 0;
+
+ foreach ($array as $key => $value) {
+ $this->expectValidateValueAt($i++, '['.$key.']', $value, $constraints);
+ }
+
+ $data = $this->prepareTestData($array);
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraints,
+ 'bar' => $constraints,
+ ),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testExtraFieldsDisallowed()
+ {
+ $constraint = new Range(array('min' => 4));
+
+ $data = $this->prepareTestData(array(
+ 'foo' => 5,
+ 'baz' => 6,
+ ));
+
+ $this->expectValidateValueAt(0, '[foo]', $data['foo'], array($constraint));
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ ),
+ 'extraFieldsMessage' => 'myMessage',
+ )));
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ field }}', '"baz"')
+ ->atPath('property.path[baz]')
+ ->setInvalidValue(6)
+ ->setCode(Collection::NO_SUCH_FIELD_ERROR)
+ ->assertRaised();
+ }
+
+ // bug fix
+ public function testNullNotConsideredExtraField()
+ {
+ $data = $this->prepareTestData(array(
+ 'foo' => null,
+ ));
+
+ $constraint = new Range(array('min' => 4));
+
+ $this->expectValidateValueAt(0, '[foo]', $data['foo'], array($constraint));
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ ),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testExtraFieldsAllowed()
+ {
+ $data = $this->prepareTestData(array(
+ 'foo' => 5,
+ 'bar' => 6,
+ ));
+
+ $constraint = new Range(array('min' => 4));
+
+ $this->expectValidateValueAt(0, '[foo]', $data['foo'], array($constraint));
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ ),
+ 'allowExtraFields' => true,
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testMissingFieldsDisallowed()
+ {
+ $data = $this->prepareTestData(array());
+
+ $constraint = new Range(array('min' => 4));
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ ),
+ 'missingFieldsMessage' => 'myMessage',
+ )));
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ field }}', '"foo"')
+ ->atPath('property.path[foo]')
+ ->setInvalidValue(null)
+ ->setCode(Collection::MISSING_FIELD_ERROR)
+ ->assertRaised();
+ }
+
+ public function testMissingFieldsAllowed()
+ {
+ $data = $this->prepareTestData(array());
+
+ $constraint = new Range(array('min' => 4));
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ ),
+ 'allowMissingFields' => true,
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testOptionalFieldPresent()
+ {
+ $data = $this->prepareTestData(array(
+ 'foo' => null,
+ ));
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Optional(),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testOptionalFieldNotPresent()
+ {
+ $data = $this->prepareTestData(array());
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Optional(),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testOptionalFieldSingleConstraint()
+ {
+ $array = array(
+ 'foo' => 5,
+ );
+
+ $constraint = new Range(array('min' => 4));
+
+ $this->expectValidateValueAt(0, '[foo]', $array['foo'], array($constraint));
+
+ $data = $this->prepareTestData($array);
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Optional($constraint),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testOptionalFieldMultipleConstraints()
+ {
+ $array = array(
+ 'foo' => 5,
+ );
+
+ $constraints = array(
+ new NotNull(),
+ new Range(array('min' => 4)),
+ );
+
+ $this->expectValidateValueAt(0, '[foo]', $array['foo'], $constraints);
+
+ $data = $this->prepareTestData($array);
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Optional($constraints),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testRequiredFieldPresent()
+ {
+ $data = $this->prepareTestData(array(
+ 'foo' => null,
+ ));
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Required(),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testRequiredFieldNotPresent()
+ {
+ $data = $this->prepareTestData(array());
+
+ $this->validator->validate($data, new Collection(array(
+ 'fields' => array(
+ 'foo' => new Required(),
+ ),
+ 'missingFieldsMessage' => 'myMessage',
+ )));
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ field }}', '"foo"')
+ ->atPath('property.path[foo]')
+ ->setInvalidValue(null)
+ ->setCode(Collection::MISSING_FIELD_ERROR)
+ ->assertRaised();
+ }
+
+ public function testRequiredFieldSingleConstraint()
+ {
+ $array = array(
+ 'foo' => 5,
+ );
+
+ $constraint = new Range(array('min' => 4));
+
+ $this->expectValidateValueAt(0, '[foo]', $array['foo'], array($constraint));
+
+ $data = $this->prepareTestData($array);
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Required($constraint),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testRequiredFieldMultipleConstraints()
+ {
+ $array = array(
+ 'foo' => 5,
+ );
+
+ $constraints = array(
+ new NotNull(),
+ new Range(array('min' => 4)),
+ );
+
+ $this->expectValidateValueAt(0, '[foo]', $array['foo'], $constraints);
+
+ $data = $this->prepareTestData($array);
+
+ $this->validator->validate($data, new Collection(array(
+ 'foo' => new Required($constraints),
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function testObjectShouldBeLeftUnchanged()
+ {
+ $value = new \ArrayObject(array(
+ 'foo' => 3,
+ ));
+
+ $constraint = new Range(array('min' => 2));
+
+ $this->expectValidateValueAt(0, '[foo]', $value['foo'], array($constraint));
+
+ $this->validator->validate($value, new Collection(array(
+ 'fields' => array(
+ 'foo' => $constraint,
+ ),
+ )));
+
+ $this->assertEquals(array(
+ 'foo' => 3,
+ ), (array) $value);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CompositeTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CompositeTest.php
new file mode 100644
index 0000000..df42550
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CompositeTest.php
@@ -0,0 +1,148 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Composite;
+use Symfony\Component\Validator\Constraints\NotBlank;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Valid;
+
+class ConcreteComposite extends Composite
+{
+ public $constraints;
+
+ protected function getCompositeOption()
+ {
+ return 'constraints';
+ }
+
+ public function getDefaultOption()
+ {
+ return 'constraints';
+ }
+}
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CompositeTest extends TestCase
+{
+ public function testMergeNestedGroupsIfNoExplicitParentGroup()
+ {
+ $constraint = new ConcreteComposite(array(
+ new NotNull(array('groups' => 'Default')),
+ new NotBlank(array('groups' => array('Default', 'Strict'))),
+ ));
+
+ $this->assertEquals(array('Default', 'Strict'), $constraint->groups);
+ $this->assertEquals(array('Default'), $constraint->constraints[0]->groups);
+ $this->assertEquals(array('Default', 'Strict'), $constraint->constraints[1]->groups);
+ }
+
+ public function testSetImplicitNestedGroupsIfExplicitParentGroup()
+ {
+ $constraint = new ConcreteComposite(array(
+ 'constraints' => array(
+ new NotNull(),
+ new NotBlank(),
+ ),
+ 'groups' => array('Default', 'Strict'),
+ ));
+
+ $this->assertEquals(array('Default', 'Strict'), $constraint->groups);
+ $this->assertEquals(array('Default', 'Strict'), $constraint->constraints[0]->groups);
+ $this->assertEquals(array('Default', 'Strict'), $constraint->constraints[1]->groups);
+ }
+
+ public function testExplicitNestedGroupsMustBeSubsetOfExplicitParentGroups()
+ {
+ $constraint = new ConcreteComposite(array(
+ 'constraints' => array(
+ new NotNull(array('groups' => 'Default')),
+ new NotBlank(array('groups' => 'Strict')),
+ ),
+ 'groups' => array('Default', 'Strict'),
+ ));
+
+ $this->assertEquals(array('Default', 'Strict'), $constraint->groups);
+ $this->assertEquals(array('Default'), $constraint->constraints[0]->groups);
+ $this->assertEquals(array('Strict'), $constraint->constraints[1]->groups);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testFailIfExplicitNestedGroupsNotSubsetOfExplicitParentGroups()
+ {
+ new ConcreteComposite(array(
+ 'constraints' => array(
+ new NotNull(array('groups' => array('Default', 'Foobar'))),
+ ),
+ 'groups' => array('Default', 'Strict'),
+ ));
+ }
+
+ public function testImplicitGroupNamesAreForwarded()
+ {
+ $constraint = new ConcreteComposite(array(
+ new NotNull(array('groups' => 'Default')),
+ new NotBlank(array('groups' => 'Strict')),
+ ));
+
+ $constraint->addImplicitGroupName('ImplicitGroup');
+
+ $this->assertEquals(array('Default', 'Strict', 'ImplicitGroup'), $constraint->groups);
+ $this->assertEquals(array('Default', 'ImplicitGroup'), $constraint->constraints[0]->groups);
+ $this->assertEquals(array('Strict'), $constraint->constraints[1]->groups);
+ }
+
+ public function testSingleConstraintsAccepted()
+ {
+ $nestedConstraint = new NotNull();
+ $constraint = new ConcreteComposite($nestedConstraint);
+
+ $this->assertEquals(array($nestedConstraint), $constraint->constraints);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testFailIfNoConstraint()
+ {
+ new ConcreteComposite(array(
+ new NotNull(array('groups' => 'Default')),
+ 'NotBlank',
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testFailIfNoConstraintObject()
+ {
+ new ConcreteComposite(array(
+ new NotNull(array('groups' => 'Default')),
+ new \ArrayObject(),
+ ));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testValidCantBeNested()
+ {
+ new ConcreteComposite(array(
+ new Valid(),
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorArrayTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorArrayTest.php
new file mode 100644
index 0000000..5f562e7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorArrayTest.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CountValidatorArrayTest extends CountValidatorTest
+{
+ protected function createCollection(array $content)
+ {
+ return $content;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorCountableTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorCountableTest.php
new file mode 100644
index 0000000..7d46967
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorCountableTest.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Tests\Fixtures\Countable;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CountValidatorCountableTest extends CountValidatorTest
+{
+ protected function createCollection(array $content)
+ {
+ return new Countable($content);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorTest.php
new file mode 100644
index 0000000..5c89c85
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountValidatorTest.php
@@ -0,0 +1,203 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Count;
+use Symfony\Component\Validator\Constraints\CountValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class CountValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new CountValidator();
+ }
+
+ abstract protected function createCollection(array $content);
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Count(6));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsCountableType()
+ {
+ $this->validator->validate(new \stdClass(), new Count(5));
+ }
+
+ public function getThreeOrLessElements()
+ {
+ return array(
+ array($this->createCollection(array(1))),
+ array($this->createCollection(array(1, 2))),
+ array($this->createCollection(array(1, 2, 3))),
+ array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3))),
+ );
+ }
+
+ public function getFourElements()
+ {
+ return array(
+ array($this->createCollection(array(1, 2, 3, 4))),
+ array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4))),
+ );
+ }
+
+ public function getFiveOrMoreElements()
+ {
+ return array(
+ array($this->createCollection(array(1, 2, 3, 4, 5))),
+ array($this->createCollection(array(1, 2, 3, 4, 5, 6))),
+ array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5))),
+ );
+ }
+
+ /**
+ * @dataProvider getThreeOrLessElements
+ */
+ public function testValidValuesMax($value)
+ {
+ $constraint = new Count(array('max' => 3));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getFiveOrMoreElements
+ */
+ public function testValidValuesMin($value)
+ {
+ $constraint = new Count(array('min' => 5));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getFourElements
+ */
+ public function testValidValuesExact($value)
+ {
+ $constraint = new Count(4);
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getFiveOrMoreElements
+ */
+ public function testTooManyValues($value)
+ {
+ $constraint = new Count(array(
+ 'max' => 4,
+ 'maxMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ count }}', \count($value))
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Count::TOO_MANY_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getThreeOrLessElements
+ */
+ public function testTooFewValues($value)
+ {
+ $constraint = new Count(array(
+ 'min' => 4,
+ 'minMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ count }}', \count($value))
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Count::TOO_FEW_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getFiveOrMoreElements
+ */
+ public function testTooManyValuesExact($value)
+ {
+ $constraint = new Count(array(
+ 'min' => 4,
+ 'max' => 4,
+ 'exactMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ count }}', \count($value))
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Count::TOO_MANY_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getThreeOrLessElements
+ */
+ public function testTooFewValuesExact($value)
+ {
+ $constraint = new Count(array(
+ 'min' => 4,
+ 'max' => 4,
+ 'exactMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ count }}', \count($value))
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Count::TOO_FEW_ERROR)
+ ->assertRaised();
+ }
+
+ public function testDefaultOption()
+ {
+ $constraint = new Count(5);
+
+ $this->assertEquals(5, $constraint->min);
+ $this->assertEquals(5, $constraint->max);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountryValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountryValidatorTest.php
new file mode 100644
index 0000000..4baee3e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CountryValidatorTest.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Intl\Util\IntlTestHelper;
+use Symfony\Component\Validator\Constraints\Country;
+use Symfony\Component\Validator\Constraints\CountryValidator;
+use Symfony\Component\Validator\Validation;
+
+class CountryValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new CountryValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Country());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Country());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Country());
+ }
+
+ /**
+ * @dataProvider getValidCountries
+ */
+ public function testValidCountries($country)
+ {
+ $this->validator->validate($country, new Country());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidCountries()
+ {
+ return array(
+ array('GB'),
+ array('AT'),
+ array('MY'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidCountries
+ */
+ public function testInvalidCountries($country)
+ {
+ $constraint = new Country(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($country, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$country.'"')
+ ->setCode(Country::NO_SUCH_COUNTRY_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidCountries()
+ {
+ return array(
+ array('foobar'),
+ array('EN'),
+ );
+ }
+
+ public function testValidateUsingCountrySpecificLocale()
+ {
+ // in order to test with "en_GB"
+ IntlTestHelper::requireFullIntl($this, false);
+
+ \Locale::setDefault('en_GB');
+
+ $existingCountry = 'GB';
+
+ $this->validator->validate($existingCountry, new Country());
+
+ $this->assertNoViolation();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/CurrencyValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CurrencyValidatorTest.php
new file mode 100644
index 0000000..1c11a6b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/CurrencyValidatorTest.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Intl\Util\IntlTestHelper;
+use Symfony\Component\Validator\Constraints\Currency;
+use Symfony\Component\Validator\Constraints\CurrencyValidator;
+use Symfony\Component\Validator\Validation;
+
+class CurrencyValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new CurrencyValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Currency());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Currency());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Currency());
+ }
+
+ /**
+ * @dataProvider getValidCurrencies
+ */
+ public function testValidCurrencies($currency)
+ {
+ $this->validator->validate($currency, new Currency());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getValidCurrencies
+ **/
+ public function testValidCurrenciesWithCountrySpecificLocale($currency)
+ {
+ IntlTestHelper::requireFullIntl($this, false);
+
+ \Locale::setDefault('en_GB');
+
+ $this->validator->validate($currency, new Currency());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidCurrencies()
+ {
+ return array(
+ array('EUR'),
+ array('USD'),
+ array('SIT'),
+ array('AUD'),
+ array('CAD'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidCurrencies
+ */
+ public function testInvalidCurrencies($currency)
+ {
+ $constraint = new Currency(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($currency, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$currency.'"')
+ ->setCode(Currency::NO_SUCH_CURRENCY_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidCurrencies()
+ {
+ return array(
+ array('EN'),
+ array('foobar'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/DateTimeValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/DateTimeValidatorTest.php
new file mode 100644
index 0000000..25d88aa
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/DateTimeValidatorTest.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\DateTime;
+use Symfony\Component\Validator\Constraints\DateTimeValidator;
+use Symfony\Component\Validator\Validation;
+
+class DateTimeValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new DateTimeValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new DateTime());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new DateTime());
+
+ $this->assertNoViolation();
+ }
+
+ public function testDateTimeClassIsValid()
+ {
+ $this->validator->validate(new \DateTime(), new DateTime());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new DateTime());
+ }
+
+ /**
+ * @dataProvider getValidDateTimes
+ */
+ public function testValidDateTimes($dateTime)
+ {
+ $this->validator->validate($dateTime, new DateTime());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidDateTimes()
+ {
+ return array(
+ array('2010-01-01 01:02:03'),
+ array('1955-12-12 00:00:00'),
+ array('2030-05-31 23:59:59'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidDateTimes
+ */
+ public function testInvalidDateTimes($dateTime, $code)
+ {
+ $constraint = new DateTime(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($dateTime, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$dateTime.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidDateTimes()
+ {
+ return array(
+ array('foobar', DateTime::INVALID_FORMAT_ERROR),
+ array('2010-01-01', DateTime::INVALID_FORMAT_ERROR),
+ array('00:00:00', DateTime::INVALID_FORMAT_ERROR),
+ array('2010-01-01 00:00', DateTime::INVALID_FORMAT_ERROR),
+ array('2010-13-01 00:00:00', DateTime::INVALID_DATE_ERROR),
+ array('2010-04-32 00:00:00', DateTime::INVALID_DATE_ERROR),
+ array('2010-02-29 00:00:00', DateTime::INVALID_DATE_ERROR),
+ array('2010-01-01 24:00:00', DateTime::INVALID_TIME_ERROR),
+ array('2010-01-01 00:60:00', DateTime::INVALID_TIME_ERROR),
+ array('2010-01-01 00:00:60', DateTime::INVALID_TIME_ERROR),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/DateValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/DateValidatorTest.php
new file mode 100644
index 0000000..21f0a2d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/DateValidatorTest.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Date;
+use Symfony\Component\Validator\Constraints\DateValidator;
+use Symfony\Component\Validator\Validation;
+
+class DateValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new DateValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Date());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Date());
+
+ $this->assertNoViolation();
+ }
+
+ public function testDateTimeClassIsValid()
+ {
+ $this->validator->validate(new \DateTime(), new Date());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Date());
+ }
+
+ /**
+ * @dataProvider getValidDates
+ */
+ public function testValidDates($date)
+ {
+ $this->validator->validate($date, new Date());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidDates()
+ {
+ return array(
+ array('2010-01-01'),
+ array('1955-12-12'),
+ array('2030-05-31'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidDates
+ */
+ public function testInvalidDates($date, $code)
+ {
+ $constraint = new Date(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($date, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$date.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidDates()
+ {
+ return array(
+ array('foobar', Date::INVALID_FORMAT_ERROR),
+ array('foobar 2010-13-01', Date::INVALID_FORMAT_ERROR),
+ array('2010-13-01 foobar', Date::INVALID_FORMAT_ERROR),
+ array('2010-13-01', Date::INVALID_DATE_ERROR),
+ array('2010-04-32', Date::INVALID_DATE_ERROR),
+ array('2010-02-29', Date::INVALID_DATE_ERROR),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/EmailValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/EmailValidatorTest.php
new file mode 100644
index 0000000..5933bd5
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/EmailValidatorTest.php
@@ -0,0 +1,190 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Bridge\PhpUnit\DnsMock;
+use Symfony\Component\Validator\Constraints\Email;
+use Symfony\Component\Validator\Constraints\EmailValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @group dns-sensitive
+ */
+class EmailValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new EmailValidator(false);
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Email());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Email());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Email());
+ }
+
+ /**
+ * @dataProvider getValidEmails
+ */
+ public function testValidEmails($email)
+ {
+ $this->validator->validate($email, new Email());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidEmails()
+ {
+ return array(
+ array('fabien@symfony.com'),
+ array('example@example.co.uk'),
+ array('fabien_potencier@example.fr'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidEmails
+ */
+ public function testInvalidEmails($email)
+ {
+ $constraint = new Email(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($email, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$email.'"')
+ ->setCode(Email::INVALID_FORMAT_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidEmails()
+ {
+ return array(
+ array('example'),
+ array('example@'),
+ array('example@localhost'),
+ array('foo@example.com bar'),
+ );
+ }
+
+ public function testStrict()
+ {
+ $constraint = new Email(array('strict' => true));
+
+ $this->validator->validate('example@localhost', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getDnsChecks
+ * @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
+ */
+ public function testDnsChecks($type, $violation)
+ {
+ DnsMock::withMockedHosts(array('example.com' => array(array('type' => $violation ? false : $type))));
+
+ $constraint = new Email(array(
+ 'message' => 'myMessage',
+ 'MX' === $type ? 'checkMX' : 'checkHost' => true,
+ ));
+
+ $this->validator->validate('foo@example.com', $constraint);
+
+ if (!$violation) {
+ $this->assertNoViolation();
+ } else {
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"foo@example.com"')
+ ->setCode($violation)
+ ->assertRaised();
+ }
+ }
+
+ public function getDnsChecks()
+ {
+ return array(
+ array('MX', false),
+ array('MX', Email::MX_CHECK_FAILED_ERROR),
+ array('A', false),
+ array('A', Email::HOST_CHECK_FAILED_ERROR),
+ array('AAAA', false),
+ array('AAAA', Email::HOST_CHECK_FAILED_ERROR),
+ );
+ }
+
+ /**
+ * @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
+ */
+ public function testHostnameIsProperlyParsed()
+ {
+ DnsMock::withMockedHosts(array('baz.com' => array(array('type' => 'MX'))));
+
+ $this->validator->validate(
+ '"foo@bar"@baz.com',
+ new Email(array('checkMX' => true))
+ );
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider provideCheckTypes
+ */
+ public function testEmptyHostIsNotValid($checkType, $violation)
+ {
+ $this->validator->validate(
+ 'foo@bar.fr@',
+ new Email(array(
+ 'message' => 'myMessage',
+ $checkType => true,
+ ))
+ );
+
+ $this
+ ->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"foo@bar.fr@"')
+ ->setCode($violation)
+ ->assertRaised();
+ }
+
+ public function provideCheckTypes()
+ {
+ return array(
+ array('checkMX', Email::MX_CHECK_FAILED_ERROR),
+ array('checkHost', Email::HOST_CHECK_FAILED_ERROR),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/EqualToValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/EqualToValidatorTest.php
new file mode 100644
index 0000000..32c81c3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/EqualToValidatorTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\EqualTo;
+use Symfony\Component\Validator\Constraints\EqualToValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class EqualToValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new EqualToValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new EqualTo($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return EqualTo::NOT_EQUAL_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(3, 3),
+ array(3, '3'),
+ array('a', 'a'),
+ array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
+ array(new \DateTime('2000-01-01'), '2000-01-01'),
+ array(new \DateTime('2000-01-01 UTC'), '2000-01-01 UTC'),
+ array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)),
+ array(null, 1),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(1, '1', 2, '2', 'integer'),
+ array('22', '"22"', '333', '"333"', 'string'),
+ array(new \DateTime('2001-01-01'), 'Jan 1, 2001, 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2001-01-01'), 'Jan 1, 2001, 12:00 AM', '2000-01-01', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2001-01-01 UTC'), 'Jan 1, 2001, 12:00 AM', '2000-01-01 UTC', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new ComparisonTest_Class(4), '4', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/ExpressionValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ExpressionValidatorTest.php
new file mode 100644
index 0000000..ee287c9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ExpressionValidatorTest.php
@@ -0,0 +1,279 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\PropertyAccess\PropertyAccess;
+use Symfony\Component\Validator\Constraints\Expression;
+use Symfony\Component\Validator\Constraints\ExpressionValidator;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+use Symfony\Component\Validator\Tests\Fixtures\ToString;
+use Symfony\Component\Validator\Validation;
+
+class ExpressionValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new ExpressionValidator(PropertyAccess::createPropertyAccessor());
+ }
+
+ public function testExpressionIsEvaluatedWithNullValue()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'false',
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(null, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'null')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testExpressionIsEvaluatedWithEmptyStringValue()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'false',
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate('', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '""')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testSucceedingExpressionAtObjectLevel()
+ {
+ $constraint = new Expression('this.data == 1');
+
+ $object = new Entity();
+ $object->data = '1';
+
+ $this->setObject($object);
+
+ $this->validator->validate($object, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testFailingExpressionAtObjectLevel()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'this.data == 1',
+ 'message' => 'myMessage',
+ ));
+
+ $object = new Entity();
+ $object->data = '2';
+
+ $this->setObject($object);
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'object')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testSucceedingExpressionAtObjectLevelWithToString()
+ {
+ $constraint = new Expression('this.data == 1');
+
+ $object = new ToString();
+ $object->data = '1';
+
+ $this->setObject($object);
+
+ $this->validator->validate($object, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testFailingExpressionAtObjectLevelWithToString()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'this.data == 1',
+ 'message' => 'myMessage',
+ ));
+
+ $object = new ToString();
+ $object->data = '2';
+
+ $this->setObject($object);
+
+ $this->validator->validate($object, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'toString')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testSucceedingExpressionAtPropertyLevel()
+ {
+ $constraint = new Expression('value == this.data');
+
+ $object = new Entity();
+ $object->data = '1';
+
+ $this->setRoot($object);
+ $this->setPropertyPath('data');
+ $this->setProperty($object, 'data');
+
+ $this->validator->validate('1', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testFailingExpressionAtPropertyLevel()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'value == this.data',
+ 'message' => 'myMessage',
+ ));
+
+ $object = new Entity();
+ $object->data = '1';
+
+ $this->setRoot($object);
+ $this->setPropertyPath('data');
+ $this->setProperty($object, 'data');
+
+ $this->validator->validate('2', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->atPath('data')
+ ->setParameter('{{ value }}', '"2"')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testSucceedingExpressionAtNestedPropertyLevel()
+ {
+ $constraint = new Expression('value == this.data');
+
+ $object = new Entity();
+ $object->data = '1';
+
+ $root = new Entity();
+ $root->reference = $object;
+
+ $this->setRoot($root);
+ $this->setPropertyPath('reference.data');
+ $this->setProperty($object, 'data');
+
+ $this->validator->validate('1', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testFailingExpressionAtNestedPropertyLevel()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'value == this.data',
+ 'message' => 'myMessage',
+ ));
+
+ $object = new Entity();
+ $object->data = '1';
+
+ $root = new Entity();
+ $root->reference = $object;
+
+ $this->setRoot($root);
+ $this->setPropertyPath('reference.data');
+ $this->setProperty($object, 'data');
+
+ $this->validator->validate('2', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->atPath('reference.data')
+ ->setParameter('{{ value }}', '"2"')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * When validatePropertyValue() is called with a class name
+ * https://github.com/symfony/symfony/pull/11498.
+ */
+ public function testSucceedingExpressionAtPropertyLevelWithoutRoot()
+ {
+ $constraint = new Expression('value == "1"');
+
+ $this->setRoot('1');
+ $this->setPropertyPath('');
+ $this->setProperty(null, 'property');
+
+ $this->validator->validate('1', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * When validatePropertyValue() is called with a class name
+ * https://github.com/symfony/symfony/pull/11498.
+ */
+ public function testFailingExpressionAtPropertyLevelWithoutRoot()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'value == "1"',
+ 'message' => 'myMessage',
+ ));
+
+ $this->setRoot('2');
+ $this->setPropertyPath('');
+ $this->setProperty(null, 'property');
+
+ $this->validator->validate('2', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->atPath('')
+ ->setParameter('{{ value }}', '"2"')
+ ->setCode(Expression::EXPRESSION_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testExpressionLanguageUsage()
+ {
+ $constraint = new Expression(array(
+ 'expression' => 'false',
+ ));
+
+ $expressionLanguage = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ExpressionLanguage')->getMock();
+
+ $used = false;
+
+ $expressionLanguage->method('evaluate')
+ ->will($this->returnCallback(function () use (&$used) {
+ $used = true;
+
+ return true;
+ }));
+
+ $validator = new ExpressionValidator(null, $expressionLanguage);
+ $validator->initialize($this->createContext());
+ $validator->validate(null, $constraint);
+
+ $this->assertTrue($used, 'Failed asserting that custom ExpressionLanguage instance is used.');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileTest.php
new file mode 100644
index 0000000..b7745f4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileTest.php
@@ -0,0 +1,139 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\File;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+
+class FileTest extends TestCase
+{
+ /**
+ * @dataProvider provideValidSizes
+ */
+ public function testMaxSize($maxSize, $bytes, $binaryFormat)
+ {
+ $file = new File(array('maxSize' => $maxSize));
+
+ $this->assertSame($bytes, $file->maxSize);
+ $this->assertSame($binaryFormat, $file->binaryFormat);
+ $this->assertTrue($file->__isset('maxSize'));
+ }
+
+ public function testMagicIsset()
+ {
+ $file = new File(array('maxSize' => 1));
+
+ $this->assertTrue($file->__isset('maxSize'));
+ $this->assertTrue($file->__isset('groups'));
+ $this->assertFalse($file->__isset('toto'));
+ }
+
+ /**
+ * @dataProvider provideValidSizes
+ */
+ public function testMaxSizeCanBeSetAfterInitialization($maxSize, $bytes, $binaryFormat)
+ {
+ $file = new File();
+ $file->maxSize = $maxSize;
+
+ $this->assertSame($bytes, $file->maxSize);
+ $this->assertSame($binaryFormat, $file->binaryFormat);
+ }
+
+ /**
+ * @dataProvider provideInvalidSizes
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidValueForMaxSizeThrowsExceptionAfterInitialization($maxSize)
+ {
+ $file = new File(array('maxSize' => 1000));
+ $file->maxSize = $maxSize;
+ }
+
+ /**
+ * @dataProvider provideInvalidSizes
+ */
+ public function testMaxSizeCannotBeSetToInvalidValueAfterInitialization($maxSize)
+ {
+ $file = new File(array('maxSize' => 1000));
+
+ try {
+ $file->maxSize = $maxSize;
+ } catch (ConstraintDefinitionException $e) {
+ }
+
+ $this->assertSame(1000, $file->maxSize);
+ }
+
+ /**
+ * @dataProvider provideInValidSizes
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMaxSize($maxSize)
+ {
+ new File(array('maxSize' => $maxSize));
+ }
+
+ public function provideValidSizes()
+ {
+ return array(
+ array('500', 500, false),
+ array(12300, 12300, false),
+ array('1ki', 1024, true),
+ array('1KI', 1024, true),
+ array('2k', 2000, false),
+ array('2K', 2000, false),
+ array('1mi', 1048576, true),
+ array('1MI', 1048576, true),
+ array('3m', 3000000, false),
+ array('3M', 3000000, false),
+ );
+ }
+
+ public function provideInvalidSizes()
+ {
+ return array(
+ array('+100'),
+ array('foo'),
+ array('1Ko'),
+ array('1kio'),
+ array('1G'),
+ array('1Gi'),
+ );
+ }
+
+ /**
+ * @dataProvider provideFormats
+ */
+ public function testBinaryFormat($maxSize, $guessedFormat, $binaryFormat)
+ {
+ $file = new File(array('maxSize' => $maxSize, 'binaryFormat' => $guessedFormat));
+
+ $this->assertSame($binaryFormat, $file->binaryFormat);
+ }
+
+ public function provideFormats()
+ {
+ return array(
+ array(100, null, false),
+ array(100, true, true),
+ array(100, false, false),
+ array('100K', null, false),
+ array('100K', true, true),
+ array('100K', false, false),
+ array('100Ki', null, true),
+ array('100Ki', true, true),
+ array('100Ki', false, false),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorObjectTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorObjectTest.php
new file mode 100644
index 0000000..f35f93b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorObjectTest.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\HttpFoundation\File\File;
+
+class FileValidatorObjectTest extends FileValidatorTest
+{
+ protected function getFile($filename)
+ {
+ return new File($filename);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorPathTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorPathTest.php
new file mode 100644
index 0000000..11b8d4c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorPathTest.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\File;
+
+class FileValidatorPathTest extends FileValidatorTest
+{
+ protected function getFile($filename)
+ {
+ return $filename;
+ }
+
+ public function testFileNotFound()
+ {
+ $constraint = new File(array(
+ 'notFoundMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate('foobar', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ file }}', '"foobar"')
+ ->setCode(File::NOT_FOUND_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorTest.php
new file mode 100644
index 0000000..6e2199c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/FileValidatorTest.php
@@ -0,0 +1,483 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\HttpFoundation\File\UploadedFile;
+use Symfony\Component\Validator\Constraints\File;
+use Symfony\Component\Validator\Constraints\FileValidator;
+use Symfony\Component\Validator\Validation;
+
+abstract class FileValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected $path;
+
+ protected $file;
+
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new FileValidator();
+ }
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->path = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'FileValidatorTest';
+ $this->file = fopen($this->path, 'w');
+ fwrite($this->file, ' ', 1);
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+
+ if (\is_resource($this->file)) {
+ fclose($this->file);
+ }
+
+ if (file_exists($this->path)) {
+ unlink($this->path);
+ }
+
+ $this->path = null;
+ $this->file = null;
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new File());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new File());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleTypeOrFile()
+ {
+ $this->validator->validate(new \stdClass(), new File());
+ }
+
+ public function testValidFile()
+ {
+ $this->validator->validate($this->path, new File());
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidUploadedfile()
+ {
+ $file = new UploadedFile($this->path, 'originalName', null, null, null, true);
+ $this->validator->validate($file, new File());
+
+ $this->assertNoViolation();
+ }
+
+ public function provideMaxSizeExceededTests()
+ {
+ // We have various interesting limit - size combinations to test.
+ // Assume a limit of 1000 bytes (1 kB). Then the following table
+ // lists the violation messages for different file sizes:
+ // -----------+--------------------------------------------------------
+ // Size | Violation Message
+ // -----------+--------------------------------------------------------
+ // 1000 bytes | No violation
+ // 1001 bytes | "Size of 1001 bytes exceeded limit of 1000 bytes"
+ // 1004 bytes | "Size of 1004 bytes exceeded limit of 1000 bytes"
+ // | NOT: "Size of 1 kB exceeded limit of 1 kB"
+ // 1005 bytes | "Size of 1.01 kB exceeded limit of 1 kB"
+ // -----------+--------------------------------------------------------
+
+ // As you see, we have two interesting borders:
+
+ // 1000/1001 - The border as of which a violation occurs
+ // 1004/1005 - The border as of which the message can be rounded to kB
+
+ // Analogous for kB/MB.
+
+ // Prior to Symfony 2.5, violation messages are always displayed in the
+ // same unit used to specify the limit.
+
+ // As of Symfony 2.5, the above logic is implemented.
+ return array(
+ // limit in bytes
+ array(1001, 1000, '1001', '1000', 'bytes'),
+ array(1004, 1000, '1004', '1000', 'bytes'),
+ array(1005, 1000, '1.01', '1', 'kB'),
+
+ array(1000001, 1000000, '1000001', '1000000', 'bytes'),
+ array(1004999, 1000000, '1005', '1000', 'kB'),
+ array(1005000, 1000000, '1.01', '1', 'MB'),
+
+ // limit in kB
+ array(1001, '1k', '1001', '1000', 'bytes'),
+ array(1004, '1k', '1004', '1000', 'bytes'),
+ array(1005, '1k', '1.01', '1', 'kB'),
+
+ array(1000001, '1000k', '1000001', '1000000', 'bytes'),
+ array(1004999, '1000k', '1005', '1000', 'kB'),
+ array(1005000, '1000k', '1.01', '1', 'MB'),
+
+ // limit in MB
+ array(1000001, '1M', '1000001', '1000000', 'bytes'),
+ array(1004999, '1M', '1005', '1000', 'kB'),
+ array(1005000, '1M', '1.01', '1', 'MB'),
+
+ // limit in KiB
+ array(1025, '1Ki', '1025', '1024', 'bytes'),
+ array(1029, '1Ki', '1029', '1024', 'bytes'),
+ array(1030, '1Ki', '1.01', '1', 'KiB'),
+
+ array(1048577, '1024Ki', '1048577', '1048576', 'bytes'),
+ array(1053818, '1024Ki', '1029.12', '1024', 'KiB'),
+ array(1053819, '1024Ki', '1.01', '1', 'MiB'),
+
+ // limit in MiB
+ array(1048577, '1Mi', '1048577', '1048576', 'bytes'),
+ array(1053818, '1Mi', '1029.12', '1024', 'KiB'),
+ array(1053819, '1Mi', '1.01', '1', 'MiB'),
+ );
+ }
+
+ /**
+ * @dataProvider provideMaxSizeExceededTests
+ */
+ public function testMaxSizeExceeded($bytesWritten, $limit, $sizeAsString, $limitAsString, $suffix)
+ {
+ fseek($this->file, $bytesWritten - 1, SEEK_SET);
+ fwrite($this->file, '0');
+ fclose($this->file);
+
+ $constraint = new File(array(
+ 'maxSize' => $limit,
+ 'maxSizeMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->getFile($this->path), $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ limit }}', $limitAsString)
+ ->setParameter('{{ size }}', $sizeAsString)
+ ->setParameter('{{ suffix }}', $suffix)
+ ->setParameter('{{ file }}', '"'.$this->path.'"')
+ ->setCode(File::TOO_LARGE_ERROR)
+ ->assertRaised();
+ }
+
+ public function provideMaxSizeNotExceededTests()
+ {
+ return array(
+ // limit in bytes
+ array(1000, 1000),
+ array(1000000, 1000000),
+
+ // limit in kB
+ array(1000, '1k'),
+ array(1000000, '1000k'),
+
+ // limit in MB
+ array(1000000, '1M'),
+
+ // limit in KiB
+ array(1024, '1Ki'),
+ array(1048576, '1024Ki'),
+
+ // limit in MiB
+ array(1048576, '1Mi'),
+ );
+ }
+
+ /**
+ * @dataProvider provideMaxSizeNotExceededTests
+ */
+ public function testMaxSizeNotExceeded($bytesWritten, $limit)
+ {
+ fseek($this->file, $bytesWritten - 1, SEEK_SET);
+ fwrite($this->file, '0');
+ fclose($this->file);
+
+ $constraint = new File(array(
+ 'maxSize' => $limit,
+ 'maxSizeMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->getFile($this->path), $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMaxSize()
+ {
+ $constraint = new File(array(
+ 'maxSize' => '1abc',
+ ));
+
+ $this->validator->validate($this->path, $constraint);
+ }
+
+ public function provideBinaryFormatTests()
+ {
+ return array(
+ array(11, 10, null, '11', '10', 'bytes'),
+ array(11, 10, true, '11', '10', 'bytes'),
+ array(11, 10, false, '11', '10', 'bytes'),
+
+ // round(size) == 1.01kB, limit == 1kB
+ array(ceil(1000 * 1.01), 1000, null, '1.01', '1', 'kB'),
+ array(ceil(1000 * 1.01), '1k', null, '1.01', '1', 'kB'),
+ array(ceil(1024 * 1.01), '1Ki', null, '1.01', '1', 'KiB'),
+
+ array(ceil(1024 * 1.01), 1024, true, '1.01', '1', 'KiB'),
+ array(ceil(1024 * 1.01 * 1000), '1024k', true, '1010', '1000', 'KiB'),
+ array(ceil(1024 * 1.01), '1Ki', true, '1.01', '1', 'KiB'),
+
+ array(ceil(1000 * 1.01), 1000, false, '1.01', '1', 'kB'),
+ array(ceil(1000 * 1.01), '1k', false, '1.01', '1', 'kB'),
+ array(ceil(1024 * 1.01 * 10), '10Ki', false, '10.34', '10.24', 'kB'),
+ );
+ }
+
+ /**
+ * @dataProvider provideBinaryFormatTests
+ */
+ public function testBinaryFormat($bytesWritten, $limit, $binaryFormat, $sizeAsString, $limitAsString, $suffix)
+ {
+ fseek($this->file, $bytesWritten - 1, SEEK_SET);
+ fwrite($this->file, '0');
+ fclose($this->file);
+
+ $constraint = new File(array(
+ 'maxSize' => $limit,
+ 'binaryFormat' => $binaryFormat,
+ 'maxSizeMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->getFile($this->path), $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ limit }}', $limitAsString)
+ ->setParameter('{{ size }}', $sizeAsString)
+ ->setParameter('{{ suffix }}', $suffix)
+ ->setParameter('{{ file }}', '"'.$this->path.'"')
+ ->setCode(File::TOO_LARGE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testValidMimeType()
+ {
+ $file = $this
+ ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
+ ->setConstructorArgs(array(__DIR__.'/Fixtures/foo'))
+ ->getMock();
+ $file
+ ->expects($this->once())
+ ->method('getPathname')
+ ->will($this->returnValue($this->path));
+ $file
+ ->expects($this->once())
+ ->method('getMimeType')
+ ->will($this->returnValue('image/jpg'));
+
+ $constraint = new File(array(
+ 'mimeTypes' => array('image/png', 'image/jpg'),
+ ));
+
+ $this->validator->validate($file, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidWildcardMimeType()
+ {
+ $file = $this
+ ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
+ ->setConstructorArgs(array(__DIR__.'/Fixtures/foo'))
+ ->getMock();
+ $file
+ ->expects($this->once())
+ ->method('getPathname')
+ ->will($this->returnValue($this->path));
+ $file
+ ->expects($this->once())
+ ->method('getMimeType')
+ ->will($this->returnValue('image/jpg'));
+
+ $constraint = new File(array(
+ 'mimeTypes' => array('image/*'),
+ ));
+
+ $this->validator->validate($file, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testInvalidMimeType()
+ {
+ $file = $this
+ ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
+ ->setConstructorArgs(array(__DIR__.'/Fixtures/foo'))
+ ->getMock();
+ $file
+ ->expects($this->once())
+ ->method('getPathname')
+ ->will($this->returnValue($this->path));
+ $file
+ ->expects($this->once())
+ ->method('getMimeType')
+ ->will($this->returnValue('application/pdf'));
+
+ $constraint = new File(array(
+ 'mimeTypes' => array('image/png', 'image/jpg'),
+ 'mimeTypesMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($file, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ type }}', '"application/pdf"')
+ ->setParameter('{{ types }}', '"image/png", "image/jpg"')
+ ->setParameter('{{ file }}', '"'.$this->path.'"')
+ ->setCode(File::INVALID_MIME_TYPE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testInvalidWildcardMimeType()
+ {
+ $file = $this
+ ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
+ ->setConstructorArgs(array(__DIR__.'/Fixtures/foo'))
+ ->getMock();
+ $file
+ ->expects($this->once())
+ ->method('getPathname')
+ ->will($this->returnValue($this->path));
+ $file
+ ->expects($this->once())
+ ->method('getMimeType')
+ ->will($this->returnValue('application/pdf'));
+
+ $constraint = new File(array(
+ 'mimeTypes' => array('image/*', 'image/jpg'),
+ 'mimeTypesMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($file, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ type }}', '"application/pdf"')
+ ->setParameter('{{ types }}', '"image/*", "image/jpg"')
+ ->setParameter('{{ file }}', '"'.$this->path.'"')
+ ->setCode(File::INVALID_MIME_TYPE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testDisallowEmpty()
+ {
+ ftruncate($this->file, 0);
+
+ $constraint = new File(array(
+ 'disallowEmptyMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->getFile($this->path), $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ file }}', '"'.$this->path.'"')
+ ->setCode(File::EMPTY_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider uploadedFileErrorProvider
+ */
+ public function testUploadedFileError($error, $message, array $params = array(), $maxSize = null)
+ {
+ $file = new UploadedFile('/path/to/file', 'originalName', 'mime', 0, $error);
+
+ $constraint = new File(array(
+ $message => 'myMessage',
+ 'maxSize' => $maxSize,
+ ));
+
+ $this->validator->validate($file, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameters($params)
+ ->setCode($error)
+ ->assertRaised();
+ }
+
+ public function uploadedFileErrorProvider()
+ {
+ $tests = array(
+ array(UPLOAD_ERR_FORM_SIZE, 'uploadFormSizeErrorMessage'),
+ array(UPLOAD_ERR_PARTIAL, 'uploadPartialErrorMessage'),
+ array(UPLOAD_ERR_NO_FILE, 'uploadNoFileErrorMessage'),
+ array(UPLOAD_ERR_NO_TMP_DIR, 'uploadNoTmpDirErrorMessage'),
+ array(UPLOAD_ERR_CANT_WRITE, 'uploadCantWriteErrorMessage'),
+ array(UPLOAD_ERR_EXTENSION, 'uploadExtensionErrorMessage'),
+ );
+
+ if (class_exists('Symfony\Component\HttpFoundation\File\UploadedFile')) {
+ // when no maxSize is specified on constraint, it should use the ini value
+ $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
+ '{{ limit }}' => UploadedFile::getMaxFilesize() / 1048576,
+ '{{ suffix }}' => 'MiB',
+ ));
+
+ // it should use the smaller limitation (maxSize option in this case)
+ $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
+ '{{ limit }}' => 1,
+ '{{ suffix }}' => 'bytes',
+ ), '1');
+
+ // access FileValidator::factorizeSizes() private method to format max file size
+ $reflection = new \ReflectionClass(\get_class(new FileValidator()));
+ $method = $reflection->getMethod('factorizeSizes');
+ $method->setAccessible(true);
+ list($sizeAsString, $limit, $suffix) = $method->invokeArgs(new FileValidator(), array(0, UploadedFile::getMaxFilesize(), false));
+
+ // it correctly parses the maxSize option and not only uses simple string comparison
+ // 1000M should be bigger than the ini value
+ $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
+ '{{ limit }}' => $limit,
+ '{{ suffix }}' => $suffix,
+ ), '1000M');
+
+ // it correctly parses the maxSize option and not only uses simple string comparison
+ // 1000M should be bigger than the ini value
+ $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
+ '{{ limit }}' => '0.1',
+ '{{ suffix }}' => 'MB',
+ ), '100K');
+ }
+
+ return $tests;
+ }
+
+ abstract protected function getFile($filename);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/foo b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/foo
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/foo
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test.gif b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test.gif
new file mode 100644
index 0000000..6b44fc7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test.gif
Binary files differ
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_4by3.gif b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_4by3.gif
new file mode 100644
index 0000000..64dd3ff
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_4by3.gif
Binary files differ
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_landscape.gif b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_landscape.gif
new file mode 100644
index 0000000..8701235
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_landscape.gif
Binary files differ
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_portrait.gif b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_portrait.gif
new file mode 100644
index 0000000..cc480ca
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/Fixtures/test_portrait.gif
Binary files differ
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php
new file mode 100644
index 0000000..2a8bcb3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
+use Symfony\Component\Validator\Constraints\GreaterThanOrEqualValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class GreaterThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new GreaterThanOrEqualValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new GreaterThanOrEqual($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return GreaterThanOrEqual::TOO_LOW_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(3, 2),
+ array(1, 1),
+ array(new \DateTime('2010/01/01'), new \DateTime('2000/01/01')),
+ array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01')),
+ array(new \DateTime('2010/01/01'), '2000/01/01'),
+ array(new \DateTime('2000/01/01'), '2000/01/01'),
+ array(new \DateTime('2010/01/01 UTC'), '2000/01/01 UTC'),
+ array(new \DateTime('2000/01/01 UTC'), '2000/01/01 UTC'),
+ array('a', 'a'),
+ array('z', 'a'),
+ array(null, 1),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(1, '1', 2, '2', 'integer'),
+ array(new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', new \DateTime('2005/01/01'), 'Jan 1, 2005, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', '2005/01/01', 'Jan 1, 2005, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01 UTC'), 'Jan 1, 2000, 12:00 AM', '2005/01/01 UTC', 'Jan 1, 2005, 12:00 AM', 'DateTime'),
+ array('b', '"b"', 'c', '"c"', 'string'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanValidatorTest.php
new file mode 100644
index 0000000..8e763fb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/GreaterThanValidatorTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\GreaterThan;
+use Symfony\Component\Validator\Constraints\GreaterThanValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class GreaterThanValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new GreaterThanValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new GreaterThan($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return GreaterThan::TOO_LOW_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(2, 1),
+ array(new \DateTime('2005/01/01'), new \DateTime('2001/01/01')),
+ array(new \DateTime('2005/01/01'), '2001/01/01'),
+ array(new \DateTime('2005/01/01 UTC'), '2001/01/01 UTC'),
+ array(new ComparisonTest_Class(5), new ComparisonTest_Class(4)),
+ array('333', '22'),
+ array(null, 1),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(1, '1', 2, '2', 'integer'),
+ array(2, '2', 2, '2', 'integer'),
+ array(new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', new \DateTime('2005/01/01'), 'Jan 1, 2005, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', '2005/01/01', 'Jan 1, 2005, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01'), 'Jan 1, 2000, 12:00 AM', '2000/01/01', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01 UTC'), 'Jan 1, 2000, 12:00 AM', '2005/01/01 UTC', 'Jan 1, 2005, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000/01/01 UTC'), 'Jan 1, 2000, 12:00 AM', '2000/01/01 UTC', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new ComparisonTest_Class(4), '4', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ array(new ComparisonTest_Class(5), '5', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ array('22', '"22"', '333', '"333"', 'string'),
+ array('22', '"22"', '22', '"22"', 'string'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/GroupSequenceTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/GroupSequenceTest.php
new file mode 100644
index 0000000..2b906a9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/GroupSequenceTest.php
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class GroupSequenceTest extends TestCase
+{
+ public function testCreate()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2'));
+
+ $this->assertSame(array('Group 1', 'Group 2'), $sequence->groups);
+ }
+
+ public function testCreateDoctrineStyle()
+ {
+ $sequence = new GroupSequence(array('value' => array('Group 1', 'Group 2')));
+
+ $this->assertSame(array('Group 1', 'Group 2'), $sequence->groups);
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyIterate()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2'));
+
+ $this->assertSame(array('Group 1', 'Group 2'), iterator_to_array($sequence));
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyCount()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2'));
+
+ $this->assertCount(2, $sequence);
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyArrayAccess()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2'));
+
+ $this->assertSame('Group 1', $sequence[0]);
+ $this->assertSame('Group 2', $sequence[1]);
+ $this->assertArrayHasKey(0, $sequence);
+ $this->assertArrayNotHasKey(2, $sequence);
+ unset($sequence[0]);
+ $this->assertArrayNotHasKey(0, $sequence);
+ $sequence[] = 'Group 3';
+ $this->assertArrayHasKey(2, $sequence);
+ $this->assertSame('Group 3', $sequence[2]);
+ $sequence[0] = 'Group 1';
+ $this->assertArrayHasKey(0, $sequence);
+ $this->assertSame('Group 1', $sequence[0]);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\OutOfBoundsException
+ * @group legacy
+ */
+ public function testLegacyGetExpectsExistingKey()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2'));
+
+ $sequence[2];
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyUnsetIgnoresNonExistingKeys()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2'));
+
+ // should not fail
+ unset($sequence[2]);
+
+ $this->assertCount(2, $sequence);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IbanValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IbanValidatorTest.php
new file mode 100644
index 0000000..16bf834
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IbanValidatorTest.php
@@ -0,0 +1,450 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Iban;
+use Symfony\Component\Validator\Constraints\IbanValidator;
+use Symfony\Component\Validator\Validation;
+
+class IbanValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IbanValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Iban());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Iban());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getValidIbans
+ */
+ public function testValidIbans($iban)
+ {
+ $this->validator->validate($iban, new Iban());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidIbans()
+ {
+ return array(
+ array('CH9300762011623852957'), // Switzerland without spaces
+ array('CH93 0076 2011 6238 5295 7'), // Switzerland with multiple spaces
+
+ // Country list
+ // http://www.rbs.co.uk/corporate/international/g0/guide-to-international-business/regulatory-information/iban/iban-example.ashx
+
+ array('AL47 2121 1009 0000 0002 3569 8741'), //Albania
+ array('AD12 0001 2030 2003 5910 0100'), //Andorra
+ array('AT61 1904 3002 3457 3201'), //Austria
+ array('AZ21 NABZ 0000 0000 1370 1000 1944'), //Azerbaijan
+ array('BH67 BMAG 0000 1299 1234 56'), //Bahrain
+ array('BE62 5100 0754 7061'), //Belgium
+ array('BA39 1290 0794 0102 8494'), //Bosnia and Herzegovina
+ array('BG80 BNBG 9661 1020 3456 78'), //Bulgaria
+ array('BY 13 NBRB 3600 900000002Z00AB00'), //Belarus
+ array('BY13 NBRB 3600 900000002Z00AB00'), //Belarus
+ array('BY22NB23324232T78YR7823HR32U'), //Belarus
+ array('HR12 1001 0051 8630 0016 0'), //Croatia
+ array('CY17 0020 0128 0000 0012 0052 7600'), //Cyprus
+ array('CZ65 0800 0000 1920 0014 5399'), //Czech Republic
+ array('DK50 0040 0440 1162 43'), //Denmark
+ array('EE38 2200 2210 2014 5685'), //Estonia
+ array('FO97 5432 0388 8999 44'), //Faroe Islands
+ array('FI21 1234 5600 0007 85'), //Finland
+ array('FR14 2004 1010 0505 0001 3M02 606'), //France
+ array('GE29 NB00 0000 0101 9049 17'), //Georgia
+ array('DE89 3704 0044 0532 0130 00'), //Germany
+ array('GI75 NWBK 0000 0000 7099 453'), //Gibraltar
+ array('GR16 0110 1250 0000 0001 2300 695'), //Greece
+ array('GL56 0444 9876 5432 10'), //Greenland
+ array('HU42 1177 3016 1111 1018 0000 0000'), //Hungary
+ array('IS14 0159 2600 7654 5510 7303 39'), //Iceland
+ array('IE29 AIBK 9311 5212 3456 78'), //Ireland
+ array('IL62 0108 0000 0009 9999 999'), //Israel
+ array('IT40 S054 2811 1010 0000 0123 456'), //Italy
+ array('LV80 BANK 0000 4351 9500 1'), //Latvia
+ array('LB62 0999 0000 0001 0019 0122 9114'), //Lebanon
+ array('LI21 0881 0000 2324 013A A'), //Liechtenstein
+ array('LT12 1000 0111 0100 1000'), //Lithuania
+ array('LU28 0019 4006 4475 0000'), //Luxembourg
+ array('MK072 5012 0000 0589 84'), //Macedonia
+ array('MT84 MALT 0110 0001 2345 MTLC AST0 01S'), //Malta
+ array('MU17 BOMM 0101 1010 3030 0200 000M UR'), //Mauritius
+ array('MD24 AG00 0225 1000 1310 4168'), //Moldova
+ array('MC93 2005 2222 1001 1223 3M44 555'), //Monaco
+ array('ME25 5050 0001 2345 6789 51'), //Montenegro
+ array('NL39 RABO 0300 0652 64'), //Netherlands
+ array('NO93 8601 1117 947'), //Norway
+ array('PK36 SCBL 0000 0011 2345 6702'), //Pakistan
+ array('PL60 1020 1026 0000 0422 7020 1111'), //Poland
+ array('PT50 0002 0123 1234 5678 9015 4'), //Portugal
+ array('RO49 AAAA 1B31 0075 9384 0000'), //Romania
+ array('SM86 U032 2509 8000 0000 0270 100'), //San Marino
+ array('SA03 8000 0000 6080 1016 7519'), //Saudi Arabia
+ array('RS35 2600 0560 1001 6113 79'), //Serbia
+ array('SK31 1200 0000 1987 4263 7541'), //Slovak Republic
+ array('SI56 1910 0000 0123 438'), //Slovenia
+ array('ES80 2310 0001 1800 0001 2345'), //Spain
+ array('SE35 5000 0000 0549 1000 0003'), //Sweden
+ array('CH93 0076 2011 6238 5295 7'), //Switzerland
+ array('TN59 1000 6035 1835 9847 8831'), //Tunisia
+ array('TR33 0006 1005 1978 6457 8413 26'), //Turkey
+ array('AE07 0331 2345 6789 0123 456'), //UAE
+ array('GB12 CPBK 0892 9965 0449 91'), //United Kingdom
+
+ //Extended country list
+ //http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html
+ // https://www.swift.com/sites/default/files/resources/iban_registry.pdf
+ array('AO06000600000100037131174'), //Angola
+ array('AZ21NABZ00000000137010001944'), //Azerbaijan
+ array('BH29BMAG1299123456BH00'), //Bahrain
+ array('BJ11B00610100400271101192591'), //Benin
+ array('BR9700360305000010009795493P1'), // Brazil
+ array('BR1800000000141455123924100C2'), // Brazil
+ array('VG96VPVG0000012345678901'), //British Virgin Islands
+ array('BF1030134020015400945000643'), //Burkina Faso
+ array('BI43201011067444'), //Burundi
+ array('CM2110003001000500000605306'), //Cameroon
+ array('CV64000300004547069110176'), //Cape Verde
+ array('FR7630007000110009970004942'), //Central African Republic
+ array('CG5230011000202151234567890'), //Congo
+ array('CR05015202001026284066'), //Costa Rica
+ array('DO28BAGR00000001212453611324'), //Dominican Republic
+ array('GT82TRAJ01020000001210029690'), //Guatemala
+ array('IR580540105180021273113007'), //Iran
+ array('IL620108000000099999999'), //Israel
+ array('CI05A00060174100178530011852'), //Ivory Coast
+ array('JO94CBJO0010000000000131000302'), // Jordan
+ array('KZ176010251000042993'), //Kazakhstan
+ array('KW74NBOK0000000000001000372151'), //Kuwait
+ array('LB30099900000001001925579115'), //Lebanon
+ array('MG4600005030010101914016056'), //Madagascar
+ array('ML03D00890170001002120000447'), //Mali
+ array('MR1300012000010000002037372'), //Mauritania
+ array('MU17BOMM0101101030300200000MUR'), //Mauritius
+ array('MZ59000100000011834194157'), //Mozambique
+ array('PS92PALS000000000400123456702'), //Palestinian Territory
+ array('QA58DOHB00001234567890ABCDEFG'), //Qatar
+ array('XK051212012345678906'), //Republic of Kosovo
+ array('PT50000200000163099310355'), //Sao Tome and Principe
+ array('SA0380000000608010167519'), //Saudi Arabia
+ array('SN12K00100152000025690007542'), //Senegal
+ array('TL380080012345678910157'), //Timor-Leste
+ array('TN5914207207100707129648'), //Tunisia
+ array('TR330006100519786457841326'), //Turkey
+ array('UA213223130000026007233566001'), //Ukraine
+ array('AE260211000000230064016'), //United Arab Emirates
+ );
+ }
+
+ /**
+ * @dataProvider getIbansWithInvalidFormat
+ */
+ public function testIbansWithInvalidFormat($iban)
+ {
+ $this->assertViolationRaised($iban, Iban::INVALID_FORMAT_ERROR);
+ }
+
+ public function getIbansWithInvalidFormat()
+ {
+ return array(
+ array('AL47 2121 1009 0000 0002 3569 874'), //Albania
+ array('AD12 0001 2030 2003 5910 010'), //Andorra
+ array('AT61 1904 3002 3457 320'), //Austria
+ array('AZ21 NABZ 0000 0000 1370 1000 194'), //Azerbaijan
+ array('AZ21 N1BZ 0000 0000 1370 1000 1944'), //Azerbaijan
+ array('BH67 BMAG 0000 1299 1234 5'), //Bahrain
+ array('BH67 B2AG 0000 1299 1234 56'), //Bahrain
+ array('BE62 5100 0754 7061 2'), //Belgium
+ array('BA39 1290 0794 0102 8494 4'), //Bosnia and Herzegovina
+ array('BG80 BNBG 9661 1020 3456 7'), //Bulgaria
+ array('BG80 B2BG 9661 1020 3456 78'), //Bulgaria
+ array('BY 13 NBRB 3600 900000002Z00AB001'), //Belarus
+ array('BY 13 NBRB 3600 900000002Z00AB0'), //Belarus
+ array('BYRO NBRB 3600 900000002Z00AB0'), //Belarus
+ array('BY 13 3600 NBRB 900000002Z00AB05'), //Belarus
+ array('HR12 1001 0051 8630 0016 01'), //Croatia
+ array('CY17 0020 0128 0000 0012 0052 7600 1'), //Cyprus
+ array('CZ65 0800 0000 1920 0014 5399 1'), //Czech Republic
+ array('DK50 0040 0440 1162 431'), //Denmark
+ array('EE38 2200 2210 2014 5685 1'), //Estonia
+ array('FO97 5432 0388 8999 441'), //Faroe Islands
+ array('FI21 1234 5600 0007 851'), //Finland
+ array('FR14 2004 1010 0505 0001 3M02 6061'), //France
+ array('GE29 NB00 0000 0101 9049 171'), //Georgia
+ array('DE89 3704 0044 0532 0130 001'), //Germany
+ array('GI75 NWBK 0000 0000 7099 4531'), //Gibraltar
+ array('GR16 0110 1250 0000 0001 2300 6951'), //Greece
+ array('GL56 0444 9876 5432 101'), //Greenland
+ array('HU42 1177 3016 1111 1018 0000 0000 1'), //Hungary
+ array('IS14 0159 2600 7654 5510 7303 391'), //Iceland
+ array('IE29 AIBK 9311 5212 3456 781'), //Ireland
+ array('IL62 0108 0000 0009 9999 9991'), //Israel
+ array('IT40 S054 2811 1010 0000 0123 4561'), //Italy
+ array('LV80 BANK 0000 4351 9500 11'), //Latvia
+ array('LB62 0999 0000 0001 0019 0122 9114 1'), //Lebanon
+ array('LI21 0881 0000 2324 013A A1'), //Liechtenstein
+ array('LT12 1000 0111 0100 1000 1'), //Lithuania
+ array('LU28 0019 4006 4475 0000 1'), //Luxembourg
+ array('MK072 5012 0000 0589 84 1'), //Macedonia
+ array('MT84 MALT 0110 0001 2345 MTLC AST0 01SA'), //Malta
+ array('MU17 BOMM 0101 1010 3030 0200 000M URA'), //Mauritius
+ array('MD24 AG00 0225 1000 1310 4168 1'), //Moldova
+ array('MC93 2005 2222 1001 1223 3M44 5551'), //Monaco
+ array('ME25 5050 0001 2345 6789 511'), //Montenegro
+ array('NL39 RABO 0300 0652 641'), //Netherlands
+ array('NO93 8601 1117 9471'), //Norway
+ array('PK36 SCBL 0000 0011 2345 6702 1'), //Pakistan
+ array('PL60 1020 1026 0000 0422 7020 1111 1'), //Poland
+ array('PT50 0002 0123 1234 5678 9015 41'), //Portugal
+ array('RO49 AAAA 1B31 0075 9384 0000 1'), //Romania
+ array('SM86 U032 2509 8000 0000 0270 1001'), //San Marino
+ array('SA03 8000 0000 6080 1016 7519 1'), //Saudi Arabia
+ array('RS35 2600 0560 1001 6113 791'), //Serbia
+ array('SK31 1200 0000 1987 4263 7541 1'), //Slovak Republic
+ array('SI56 1910 0000 0123 4381'), //Slovenia
+ array('ES80 2310 0001 1800 0001 2345 1'), //Spain
+ array('SE35 5000 0000 0549 1000 0003 1'), //Sweden
+ array('CH93 0076 2011 6238 5295 71'), //Switzerland
+ array('TN59 1000 6035 1835 9847 8831 1'), //Tunisia
+ array('TR33 0006 1005 1978 6457 8413 261'), //Turkey
+ array('AE07 0331 2345 6789 0123 4561'), //UAE
+ array('GB12 CPBK 0892 9965 0449 911'), //United Kingdom
+
+ //Extended country list
+ array('AO060006000001000371311741'), //Angola
+ array('AZ21NABZ000000001370100019441'), //Azerbaijan
+ array('BH29BMAG1299123456BH001'), //Bahrain
+ array('BJ11B006101004002711011925911'), //Benin
+ array('BR9700360305000010009795493P11'), // Brazil
+ array('BR1800000000141455123924100C21'), // Brazil
+ array('VG96VPVG00000123456789011'), //British Virgin Islands
+ array('BF10301340200154009450006431'), //Burkina Faso
+ array('BI432010110674441'), //Burundi
+ array('CM21100030010005000006053061'), //Cameroon
+ array('CV640003000045470691101761'), //Cape Verde
+ array('FR76300070001100099700049421'), //Central African Republic
+ array('CG52300110002021512345678901'), //Congo
+ array('CR05152020010262840661'), //Costa Rica
+ array('CR0515202001026284066'), //Costa Rica
+ array('DO28BAGR000000012124536113241'), //Dominican Republic
+ array('GT82TRAJ010200000012100296901'), //Guatemala
+ array('IR5805401051800212731130071'), //Iran
+ array('IL6201080000000999999991'), //Israel
+ array('CI05A000601741001785300118521'), //Ivory Coast
+ array('JO94CBJO00100000000001310003021'), // Jordan
+ array('KZ1760102510000429931'), //Kazakhstan
+ array('KW74NBOK00000000000010003721511'), //Kuwait
+ array('LB300999000000010019255791151'), //Lebanon
+ array('MG46000050300101019140160561'), //Madagascar
+ array('ML03D008901700010021200004471'), //Mali
+ array('MR13000120000100000020373721'), //Mauritania
+ array('MU17BOMM0101101030300200000MUR1'), //Mauritius
+ array('MZ590001000000118341941571'), //Mozambique
+ array('PS92PALS0000000004001234567021'), //Palestinian Territory
+ array('QA58DOHB00001234567890ABCDEFG1'), //Qatar
+ array('XK0512120123456789061'), //Republic of Kosovo
+ array('PT500002000001630993103551'), //Sao Tome and Principe
+ array('SA03800000006080101675191'), //Saudi Arabia
+ array('SN12K001001520000256900075421'), //Senegal
+ array('TL3800800123456789101571'), //Timor-Leste
+ array('TN59142072071007071296481'), //Tunisia
+ array('TR3300061005197864578413261'), //Turkey
+ array('UA21AAAA1300000260072335660012'), //Ukraine
+ array('AE2602110000002300640161'), //United Arab Emirates
+ );
+ }
+
+ /**
+ * @dataProvider getIbansWithValidFormatButIncorrectChecksum
+ */
+ public function testIbansWithValidFormatButIncorrectChecksum($iban)
+ {
+ $this->assertViolationRaised($iban, Iban::CHECKSUM_FAILED_ERROR);
+ }
+
+ public function getIbansWithValidFormatButIncorrectChecksum()
+ {
+ return array(
+ array('AL47 2121 1009 0000 0002 3569 8742'), //Albania
+ array('AD12 0001 2030 2003 5910 0101'), //Andorra
+ array('AT61 1904 3002 3457 3202'), //Austria
+ array('AZ21 NABZ 0000 0000 1370 1000 1945'), //Azerbaijan
+ array('BH67 BMAG 0000 1299 1234 57'), //Bahrain
+ array('BE62 5100 0754 7062'), //Belgium
+ array('BA39 1290 0794 0102 8495'), //Bosnia and Herzegovina
+ array('BG80 BNBG 9661 1020 3456 79'), //Bulgaria
+ array('BY90 NBRB 3600 900000002Z00AB00'), //Belarus
+ array('HR12 1001 0051 8630 0016 1'), //Croatia
+ array('CY17 0020 0128 0000 0012 0052 7601'), //Cyprus
+ array('CZ65 0800 0000 1920 0014 5398'), //Czech Republic
+ array('DK50 0040 0440 1162 44'), //Denmark
+ array('EE38 2200 2210 2014 5684'), //Estonia
+ array('FO97 5432 0388 8999 43'), //Faroe Islands
+ array('FI21 1234 5600 0007 84'), //Finland
+ array('FR14 2004 1010 0505 0001 3M02 605'), //France
+ array('GE29 NB00 0000 0101 9049 16'), //Georgia
+ array('DE89 3704 0044 0532 0130 01'), //Germany
+ array('GI75 NWBK 0000 0000 7099 452'), //Gibraltar
+ array('GR16 0110 1250 0000 0001 2300 694'), //Greece
+ array('GL56 0444 9876 5432 11'), //Greenland
+ array('HU42 1177 3016 1111 1018 0000 0001'), //Hungary
+ array('IS14 0159 2600 7654 5510 7303 38'), //Iceland
+ array('IE29 AIBK 9311 5212 3456 79'), //Ireland
+ array('IL62 0108 0000 0009 9999 998'), //Israel
+ array('IT40 S054 2811 1010 0000 0123 457'), //Italy
+ array('LV80 BANK 0000 4351 9500 2'), //Latvia
+ array('LB62 0999 0000 0001 0019 0122 9115'), //Lebanon
+ array('LI21 0881 0000 2324 013A B'), //Liechtenstein
+ array('LT12 1000 0111 0100 1001'), //Lithuania
+ array('LU28 0019 4006 4475 0001'), //Luxembourg
+ array('MK072 5012 0000 0589 85'), //Macedonia
+ array('MT84 MALT 0110 0001 2345 MTLC AST0 01T'), //Malta
+ array('MU17 BOMM 0101 1010 3030 0200 000M UP'), //Mauritius
+ array('MD24 AG00 0225 1000 1310 4169'), //Moldova
+ array('MC93 2005 2222 1001 1223 3M44 554'), //Monaco
+ array('ME25 5050 0001 2345 6789 52'), //Montenegro
+ array('NL39 RABO 0300 0652 65'), //Netherlands
+ array('NO93 8601 1117 948'), //Norway
+ array('PK36 SCBL 0000 0011 2345 6703'), //Pakistan
+ array('PL60 1020 1026 0000 0422 7020 1112'), //Poland
+ array('PT50 0002 0123 1234 5678 9015 5'), //Portugal
+ array('RO49 AAAA 1B31 0075 9384 0001'), //Romania
+ array('SM86 U032 2509 8000 0000 0270 101'), //San Marino
+ array('SA03 8000 0000 6080 1016 7518'), //Saudi Arabia
+ array('RS35 2600 0560 1001 6113 78'), //Serbia
+ array('SK31 1200 0000 1987 4263 7542'), //Slovak Republic
+ array('SI56 1910 0000 0123 439'), //Slovenia
+ array('ES80 2310 0001 1800 0001 2346'), //Spain
+ array('SE35 5000 0000 0549 1000 0004'), //Sweden
+ array('CH93 0076 2011 6238 5295 8'), //Switzerland
+ array('TN59 1000 6035 1835 9847 8832'), //Tunisia
+ array('TR33 0006 1005 1978 6457 8413 27'), //Turkey
+ array('AE07 0331 2345 6789 0123 457'), //UAE
+ array('GB12 CPBK 0892 9965 0449 92'), //United Kingdom
+
+ //Extended country list
+ array('AO06000600000100037131175'), //Angola
+ array('AZ21NABZ00000000137010001945'), //Azerbaijan
+ array('BH29BMAG1299123456BH01'), //Bahrain
+ array('BJ11B00610100400271101192592'), //Benin
+ array('BR9700360305000010009795493P2'), // Brazil
+ array('BR1800000000141455123924100C3'), // Brazil
+ array('VG96VPVG0000012345678902'), //British Virgin Islands
+ array('BF1030134020015400945000644'), //Burkina Faso
+ array('BI43201011067445'), //Burundi
+ array('CM2110003001000500000605307'), //Cameroon
+ array('CV64000300004547069110177'), //Cape Verde
+ array('FR7630007000110009970004943'), //Central African Republic
+ array('CG5230011000202151234567891'), //Congo
+ array('CR96042332432534543564'), //Costa Rica
+ array('DO28BAGR00000001212453611325'), //Dominican Republic
+ array('GT82TRAJ01020000001210029691'), //Guatemala
+ array('IR580540105180021273113008'), //Iran
+ array('IL620108000000099999998'), //Israel
+ array('CI05A00060174100178530011853'), //Ivory Coast
+ array('JO94CBJO0010000000000131000303'), // Jordan
+ array('KZ176010251000042994'), //Kazakhstan
+ array('KW74NBOK0000000000001000372152'), //Kuwait
+ array('LB30099900000001001925579116'), //Lebanon
+ array('MG4600005030010101914016057'), //Madagascar
+ array('ML03D00890170001002120000448'), //Mali
+ array('MR1300012000010000002037373'), //Mauritania
+ array('MU17BOMM0101101030300200000MUP'), //Mauritius
+ array('MZ59000100000011834194158'), //Mozambique
+ array('PS92PALS000000000400123456703'), //Palestinian Territory
+ array('QA58DOHB00001234567890ABCDEFH'), //Qatar
+ array('XK051212012345678907'), //Republic of Kosovo
+ array('PT50000200000163099310356'), //Sao Tome and Principe
+ array('SA0380000000608010167518'), //Saudi Arabia
+ array('SN12K00100152000025690007543'), //Senegal
+ array('TL380080012345678910158'), //Timor-Leste
+ array('TN5914207207100707129649'), //Tunisia
+ array('TR330006100519786457841327'), //Turkey
+ array('UA213223130000026007233566002'), //Ukraine
+ array('AE260211000000230064017'), //United Arab Emirates
+ );
+ }
+
+ /**
+ * @dataProvider getUnsupportedCountryCodes
+ */
+ public function testIbansWithUnsupportedCountryCode($countryCode)
+ {
+ $this->assertViolationRaised($countryCode.'260211000000230064016', Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR);
+ }
+
+ public function getUnsupportedCountryCodes()
+ {
+ return array(
+ array('AG'),
+ array('AI'),
+ array('AQ'),
+ array('AS'),
+ array('AW'),
+ );
+ }
+
+ public function testIbansWithInvalidCharacters()
+ {
+ $this->assertViolationRaised('CH930076201162385295]', Iban::INVALID_CHARACTERS_ERROR);
+ }
+
+ /**
+ * @dataProvider getIbansWithInvalidCountryCode
+ */
+ public function testIbansWithInvalidCountryCode($iban)
+ {
+ $this->assertViolationRaised($iban, Iban::INVALID_COUNTRY_CODE_ERROR);
+ }
+
+ public function getIbansWithInvalidCountryCode()
+ {
+ return array(
+ array('0750447346'),
+ array('2X0750447346'),
+ array('A20750447346'),
+ );
+ }
+
+ private function assertViolationRaised($iban, $code)
+ {
+ $constraint = new Iban(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($iban, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$iban.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IdenticalToValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IdenticalToValidatorTest.php
new file mode 100644
index 0000000..4999919
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IdenticalToValidatorTest.php
@@ -0,0 +1,94 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\IdenticalTo;
+use Symfony\Component\Validator\Constraints\IdenticalToValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class IdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IdenticalToValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new IdenticalTo($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return IdenticalTo::NOT_IDENTICAL_ERROR;
+ }
+
+ public function provideAllValidComparisons()
+ {
+ $this->setDefaultTimezone('UTC');
+
+ // Don't call addPhp5Dot5Comparisons() automatically, as it does
+ // not take care of identical objects
+ $comparisons = $this->provideValidComparisons();
+
+ $this->restoreDefaultTimezone();
+
+ return $comparisons;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ $date = new \DateTime('2000-01-01');
+ $object = new ComparisonTest_Class(2);
+
+ $comparisons = array(
+ array(3, 3),
+ array('a', 'a'),
+ array($date, $date),
+ array($object, $object),
+ array(null, 1),
+ );
+
+ if (\PHP_VERSION_ID >= 50500) {
+ $immutableDate = new \DateTimeImmutable('2000-01-01');
+ $comparisons[] = array($immutableDate, $immutableDate);
+ }
+
+ return $comparisons;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(1, '1', 2, '2', 'integer'),
+ array(2, '2', '2', '"2"', 'string'),
+ array('22', '"22"', '333', '"333"', 'string'),
+ array(new \DateTime('2001-01-01'), 'Jan 1, 2001, 12:00 AM', new \DateTime('2001-01-01'), 'Jan 1, 2001, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2001-01-01'), 'Jan 1, 2001, 12:00 AM', new \DateTime('1999-01-01'), 'Jan 1, 1999, 12:00 AM', 'DateTime'),
+ array(new ComparisonTest_Class(4), '4', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/ImageValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ImageValidatorTest.php
new file mode 100644
index 0000000..4605a06
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ImageValidatorTest.php
@@ -0,0 +1,332 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Image;
+use Symfony\Component\Validator\Constraints\ImageValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @requires extension fileinfo
+ */
+class ImageValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected $context;
+
+ /**
+ * @var ImageValidator
+ */
+ protected $validator;
+
+ protected $path;
+ protected $image;
+ protected $imageLandscape;
+ protected $imagePortrait;
+ protected $image4By3;
+
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new ImageValidator();
+ }
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->image = __DIR__.'/Fixtures/test.gif';
+ $this->imageLandscape = __DIR__.'/Fixtures/test_landscape.gif';
+ $this->imagePortrait = __DIR__.'/Fixtures/test_portrait.gif';
+ $this->image4By3 = __DIR__.'/Fixtures/test_4by3.gif';
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Image());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Image());
+
+ $this->assertNoViolation();
+ }
+
+ public function testValidImage()
+ {
+ $this->validator->validate($this->image, new Image());
+
+ $this->assertNoViolation();
+ }
+
+ public function testFileNotFound()
+ {
+ // Check that the logic from FileValidator still works
+ $constraint = new Image(array(
+ 'notFoundMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate('foobar', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ file }}', '"foobar"')
+ ->setCode(Image::NOT_FOUND_ERROR)
+ ->assertRaised();
+ }
+
+ public function testValidSize()
+ {
+ $constraint = new Image(array(
+ 'minWidth' => 1,
+ 'maxWidth' => 2,
+ 'minHeight' => 1,
+ 'maxHeight' => 2,
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testWidthTooSmall()
+ {
+ $constraint = new Image(array(
+ 'minWidth' => 3,
+ 'minWidthMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ width }}', '2')
+ ->setParameter('{{ min_width }}', '3')
+ ->setCode(Image::TOO_NARROW_ERROR)
+ ->assertRaised();
+ }
+
+ public function testWidthTooBig()
+ {
+ $constraint = new Image(array(
+ 'maxWidth' => 1,
+ 'maxWidthMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ width }}', '2')
+ ->setParameter('{{ max_width }}', '1')
+ ->setCode(Image::TOO_WIDE_ERROR)
+ ->assertRaised();
+ }
+
+ public function testHeightTooSmall()
+ {
+ $constraint = new Image(array(
+ 'minHeight' => 3,
+ 'minHeightMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ height }}', '2')
+ ->setParameter('{{ min_height }}', '3')
+ ->setCode(Image::TOO_LOW_ERROR)
+ ->assertRaised();
+ }
+
+ public function testHeightTooBig()
+ {
+ $constraint = new Image(array(
+ 'maxHeight' => 1,
+ 'maxHeightMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ height }}', '2')
+ ->setParameter('{{ max_height }}', '1')
+ ->setCode(Image::TOO_HIGH_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMinWidth()
+ {
+ $constraint = new Image(array(
+ 'minWidth' => '1abc',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMaxWidth()
+ {
+ $constraint = new Image(array(
+ 'maxWidth' => '1abc',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMinHeight()
+ {
+ $constraint = new Image(array(
+ 'minHeight' => '1abc',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMaxHeight()
+ {
+ $constraint = new Image(array(
+ 'maxHeight' => '1abc',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+ }
+
+ public function testRatioTooSmall()
+ {
+ $constraint = new Image(array(
+ 'minRatio' => 2,
+ 'minRatioMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ ratio }}', 1)
+ ->setParameter('{{ min_ratio }}', 2)
+ ->setCode(Image::RATIO_TOO_SMALL_ERROR)
+ ->assertRaised();
+ }
+
+ public function testRatioTooBig()
+ {
+ $constraint = new Image(array(
+ 'maxRatio' => 0.5,
+ 'maxRatioMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ ratio }}', 1)
+ ->setParameter('{{ max_ratio }}', 0.5)
+ ->setCode(Image::RATIO_TOO_BIG_ERROR)
+ ->assertRaised();
+ }
+
+ public function testMaxRatioUsesTwoDecimalsOnly()
+ {
+ $constraint = new Image(array(
+ 'maxRatio' => 1.33,
+ ));
+
+ $this->validator->validate($this->image4By3, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMinRatio()
+ {
+ $constraint = new Image(array(
+ 'minRatio' => '1abc',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidMaxRatio()
+ {
+ $constraint = new Image(array(
+ 'maxRatio' => '1abc',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+ }
+
+ public function testSquareNotAllowed()
+ {
+ $constraint = new Image(array(
+ 'allowSquare' => false,
+ 'allowSquareMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->image, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ width }}', 2)
+ ->setParameter('{{ height }}', 2)
+ ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testLandscapeNotAllowed()
+ {
+ $constraint = new Image(array(
+ 'allowLandscape' => false,
+ 'allowLandscapeMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->imageLandscape, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ width }}', 2)
+ ->setParameter('{{ height }}', 1)
+ ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
+ ->assertRaised();
+ }
+
+ public function testPortraitNotAllowed()
+ {
+ $constraint = new Image(array(
+ 'allowPortrait' => false,
+ 'allowPortraitMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($this->imagePortrait, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ width }}', 1)
+ ->setParameter('{{ height }}', 2)
+ ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IpValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IpValidatorTest.php
new file mode 100644
index 0000000..bcb5f59
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IpValidatorTest.php
@@ -0,0 +1,456 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Ip;
+use Symfony\Component\Validator\Constraints\IpValidator;
+use Symfony\Component\Validator\Validation;
+
+class IpValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IpValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Ip());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Ip());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Ip());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testInvalidValidatorVersion()
+ {
+ new Ip(array(
+ 'version' => 666,
+ ));
+ }
+
+ /**
+ * @dataProvider getValidIpsV4
+ */
+ public function testValidIpsV4($ip)
+ {
+ $this->validator->validate($ip, new Ip(array(
+ 'version' => Ip::V4,
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidIpsV4()
+ {
+ return array(
+ array('0.0.0.0'),
+ array('10.0.0.0'),
+ array('123.45.67.178'),
+ array('172.16.0.0'),
+ array('192.168.1.0'),
+ array('224.0.0.1'),
+ array('255.255.255.255'),
+ array('127.0.0.0'),
+ );
+ }
+
+ /**
+ * @dataProvider getValidIpsV6
+ */
+ public function testValidIpsV6($ip)
+ {
+ $this->validator->validate($ip, new Ip(array(
+ 'version' => Ip::V6,
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidIpsV6()
+ {
+ return array(
+ array('2001:0db8:85a3:0000:0000:8a2e:0370:7334'),
+ array('2001:0DB8:85A3:0000:0000:8A2E:0370:7334'),
+ array('2001:0Db8:85a3:0000:0000:8A2e:0370:7334'),
+ array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
+ array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
+ array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
+ array('fe80:0000:0000:0000:0202:b3ff:fe1e:8329'),
+ array('fe80:0:0:0:202:b3ff:fe1e:8329'),
+ array('fe80::202:b3ff:fe1e:8329'),
+ array('0:0:0:0:0:0:0:0'),
+ array('::'),
+ array('0::'),
+ array('::0'),
+ array('0::0'),
+ // IPv4 mapped to IPv6
+ array('2001:0db8:85a3:0000:0000:8a2e:0.0.0.0'),
+ array('::0.0.0.0'),
+ array('::255.255.255.255'),
+ array('::123.45.67.178'),
+ );
+ }
+
+ /**
+ * @dataProvider getValidIpsAll
+ */
+ public function testValidIpsAll($ip)
+ {
+ $this->validator->validate($ip, new Ip(array(
+ 'version' => Ip::ALL,
+ )));
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidIpsAll()
+ {
+ return array_merge($this->getValidIpsV4(), $this->getValidIpsV6());
+ }
+
+ /**
+ * @dataProvider getInvalidIpsV4
+ */
+ public function testInvalidIpsV4($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V4,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidIpsV4()
+ {
+ return array(
+ array('0'),
+ array('0.0'),
+ array('0.0.0'),
+ array('256.0.0.0'),
+ array('0.256.0.0'),
+ array('0.0.256.0'),
+ array('0.0.0.256'),
+ array('-1.0.0.0'),
+ array('foobar'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidPrivateIpsV4
+ */
+ public function testInvalidPrivateIpsV4($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V4_NO_PRIV,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidPrivateIpsV4()
+ {
+ return array(
+ array('10.0.0.0'),
+ array('172.16.0.0'),
+ array('192.168.1.0'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidReservedIpsV4
+ */
+ public function testInvalidReservedIpsV4($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V4_NO_RES,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidReservedIpsV4()
+ {
+ return array(
+ array('0.0.0.0'),
+ array('240.0.0.1'),
+ array('255.255.255.255'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidPublicIpsV4
+ */
+ public function testInvalidPublicIpsV4($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V4_ONLY_PUBLIC,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidPublicIpsV4()
+ {
+ return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidReservedIpsV4());
+ }
+
+ /**
+ * @dataProvider getInvalidIpsV6
+ */
+ public function testInvalidIpsV6($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V6,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidIpsV6()
+ {
+ return array(
+ array('z001:0db8:85a3:0000:0000:8a2e:0370:7334'),
+ array('fe80'),
+ array('fe80:8329'),
+ array('fe80:::202:b3ff:fe1e:8329'),
+ array('fe80::202:b3ff::fe1e:8329'),
+ // IPv4 mapped to IPv6
+ array('2001:0db8:85a3:0000:0000:8a2e:0370:0.0.0.0'),
+ array('::0.0'),
+ array('::0.0.0'),
+ array('::256.0.0.0'),
+ array('::0.256.0.0'),
+ array('::0.0.256.0'),
+ array('::0.0.0.256'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidPrivateIpsV6
+ */
+ public function testInvalidPrivateIpsV6($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V6_NO_PRIV,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidPrivateIpsV6()
+ {
+ return array(
+ array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
+ array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
+ array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidReservedIpsV6
+ */
+ public function testInvalidReservedIpsV6($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V6_NO_RES,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidReservedIpsV6()
+ {
+ // Quoting after official filter documentation:
+ // "FILTER_FLAG_NO_RES_RANGE = This flag does not apply to IPv6 addresses."
+ // Full description: http://php.net/manual/en/filter.filters.flags.php
+ return $this->getInvalidIpsV6();
+ }
+
+ /**
+ * @dataProvider getInvalidPublicIpsV6
+ */
+ public function testInvalidPublicIpsV6($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::V6_ONLY_PUBLIC,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidPublicIpsV6()
+ {
+ return array_merge($this->getInvalidPrivateIpsV6(), $this->getInvalidReservedIpsV6());
+ }
+
+ /**
+ * @dataProvider getInvalidIpsAll
+ */
+ public function testInvalidIpsAll($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::ALL,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidIpsAll()
+ {
+ return array_merge($this->getInvalidIpsV4(), $this->getInvalidIpsV6());
+ }
+
+ /**
+ * @dataProvider getInvalidPrivateIpsAll
+ */
+ public function testInvalidPrivateIpsAll($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::ALL_NO_PRIV,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidPrivateIpsAll()
+ {
+ return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidPrivateIpsV6());
+ }
+
+ /**
+ * @dataProvider getInvalidReservedIpsAll
+ */
+ public function testInvalidReservedIpsAll($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::ALL_NO_RES,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidReservedIpsAll()
+ {
+ return array_merge($this->getInvalidReservedIpsV4(), $this->getInvalidReservedIpsV6());
+ }
+
+ /**
+ * @dataProvider getInvalidPublicIpsAll
+ */
+ public function testInvalidPublicIpsAll($ip)
+ {
+ $constraint = new Ip(array(
+ 'version' => Ip::ALL_ONLY_PUBLIC,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($ip, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$ip.'"')
+ ->setCode(Ip::INVALID_IP_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidPublicIpsAll()
+ {
+ return array_merge($this->getInvalidPublicIpsV4(), $this->getInvalidPublicIpsV6());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsFalseValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsFalseValidatorTest.php
new file mode 100644
index 0000000..46cadec
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsFalseValidatorTest.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\IsFalse;
+use Symfony\Component\Validator\Constraints\IsFalseValidator;
+use Symfony\Component\Validator\Validation;
+
+class IsFalseValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IsFalseValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new IsFalse());
+
+ $this->assertNoViolation();
+ }
+
+ public function testFalseIsValid()
+ {
+ $this->validator->validate(false, new IsFalse());
+
+ $this->assertNoViolation();
+ }
+
+ public function testTrueIsInvalid()
+ {
+ $constraint = new IsFalse(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(true, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'true')
+ ->setCode(IsFalse::NOT_FALSE_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsNullValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsNullValidatorTest.php
new file mode 100644
index 0000000..5a55753
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsNullValidatorTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\IsNull;
+use Symfony\Component\Validator\Constraints\IsNullValidator;
+use Symfony\Component\Validator\Validation;
+
+class IsNullValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IsNullValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new IsNull());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidValues
+ */
+ public function testInvalidValues($value, $valueAsString)
+ {
+ $constraint = new IsNull(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $valueAsString)
+ ->setCode(IsNull::NOT_NULL_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidValues()
+ {
+ return array(
+ array(0, '0'),
+ array(false, 'false'),
+ array(true, 'true'),
+ array('', '""'),
+ array('foo bar', '"foo bar"'),
+ array(new \DateTime(), 'object'),
+ array(new \stdClass(), 'object'),
+ array(array(), 'array'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsTrueValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsTrueValidatorTest.php
new file mode 100644
index 0000000..1c5927d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsTrueValidatorTest.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\IsTrue;
+use Symfony\Component\Validator\Constraints\IsTrueValidator;
+use Symfony\Component\Validator\Validation;
+
+class IsTrueValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IsTrueValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new IsTrue());
+
+ $this->assertNoViolation();
+ }
+
+ public function testTrueIsValid()
+ {
+ $this->validator->validate(true, new IsTrue());
+
+ $this->assertNoViolation();
+ }
+
+ public function testFalseIsInvalid()
+ {
+ $constraint = new IsTrue(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(false, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'false')
+ ->setCode(IsTrue::NOT_TRUE_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsbnValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsbnValidatorTest.php
new file mode 100644
index 0000000..314739f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IsbnValidatorTest.php
@@ -0,0 +1,271 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Isbn;
+use Symfony\Component\Validator\Constraints\IsbnValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @see https://en.wikipedia.org/wiki/Isbn
+ */
+class IsbnValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IsbnValidator();
+ }
+
+ public function getValidIsbn10()
+ {
+ return array(
+ array('2723442284'),
+ array('2723442276'),
+ array('2723455041'),
+ array('2070546810'),
+ array('2711858839'),
+ array('2756406767'),
+ array('2870971648'),
+ array('226623854X'),
+ array('2851806424'),
+ array('0321812700'),
+ array('0-45122-5244'),
+ array('0-4712-92311'),
+ array('0-9752298-0-X'),
+ );
+ }
+
+ public function getInvalidIsbn10()
+ {
+ return array(
+ array('27234422841', Isbn::TOO_LONG_ERROR),
+ array('272344228', Isbn::TOO_SHORT_ERROR),
+ array('0-4712-9231', Isbn::TOO_SHORT_ERROR),
+ array('1234567890', Isbn::CHECKSUM_FAILED_ERROR),
+ array('0987656789', Isbn::CHECKSUM_FAILED_ERROR),
+ array('7-35622-5444', Isbn::CHECKSUM_FAILED_ERROR),
+ array('0-4X19-92611', Isbn::CHECKSUM_FAILED_ERROR),
+ array('0_45122_5244', Isbn::INVALID_CHARACTERS_ERROR),
+ array('2870#971#648', Isbn::INVALID_CHARACTERS_ERROR),
+ array('0-9752298-0-x', Isbn::INVALID_CHARACTERS_ERROR),
+ array('1A34567890', Isbn::INVALID_CHARACTERS_ERROR),
+ // chr(1) evaluates to 0
+ // 2070546810 is valid
+ array('2'.\chr(1).'70546810', Isbn::INVALID_CHARACTERS_ERROR),
+ );
+ }
+
+ public function getValidIsbn13()
+ {
+ return array(
+ array('978-2723442282'),
+ array('978-2723442275'),
+ array('978-2723455046'),
+ array('978-2070546817'),
+ array('978-2711858835'),
+ array('978-2756406763'),
+ array('978-2870971642'),
+ array('978-2266238540'),
+ array('978-2851806420'),
+ array('978-0321812704'),
+ array('978-0451225245'),
+ array('978-0471292319'),
+ );
+ }
+
+ public function getInvalidIsbn13()
+ {
+ return array(
+ array('978-27234422821', Isbn::TOO_LONG_ERROR),
+ array('978-272344228', Isbn::TOO_SHORT_ERROR),
+ array('978-2723442-82', Isbn::TOO_SHORT_ERROR),
+ array('978-2723442281', Isbn::CHECKSUM_FAILED_ERROR),
+ array('978-0321513774', Isbn::CHECKSUM_FAILED_ERROR),
+ array('979-0431225385', Isbn::CHECKSUM_FAILED_ERROR),
+ array('980-0474292319', Isbn::CHECKSUM_FAILED_ERROR),
+ array('0-4X19-92619812', Isbn::INVALID_CHARACTERS_ERROR),
+ array('978_2723442282', Isbn::INVALID_CHARACTERS_ERROR),
+ array('978#2723442282', Isbn::INVALID_CHARACTERS_ERROR),
+ array('978-272C442282', Isbn::INVALID_CHARACTERS_ERROR),
+ // chr(1) evaluates to 0
+ // 978-2070546817 is valid
+ array('978-2'.\chr(1).'70546817', Isbn::INVALID_CHARACTERS_ERROR),
+ );
+ }
+
+ public function getValidIsbn()
+ {
+ return array_merge(
+ $this->getValidIsbn10(),
+ $this->getValidIsbn13()
+ );
+ }
+
+ public function getInvalidIsbn()
+ {
+ return array_merge(
+ $this->getInvalidIsbn10(),
+ $this->getInvalidIsbn13()
+ );
+ }
+
+ public function testNullIsValid()
+ {
+ $constraint = new Isbn(true);
+
+ $this->validator->validate(null, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $constraint = new Isbn(true);
+
+ $this->validator->validate('', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $constraint = new Isbn(true);
+
+ $this->validator->validate(new \stdClass(), $constraint);
+ }
+
+ /**
+ * @dataProvider getValidIsbn10
+ */
+ public function testValidIsbn10($isbn)
+ {
+ $constraint = new Isbn(array(
+ 'type' => 'isbn10',
+ ));
+
+ $this->validator->validate($isbn, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidIsbn10
+ */
+ public function testInvalidIsbn10($isbn, $code)
+ {
+ $constraint = new Isbn(array(
+ 'type' => 'isbn10',
+ 'isbn10Message' => 'myMessage',
+ ));
+
+ $this->validator->validate($isbn, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$isbn.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getValidIsbn13
+ */
+ public function testValidIsbn13($isbn)
+ {
+ $constraint = new Isbn(array('type' => 'isbn13'));
+
+ $this->validator->validate($isbn, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidIsbn13
+ */
+ public function testInvalidIsbn13($isbn, $code)
+ {
+ $constraint = new Isbn(array(
+ 'type' => 'isbn13',
+ 'isbn13Message' => 'myMessage',
+ ));
+
+ $this->validator->validate($isbn, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$isbn.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getValidIsbn
+ */
+ public function testValidIsbnAny($isbn)
+ {
+ $constraint = new Isbn();
+
+ $this->validator->validate($isbn, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidIsbn10
+ */
+ public function testInvalidIsbnAnyIsbn10($isbn, $code)
+ {
+ $constraint = new Isbn(array(
+ 'bothIsbnMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($isbn, $constraint);
+
+ // Too long for an ISBN-10, but not long enough for an ISBN-13
+ if (Isbn::TOO_LONG_ERROR === $code) {
+ $code = Isbn::TYPE_NOT_RECOGNIZED_ERROR;
+ }
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$isbn.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getInvalidIsbn13
+ */
+ public function testInvalidIsbnAnyIsbn13($isbn, $code)
+ {
+ $constraint = new Isbn(array(
+ 'bothIsbnMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($isbn, $constraint);
+
+ // Too short for an ISBN-13, but not short enough for an ISBN-10
+ if (Isbn::TOO_SHORT_ERROR === $code) {
+ $code = Isbn::TYPE_NOT_RECOGNIZED_ERROR;
+ }
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$isbn.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/IssnValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IssnValidatorTest.php
new file mode 100644
index 0000000..a6d3994
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/IssnValidatorTest.php
@@ -0,0 +1,187 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Issn;
+use Symfony\Component\Validator\Constraints\IssnValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @see https://en.wikipedia.org/wiki/Issn
+ */
+class IssnValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new IssnValidator();
+ }
+
+ public function getValidLowerCasedIssn()
+ {
+ return array(
+ array('2162-321x'),
+ array('2160-200x'),
+ array('1537-453x'),
+ array('1937-710x'),
+ array('0002-922x'),
+ array('1553-345x'),
+ array('1553-619x'),
+ );
+ }
+
+ public function getValidNonHyphenatedIssn()
+ {
+ return array(
+ array('2162321X'),
+ array('01896016'),
+ array('15744647'),
+ array('14350645'),
+ array('07174055'),
+ array('20905076'),
+ array('14401592'),
+ );
+ }
+
+ public function getFullValidIssn()
+ {
+ return array(
+ array('1550-7416'),
+ array('1539-8560'),
+ array('2156-5376'),
+ array('1119-023X'),
+ array('1684-5315'),
+ array('1996-0786'),
+ array('1684-5374'),
+ array('1996-0794'),
+ );
+ }
+
+ public function getValidIssn()
+ {
+ return array_merge(
+ $this->getValidLowerCasedIssn(),
+ $this->getValidNonHyphenatedIssn(),
+ $this->getFullValidIssn()
+ );
+ }
+
+ public function getInvalidIssn()
+ {
+ return array(
+ array(0, Issn::TOO_SHORT_ERROR),
+ array('1539', Issn::TOO_SHORT_ERROR),
+ array('2156-537A', Issn::INVALID_CHARACTERS_ERROR),
+ array('1119-0231', Issn::CHECKSUM_FAILED_ERROR),
+ array('1684-5312', Issn::CHECKSUM_FAILED_ERROR),
+ array('1996-0783', Issn::CHECKSUM_FAILED_ERROR),
+ array('1684-537X', Issn::CHECKSUM_FAILED_ERROR),
+ array('1996-0795', Issn::CHECKSUM_FAILED_ERROR),
+ );
+ }
+
+ public function testNullIsValid()
+ {
+ $constraint = new Issn();
+
+ $this->validator->validate(null, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $constraint = new Issn();
+
+ $this->validator->validate('', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $constraint = new Issn();
+ $this->validator->validate(new \stdClass(), $constraint);
+ }
+
+ /**
+ * @dataProvider getValidLowerCasedIssn
+ */
+ public function testCaseSensitiveIssns($issn)
+ {
+ $constraint = new Issn(array(
+ 'caseSensitive' => true,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($issn, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$issn.'"')
+ ->setCode(Issn::INVALID_CASE_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getValidNonHyphenatedIssn
+ */
+ public function testRequireHyphenIssns($issn)
+ {
+ $constraint = new Issn(array(
+ 'requireHyphen' => true,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($issn, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$issn.'"')
+ ->setCode(Issn::MISSING_HYPHEN_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getValidIssn
+ */
+ public function testValidIssn($issn)
+ {
+ $constraint = new Issn();
+
+ $this->validator->validate($issn, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getInvalidIssn
+ */
+ public function testInvalidIssn($issn, $code)
+ {
+ $constraint = new Issn(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($issn, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$issn.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/LanguageValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LanguageValidatorTest.php
new file mode 100644
index 0000000..d9bd4d0
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LanguageValidatorTest.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Intl\Util\IntlTestHelper;
+use Symfony\Component\Validator\Constraints\Language;
+use Symfony\Component\Validator\Constraints\LanguageValidator;
+use Symfony\Component\Validator\Validation;
+
+class LanguageValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new LanguageValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Language());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Language());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Language());
+ }
+
+ /**
+ * @dataProvider getValidLanguages
+ */
+ public function testValidLanguages($language)
+ {
+ $this->validator->validate($language, new Language());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidLanguages()
+ {
+ return array(
+ array('en'),
+ array('en_US'),
+ array('my'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidLanguages
+ */
+ public function testInvalidLanguages($language)
+ {
+ $constraint = new Language(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($language, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$language.'"')
+ ->setCode(Language::NO_SUCH_LANGUAGE_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidLanguages()
+ {
+ return array(
+ array('EN'),
+ array('foobar'),
+ );
+ }
+
+ public function testValidateUsingCountrySpecificLocale()
+ {
+ IntlTestHelper::requireFullIntl($this, false);
+
+ \Locale::setDefault('fr_FR');
+ $existingLanguage = 'en';
+
+ $this->validator->validate($existingLanguage, new Language(array(
+ 'message' => 'aMessage',
+ )));
+
+ $this->assertNoViolation();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/LengthValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LengthValidatorTest.php
new file mode 100644
index 0000000..cd50181
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LengthValidatorTest.php
@@ -0,0 +1,252 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Validator\Constraints\LengthValidator;
+use Symfony\Component\Validator\Validation;
+
+class LengthValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new LengthValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Length(6));
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Length(6));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Length(5));
+ }
+
+ public function getThreeOrLessCharacters()
+ {
+ return array(
+ array(12),
+ array('12'),
+ array('üü'),
+ array('éé'),
+ array(123),
+ array('123'),
+ array('üüü'),
+ array('ééé'),
+ );
+ }
+
+ public function getFourCharacters()
+ {
+ return array(
+ array(1234),
+ array('1234'),
+ array('üüüü'),
+ array('éééé'),
+ );
+ }
+
+ public function getFiveOrMoreCharacters()
+ {
+ return array(
+ array(12345),
+ array('12345'),
+ array('üüüüü'),
+ array('ééééé'),
+ array(123456),
+ array('123456'),
+ array('üüüüüü'),
+ array('éééééé'),
+ );
+ }
+
+ public function getOneCharset()
+ {
+ return array(
+ array('é', 'utf8', true),
+ array("\xE9", 'CP1252', true),
+ array("\xE9", 'XXX', false),
+ array("\xE9", 'utf8', false),
+ );
+ }
+
+ /**
+ * @dataProvider getFiveOrMoreCharacters
+ */
+ public function testValidValuesMin($value)
+ {
+ $constraint = new Length(array('min' => 5));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getThreeOrLessCharacters
+ */
+ public function testValidValuesMax($value)
+ {
+ $constraint = new Length(array('max' => 3));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getFourCharacters
+ */
+ public function testValidValuesExact($value)
+ {
+ $constraint = new Length(4);
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getThreeOrLessCharacters
+ */
+ public function testInvalidValuesMin($value)
+ {
+ $constraint = new Length(array(
+ 'min' => 4,
+ 'minMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$value.'"')
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Length::TOO_SHORT_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getFiveOrMoreCharacters
+ */
+ public function testInvalidValuesMax($value)
+ {
+ $constraint = new Length(array(
+ 'max' => 4,
+ 'maxMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$value.'"')
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Length::TOO_LONG_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getThreeOrLessCharacters
+ */
+ public function testInvalidValuesExactLessThanFour($value)
+ {
+ $constraint = new Length(array(
+ 'min' => 4,
+ 'max' => 4,
+ 'exactMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$value.'"')
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Length::TOO_SHORT_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getFiveOrMoreCharacters
+ */
+ public function testInvalidValuesExactMoreThanFour($value)
+ {
+ $constraint = new Length(array(
+ 'min' => 4,
+ 'max' => 4,
+ 'exactMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$value.'"')
+ ->setParameter('{{ limit }}', 4)
+ ->setInvalidValue($value)
+ ->setPlural(4)
+ ->setCode(Length::TOO_LONG_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getOneCharset
+ */
+ public function testOneCharset($value, $charset, $isValid)
+ {
+ $constraint = new Length(array(
+ 'min' => 1,
+ 'max' => 1,
+ 'charset' => $charset,
+ 'charsetMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ if ($isValid) {
+ $this->assertNoViolation();
+ } else {
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$value.'"')
+ ->setParameter('{{ charset }}', $charset)
+ ->setInvalidValue($value)
+ ->setCode(Length::INVALID_CHARACTERS_ERROR)
+ ->assertRaised();
+ }
+ }
+
+ public function testConstraintGetDefaultOption()
+ {
+ $constraint = new Length(5);
+
+ $this->assertEquals(5, $constraint->min);
+ $this->assertEquals(5, $constraint->max);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanOrEqualValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanOrEqualValidatorTest.php
new file mode 100644
index 0000000..84f150b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanOrEqualValidatorTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\LessThanOrEqual;
+use Symfony\Component\Validator\Constraints\LessThanOrEqualValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class LessThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new LessThanOrEqualValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new LessThanOrEqual($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return LessThanOrEqual::TOO_HIGH_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(1, 2),
+ array(1, 1),
+ array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
+ array(new \DateTime('2000-01-01'), new \DateTime('2020-01-01')),
+ array(new \DateTime('2000-01-01'), '2000-01-01'),
+ array(new \DateTime('2000-01-01'), '2020-01-01'),
+ array(new \DateTime('2000-01-01 UTC'), '2000-01-01 UTC'),
+ array(new \DateTime('2000-01-01 UTC'), '2020-01-01 UTC'),
+ array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)),
+ array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)),
+ array('a', 'a'),
+ array('a', 'z'),
+ array(null, 1),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(2, '2', 1, '1', 'integer'),
+ array(new \DateTime('2010-01-01'), 'Jan 1, 2010, 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2010-01-01'), 'Jan 1, 2010, 12:00 AM', '2000-01-01', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2010-01-01 UTC'), 'Jan 1, 2010, 12:00 AM', '2000-01-01 UTC', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new ComparisonTest_Class(5), '5', new ComparisonTest_Class(4), '4', __NAMESPACE__.'\ComparisonTest_Class'),
+ array('c', '"c"', 'b', '"b"', 'string'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanValidatorTest.php
new file mode 100644
index 0000000..da2885f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LessThanValidatorTest.php
@@ -0,0 +1,78 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\LessThan;
+use Symfony\Component\Validator\Constraints\LessThanValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class LessThanValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new LessThanValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new LessThan($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return LessThan::TOO_HIGH_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(1, 2),
+ array(new \DateTime('2000-01-01'), new \DateTime('2010-01-01')),
+ array(new \DateTime('2000-01-01'), '2010-01-01'),
+ array(new \DateTime('2000-01-01 UTC'), '2010-01-01 UTC'),
+ array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)),
+ array('22', '333'),
+ array(null, 1),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(3, '3', 2, '2', 'integer'),
+ array(2, '2', 2, '2', 'integer'),
+ array(new \DateTime('2010-01-01'), 'Jan 1, 2010, 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2010-01-01'), 'Jan 1, 2010, 12:00 AM', '2000-01-01', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', '2000-01-01', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2010-01-01 UTC'), 'Jan 1, 2010, 12:00 AM', '2000-01-01 UTC', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000-01-01 UTC'), 'Jan 1, 2000, 12:00 AM', '2000-01-01 UTC', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new ComparisonTest_Class(5), '5', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ array(new ComparisonTest_Class(6), '6', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ array('333', '"333"', '22', '"22"', 'string'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/LocaleValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LocaleValidatorTest.php
new file mode 100644
index 0000000..c028596
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LocaleValidatorTest.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Locale;
+use Symfony\Component\Validator\Constraints\LocaleValidator;
+use Symfony\Component\Validator\Validation;
+
+class LocaleValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new LocaleValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Locale());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Locale());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Locale());
+ }
+
+ /**
+ * @dataProvider getValidLocales
+ */
+ public function testValidLocales($locale)
+ {
+ $this->validator->validate($locale, new Locale());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidLocales()
+ {
+ return array(
+ array('en'),
+ array('en_US'),
+ array('pt'),
+ array('pt_PT'),
+ array('zh_Hans'),
+ array('fil_PH'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidLocales
+ */
+ public function testInvalidLocales($locale)
+ {
+ $constraint = new Locale(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($locale, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$locale.'"')
+ ->setCode(Locale::NO_SUCH_LOCALE_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidLocales()
+ {
+ return array(
+ array('EN'),
+ array('foobar'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/LuhnValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LuhnValidatorTest.php
new file mode 100644
index 0000000..b0e88c3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/LuhnValidatorTest.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Luhn;
+use Symfony\Component\Validator\Constraints\LuhnValidator;
+use Symfony\Component\Validator\Validation;
+
+class LuhnValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new LuhnValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Luhn());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Luhn());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getValidNumbers
+ */
+ public function testValidNumbers($number)
+ {
+ $this->validator->validate($number, new Luhn());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidNumbers()
+ {
+ return array(
+ array('42424242424242424242'),
+ array('378282246310005'),
+ array('371449635398431'),
+ array('378734493671000'),
+ array('5610591081018250'),
+ array('30569309025904'),
+ array('38520000023237'),
+ array('6011111111111117'),
+ array('6011000990139424'),
+ array('3530111333300000'),
+ array('3566002020360505'),
+ array('5555555555554444'),
+ array('5105105105105100'),
+ array('4111111111111111'),
+ array('4012888888881881'),
+ array('4222222222222'),
+ array('5019717010103742'),
+ array('6331101999990016'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidNumbers
+ */
+ public function testInvalidNumbers($number, $code)
+ {
+ $constraint = new Luhn(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($number, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$number.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidNumbers()
+ {
+ return array(
+ array('1234567812345678', Luhn::CHECKSUM_FAILED_ERROR),
+ array('4222222222222222', Luhn::CHECKSUM_FAILED_ERROR),
+ array('0000000000000000', Luhn::CHECKSUM_FAILED_ERROR),
+ array('000000!000000000', Luhn::INVALID_CHARACTERS_ERROR),
+ array('42-22222222222222', Luhn::INVALID_CHARACTERS_ERROR),
+ );
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ * @dataProvider getInvalidTypes
+ */
+ public function testInvalidTypes($number)
+ {
+ $constraint = new Luhn();
+
+ $this->validator->validate($number, $constraint);
+ }
+
+ public function getInvalidTypes()
+ {
+ return array(
+ array(0),
+ array(123),
+ array(42424242424242424242),
+ array(378282246310005),
+ array(371449635398431),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotBlankValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotBlankValidatorTest.php
new file mode 100644
index 0000000..c7c081a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotBlankValidatorTest.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\NotBlank;
+use Symfony\Component\Validator\Constraints\NotBlankValidator;
+use Symfony\Component\Validator\Validation;
+
+class NotBlankValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new NotBlankValidator();
+ }
+
+ /**
+ * @dataProvider getValidValues
+ */
+ public function testValidValues($value)
+ {
+ $this->validator->validate($value, new NotBlank());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidValues()
+ {
+ return array(
+ array('foobar'),
+ array(0),
+ array(0.0),
+ array('0'),
+ array(1234),
+ );
+ }
+
+ public function testNullIsInvalid()
+ {
+ $constraint = new NotBlank(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(null, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'null')
+ ->setCode(NotBlank::IS_BLANK_ERROR)
+ ->assertRaised();
+ }
+
+ public function testBlankIsInvalid()
+ {
+ $constraint = new NotBlank(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate('', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '""')
+ ->setCode(NotBlank::IS_BLANK_ERROR)
+ ->assertRaised();
+ }
+
+ public function testFalseIsInvalid()
+ {
+ $constraint = new NotBlank(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(false, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'false')
+ ->setCode(NotBlank::IS_BLANK_ERROR)
+ ->assertRaised();
+ }
+
+ public function testEmptyArrayIsInvalid()
+ {
+ $constraint = new NotBlank(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(array(), $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'array')
+ ->setCode(NotBlank::IS_BLANK_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotEqualToValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotEqualToValidatorTest.php
new file mode 100644
index 0000000..a797762
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotEqualToValidatorTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\NotEqualTo;
+use Symfony\Component\Validator\Constraints\NotEqualToValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class NotEqualToValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new NotEqualToValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new NotEqualTo($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return NotEqualTo::IS_EQUAL_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(1, 2),
+ array('22', '333'),
+ array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')),
+ array(new \DateTime('2001-01-01'), '2000-01-01'),
+ array(new \DateTime('2001-01-01 UTC'), '2000-01-01 UTC'),
+ array(new ComparisonTest_Class(6), new ComparisonTest_Class(5)),
+ array(null, 1),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ return array(
+ array(3, '3', 3, '3', 'integer'),
+ array('2', '"2"', 2, '2', 'integer'),
+ array('a', '"a"', 'a', '"a"', 'string'),
+ array(new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000-01-01'), 'Jan 1, 2000, 12:00 AM', '2000-01-01', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new \DateTime('2000-01-01 UTC'), 'Jan 1, 2000, 12:00 AM', '2000-01-01 UTC', 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array(new ComparisonTest_Class(5), '5', new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotIdenticalToValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotIdenticalToValidatorTest.php
new file mode 100644
index 0000000..16f518f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotIdenticalToValidatorTest.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\NotIdenticalTo;
+use Symfony\Component\Validator\Constraints\NotIdenticalToValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Daniel Holmes <daniel@danielholmes.org>
+ */
+class NotIdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new NotIdenticalToValidator();
+ }
+
+ protected function createConstraint(array $options = null)
+ {
+ return new NotIdenticalTo($options);
+ }
+
+ protected function getErrorCode()
+ {
+ return NotIdenticalTo::IS_IDENTICAL_ERROR;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideValidComparisons()
+ {
+ return array(
+ array(1, 2),
+ array('2', 2),
+ array('22', '333'),
+ array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')),
+ array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
+ array(new \DateTime('2001-01-01'), '2000-01-01'),
+ array(new \DateTime('2000-01-01'), '2000-01-01'),
+ array(new \DateTime('2001-01-01'), '2000-01-01'),
+ array(new \DateTime('2000-01-01 UTC'), '2000-01-01 UTC'),
+ array(null, 1),
+ );
+ }
+
+ public function provideAllInvalidComparisons()
+ {
+ $this->setDefaultTimezone('UTC');
+
+ // Don't call addPhp5Dot5Comparisons() automatically, as it does
+ // not take care of identical objects
+ $comparisons = $this->provideInvalidComparisons();
+
+ $this->restoreDefaultTimezone();
+
+ return $comparisons;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideInvalidComparisons()
+ {
+ $date = new \DateTime('2000-01-01');
+ $object = new ComparisonTest_Class(2);
+
+ $comparisons = array(
+ array(3, '3', 3, '3', 'integer'),
+ array('a', '"a"', 'a', '"a"', 'string'),
+ array($date, 'Jan 1, 2000, 12:00 AM', $date, 'Jan 1, 2000, 12:00 AM', 'DateTime'),
+ array($object, '2', $object, '2', __NAMESPACE__.'\ComparisonTest_Class'),
+ );
+
+ return $comparisons;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotNullValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotNullValidatorTest.php
new file mode 100644
index 0000000..a244f63
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/NotNullValidatorTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\NotNullValidator;
+use Symfony\Component\Validator\Validation;
+
+class NotNullValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new NotNullValidator();
+ }
+
+ /**
+ * @dataProvider getValidValues
+ */
+ public function testValidValues($value)
+ {
+ $this->validator->validate($value, new NotNull());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidValues()
+ {
+ return array(
+ array(0),
+ array(false),
+ array(true),
+ array(''),
+ );
+ }
+
+ public function testNullIsInvalid()
+ {
+ $constraint = new NotNull(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate(null, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', 'null')
+ ->setCode(NotNull::IS_NULL_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/RangeValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/RangeValidatorTest.php
new file mode 100644
index 0000000..1093fa4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/RangeValidatorTest.php
@@ -0,0 +1,403 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Intl\Util\IntlTestHelper;
+use Symfony\Component\Validator\Constraints\Range;
+use Symfony\Component\Validator\Constraints\RangeValidator;
+use Symfony\Component\Validator\Validation;
+
+class RangeValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new RangeValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Range(array('min' => 10, 'max' => 20)));
+
+ $this->assertNoViolation();
+ }
+
+ public function getTenToTwenty()
+ {
+ return array(
+ array(10.00001),
+ array(19.99999),
+ array('10.00001'),
+ array('19.99999'),
+ array(10),
+ array(20),
+ array(10.0),
+ array(20.0),
+ );
+ }
+
+ public function getLessThanTen()
+ {
+ return array(
+ array(9.99999, '9.99999'),
+ array('9.99999', '"9.99999"'),
+ array(5, '5'),
+ array(1.0, '1.0'),
+ );
+ }
+
+ public function getMoreThanTwenty()
+ {
+ return array(
+ array(20.000001, '20.000001'),
+ array('20.000001', '"20.000001"'),
+ array(21, '21'),
+ array(30.0, '30.0'),
+ );
+ }
+
+ /**
+ * @dataProvider getTenToTwenty
+ */
+ public function testValidValuesMin($value)
+ {
+ $constraint = new Range(array('min' => 10));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getTenToTwenty
+ */
+ public function testValidValuesMax($value)
+ {
+ $constraint = new Range(array('max' => 20));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getTenToTwenty
+ */
+ public function testValidValuesMinMax($value)
+ {
+ $constraint = new Range(array('min' => 10, 'max' => 20));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getLessThanTen
+ */
+ public function testInvalidValuesMin($value, $formattedValue)
+ {
+ $constraint = new Range(array(
+ 'min' => 10,
+ 'minMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $formattedValue)
+ ->setParameter('{{ limit }}', 10)
+ ->setCode(Range::TOO_LOW_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getMoreThanTwenty
+ */
+ public function testInvalidValuesMax($value, $formattedValue)
+ {
+ $constraint = new Range(array(
+ 'max' => 20,
+ 'maxMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $formattedValue)
+ ->setParameter('{{ limit }}', 20)
+ ->setCode(Range::TOO_HIGH_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getMoreThanTwenty
+ */
+ public function testInvalidValuesCombinedMax($value, $formattedValue)
+ {
+ $constraint = new Range(array(
+ 'min' => 10,
+ 'max' => 20,
+ 'minMessage' => 'myMinMessage',
+ 'maxMessage' => 'myMaxMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMaxMessage')
+ ->setParameter('{{ value }}', $formattedValue)
+ ->setParameter('{{ limit }}', 20)
+ ->setCode(Range::TOO_HIGH_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getLessThanTen
+ */
+ public function testInvalidValuesCombinedMin($value, $formattedValue)
+ {
+ $constraint = new Range(array(
+ 'min' => 10,
+ 'max' => 20,
+ 'minMessage' => 'myMinMessage',
+ 'maxMessage' => 'myMaxMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMinMessage')
+ ->setParameter('{{ value }}', $formattedValue)
+ ->setParameter('{{ limit }}', 10)
+ ->setCode(Range::TOO_LOW_ERROR)
+ ->assertRaised();
+ }
+
+ public function getTenthToTwentiethMarch2014()
+ {
+ // The provider runs before setUp(), so we need to manually fix
+ // the default timezone
+ $this->setDefaultTimezone('UTC');
+
+ $tests = array(
+ array(new \DateTime('March 10, 2014')),
+ array(new \DateTime('March 15, 2014')),
+ array(new \DateTime('March 20, 2014')),
+ );
+
+ if (\PHP_VERSION_ID >= 50500) {
+ $tests[] = array(new \DateTimeImmutable('March 10, 2014'));
+ $tests[] = array(new \DateTimeImmutable('March 15, 2014'));
+ $tests[] = array(new \DateTimeImmutable('March 20, 2014'));
+ }
+
+ $this->restoreDefaultTimezone();
+
+ return $tests;
+ }
+
+ public function getSoonerThanTenthMarch2014()
+ {
+ // The provider runs before setUp(), so we need to manually fix
+ // the default timezone
+ $this->setDefaultTimezone('UTC');
+
+ $tests = array(
+ array(new \DateTime('March 20, 2013'), 'Mar 20, 2013, 12:00 AM'),
+ array(new \DateTime('March 9, 2014'), 'Mar 9, 2014, 12:00 AM'),
+ );
+
+ if (\PHP_VERSION_ID >= 50500) {
+ $tests[] = array(new \DateTimeImmutable('March 20, 2013'), 'Mar 20, 2013, 12:00 AM');
+ $tests[] = array(new \DateTimeImmutable('March 9, 2014'), 'Mar 9, 2014, 12:00 AM');
+ }
+
+ $this->restoreDefaultTimezone();
+
+ return $tests;
+ }
+
+ public function getLaterThanTwentiethMarch2014()
+ {
+ // The provider runs before setUp(), so we need to manually fix
+ // the default timezone
+ $this->setDefaultTimezone('UTC');
+
+ $tests = array(
+ array(new \DateTime('March 21, 2014'), 'Mar 21, 2014, 12:00 AM'),
+ array(new \DateTime('March 9, 2015'), 'Mar 9, 2015, 12:00 AM'),
+ );
+
+ if (\PHP_VERSION_ID >= 50500) {
+ $tests[] = array(new \DateTimeImmutable('March 21, 2014'), 'Mar 21, 2014, 12:00 AM');
+ $tests[] = array(new \DateTimeImmutable('March 9, 2015'), 'Mar 9, 2015, 12:00 AM');
+ }
+
+ $this->restoreDefaultTimezone();
+
+ return $tests;
+ }
+
+ /**
+ * @dataProvider getTenthToTwentiethMarch2014
+ */
+ public function testValidDatesMin($value)
+ {
+ $constraint = new Range(array('min' => 'March 10, 2014'));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getTenthToTwentiethMarch2014
+ */
+ public function testValidDatesMax($value)
+ {
+ $constraint = new Range(array('max' => 'March 20, 2014'));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getTenthToTwentiethMarch2014
+ */
+ public function testValidDatesMinMax($value)
+ {
+ $constraint = new Range(array('min' => 'March 10, 2014', 'max' => 'March 20, 2014'));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @dataProvider getSoonerThanTenthMarch2014
+ */
+ public function testInvalidDatesMin($value, $dateTimeAsString)
+ {
+ // Conversion of dates to string differs between ICU versions
+ // Make sure we have the correct version loaded
+ IntlTestHelper::requireIntl($this, '57.1');
+
+ $constraint = new Range(array(
+ 'min' => 'March 10, 2014',
+ 'minMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $dateTimeAsString)
+ ->setParameter('{{ limit }}', 'Mar 10, 2014, 12:00 AM')
+ ->setCode(Range::TOO_LOW_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getLaterThanTwentiethMarch2014
+ */
+ public function testInvalidDatesMax($value, $dateTimeAsString)
+ {
+ // Conversion of dates to string differs between ICU versions
+ // Make sure we have the correct version loaded
+ IntlTestHelper::requireIntl($this, '57.1');
+
+ $constraint = new Range(array(
+ 'max' => 'March 20, 2014',
+ 'maxMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $dateTimeAsString)
+ ->setParameter('{{ limit }}', 'Mar 20, 2014, 12:00 AM')
+ ->setCode(Range::TOO_HIGH_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getLaterThanTwentiethMarch2014
+ */
+ public function testInvalidDatesCombinedMax($value, $dateTimeAsString)
+ {
+ // Conversion of dates to string differs between ICU versions
+ // Make sure we have the correct version loaded
+ IntlTestHelper::requireIntl($this, '57.1');
+
+ $constraint = new Range(array(
+ 'min' => 'March 10, 2014',
+ 'max' => 'March 20, 2014',
+ 'minMessage' => 'myMinMessage',
+ 'maxMessage' => 'myMaxMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMaxMessage')
+ ->setParameter('{{ value }}', $dateTimeAsString)
+ ->setParameter('{{ limit }}', 'Mar 20, 2014, 12:00 AM')
+ ->setCode(Range::TOO_HIGH_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getSoonerThanTenthMarch2014
+ */
+ public function testInvalidDatesCombinedMin($value, $dateTimeAsString)
+ {
+ // Conversion of dates to string differs between ICU versions
+ // Make sure we have the correct version loaded
+ IntlTestHelper::requireIntl($this, '57.1');
+
+ $constraint = new Range(array(
+ 'min' => 'March 10, 2014',
+ 'max' => 'March 20, 2014',
+ 'minMessage' => 'myMinMessage',
+ 'maxMessage' => 'myMaxMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMinMessage')
+ ->setParameter('{{ value }}', $dateTimeAsString)
+ ->setParameter('{{ limit }}', 'Mar 10, 2014, 12:00 AM')
+ ->setCode(Range::TOO_LOW_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidValues()
+ {
+ return array(
+ array(9.999999),
+ array(20.000001),
+ array('9.999999'),
+ array('20.000001'),
+ array(new \stdClass()),
+ );
+ }
+
+ public function testNonNumeric()
+ {
+ $this->validator->validate('abcd', new Range(array(
+ 'min' => 10,
+ 'max' => 20,
+ 'invalidMessage' => 'myMessage',
+ )));
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"abcd"')
+ ->setCode(Range::INVALID_CHARACTERS_ERROR)
+ ->assertRaised();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexTest.php
new file mode 100644
index 0000000..26ef1b2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexTest.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Regex;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class RegexTest extends TestCase
+{
+ public function testConstraintGetDefaultOption()
+ {
+ $constraint = new Regex('/^[0-9]+$/');
+
+ $this->assertSame('/^[0-9]+$/', $constraint->pattern);
+ }
+
+ public function provideHtmlPatterns()
+ {
+ return array(
+ // HTML5 wraps the pattern in ^(?:pattern)$
+ array('/^[0-9]+$/', '[0-9]+'),
+ array('/[0-9]+$/', '.*[0-9]+'),
+ array('/^[0-9]+/', '[0-9]+.*'),
+ array('/[0-9]+/', '.*[0-9]+.*'),
+ // We need a smart way to allow matching of patterns that contain
+ // ^ and $ at various sub-clauses of an or-clause
+ // .*(pattern).* seems to work correctly
+ array('/[0-9]$|[a-z]+/', '.*([0-9]$|[a-z]+).*'),
+ array('/[0-9]$|^[a-z]+/', '.*([0-9]$|^[a-z]+).*'),
+ array('/^[0-9]|[a-z]+$/', '.*(^[0-9]|[a-z]+$).*'),
+ // Unescape escaped delimiters
+ array('/^[0-9]+\/$/', '[0-9]+/'),
+ array('#^[0-9]+\#$#', '[0-9]+#'),
+ // Cannot be converted
+ array('/^[0-9]+$/i', null),
+
+ // Inverse matches are simple, just wrap in
+ // ((?!pattern).)*
+ array('/^[0-9]+$/', '((?!^[0-9]+$).)*', false),
+ array('/[0-9]+$/', '((?![0-9]+$).)*', false),
+ array('/^[0-9]+/', '((?!^[0-9]+).)*', false),
+ array('/[0-9]+/', '((?![0-9]+).)*', false),
+ array('/[0-9]$|[a-z]+/', '((?![0-9]$|[a-z]+).)*', false),
+ array('/[0-9]$|^[a-z]+/', '((?![0-9]$|^[a-z]+).)*', false),
+ array('/^[0-9]|[a-z]+$/', '((?!^[0-9]|[a-z]+$).)*', false),
+ array('/^[0-9]+\/$/', '((?!^[0-9]+/$).)*', false),
+ array('#^[0-9]+\#$#', '((?!^[0-9]+#$).)*', false),
+ array('/^[0-9]+$/i', null, false),
+ );
+ }
+
+ /**
+ * @dataProvider provideHtmlPatterns
+ */
+ public function testGetHtmlPattern($pattern, $htmlPattern, $match = true)
+ {
+ $constraint = new Regex(array(
+ 'pattern' => $pattern,
+ 'match' => $match,
+ ));
+
+ $this->assertSame($pattern, $constraint->pattern);
+ $this->assertSame($htmlPattern, $constraint->getHtmlPattern());
+ }
+
+ public function testGetCustomHtmlPattern()
+ {
+ $constraint = new Regex(array(
+ 'pattern' => '((?![0-9]$|[a-z]+).)*',
+ 'htmlPattern' => 'foobar',
+ ));
+
+ $this->assertSame('((?![0-9]$|[a-z]+).)*', $constraint->pattern);
+ $this->assertSame('foobar', $constraint->getHtmlPattern());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexValidatorTest.php
new file mode 100644
index 0000000..88e6996
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/RegexValidatorTest.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Regex;
+use Symfony\Component\Validator\Constraints\RegexValidator;
+use Symfony\Component\Validator\Validation;
+
+class RegexValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new RegexValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Regex(array('pattern' => '/^[0-9]+$/')));
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Regex(array('pattern' => '/^[0-9]+$/')));
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Regex(array('pattern' => '/^[0-9]+$/')));
+ }
+
+ /**
+ * @dataProvider getValidValues
+ */
+ public function testValidValues($value)
+ {
+ $constraint = new Regex(array('pattern' => '/^[0-9]+$/'));
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidValues()
+ {
+ return array(
+ array(0),
+ array('0'),
+ array('090909'),
+ array(90909),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidValues
+ */
+ public function testInvalidValues($value)
+ {
+ $constraint = new Regex(array(
+ 'pattern' => '/^[0-9]+$/',
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$value.'"')
+ ->setCode(Regex::REGEX_FAILED_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidValues()
+ {
+ return array(
+ array('abcd'),
+ array('090foo'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/TimeValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/TimeValidatorTest.php
new file mode 100644
index 0000000..a6ca143
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/TimeValidatorTest.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Time;
+use Symfony\Component\Validator\Constraints\TimeValidator;
+use Symfony\Component\Validator\Validation;
+
+class TimeValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new TimeValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Time());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Time());
+
+ $this->assertNoViolation();
+ }
+
+ public function testDateTimeClassIsValid()
+ {
+ $this->validator->validate(new \DateTime(), new Time());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Time());
+ }
+
+ /**
+ * @dataProvider getValidTimes
+ */
+ public function testValidTimes($time)
+ {
+ $this->validator->validate($time, new Time());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidTimes()
+ {
+ return array(
+ array('01:02:03'),
+ array('00:00:00'),
+ array('23:59:59'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidTimes
+ */
+ public function testInvalidTimes($time, $code)
+ {
+ $constraint = new Time(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($time, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$time.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidTimes()
+ {
+ return array(
+ array('foobar', Time::INVALID_FORMAT_ERROR),
+ array('foobar 12:34:56', Time::INVALID_FORMAT_ERROR),
+ array('12:34:56 foobar', Time::INVALID_FORMAT_ERROR),
+ array('00:00', Time::INVALID_FORMAT_ERROR),
+ array('24:00:00', Time::INVALID_TIME_ERROR),
+ array('00:60:00', Time::INVALID_TIME_ERROR),
+ array('00:00:60', Time::INVALID_TIME_ERROR),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/TypeValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/TypeValidatorTest.php
new file mode 100644
index 0000000..51bd992
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/TypeValidatorTest.php
@@ -0,0 +1,187 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Type;
+use Symfony\Component\Validator\Constraints\TypeValidator;
+use Symfony\Component\Validator\Validation;
+
+class TypeValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected static $file;
+
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new TypeValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $constraint = new Type(array('type' => 'integer'));
+
+ $this->validator->validate(null, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyIsValidIfString()
+ {
+ $constraint = new Type(array('type' => 'string'));
+
+ $this->validator->validate('', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyIsInvalidIfNoString()
+ {
+ $constraint = new Type(array(
+ 'type' => 'integer',
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate('', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '""')
+ ->setParameter('{{ type }}', 'integer')
+ ->setCode(Type::INVALID_TYPE_ERROR)
+ ->assertRaised();
+ }
+
+ /**
+ * @dataProvider getValidValues
+ */
+ public function testValidValues($value, $type)
+ {
+ $constraint = new Type(array('type' => $type));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidValues()
+ {
+ $object = new \stdClass();
+ $file = $this->createFile();
+
+ return array(
+ array(true, 'Boolean'),
+ array(false, 'Boolean'),
+ array(true, 'boolean'),
+ array(false, 'boolean'),
+ array(true, 'bool'),
+ array(false, 'bool'),
+ array(0, 'numeric'),
+ array('0', 'numeric'),
+ array(1.5, 'numeric'),
+ array('1.5', 'numeric'),
+ array(0, 'integer'),
+ array(1.5, 'float'),
+ array('12345', 'string'),
+ array(array(), 'array'),
+ array($object, 'object'),
+ array($object, 'stdClass'),
+ array($file, 'resource'),
+ array('12345', 'digit'),
+ array('12a34', 'alnum'),
+ array('abcde', 'alpha'),
+ array("\n\r\t", 'cntrl'),
+ array('arf12', 'graph'),
+ array('abcde', 'lower'),
+ array('ABCDE', 'upper'),
+ array('arf12', 'print'),
+ array('*&$()', 'punct'),
+ array("\n\r\t", 'space'),
+ array('AB10BC99', 'xdigit'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidValues
+ */
+ public function testInvalidValues($value, $type, $valueAsString)
+ {
+ $constraint = new Type(array(
+ 'type' => $type,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($value, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', $valueAsString)
+ ->setParameter('{{ type }}', $type)
+ ->setCode(Type::INVALID_TYPE_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidValues()
+ {
+ $object = new \stdClass();
+ $file = $this->createFile();
+
+ return array(
+ array('foobar', 'numeric', '"foobar"'),
+ array('foobar', 'boolean', '"foobar"'),
+ array('0', 'integer', '"0"'),
+ array('1.5', 'float', '"1.5"'),
+ array(12345, 'string', '12345'),
+ array($object, 'boolean', 'object'),
+ array($object, 'numeric', 'object'),
+ array($object, 'integer', 'object'),
+ array($object, 'float', 'object'),
+ array($object, 'string', 'object'),
+ array($object, 'resource', 'object'),
+ array($file, 'boolean', 'resource'),
+ array($file, 'numeric', 'resource'),
+ array($file, 'integer', 'resource'),
+ array($file, 'float', 'resource'),
+ array($file, 'string', 'resource'),
+ array($file, 'object', 'resource'),
+ array('12a34', 'digit', '"12a34"'),
+ array('1a#23', 'alnum', '"1a#23"'),
+ array('abcd1', 'alpha', '"abcd1"'),
+ array("\nabc", 'cntrl', "\"\nabc\""),
+ array("abc\n", 'graph', "\"abc\n\""),
+ array('abCDE', 'lower', '"abCDE"'),
+ array('ABcde', 'upper', '"ABcde"'),
+ array("\nabc", 'print', "\"\nabc\""),
+ array('abc&$!', 'punct', '"abc&$!"'),
+ array("\nabc", 'space', "\"\nabc\""),
+ array('AR1012', 'xdigit', '"AR1012"'),
+ );
+ }
+
+ protected function createFile()
+ {
+ if (!static::$file) {
+ static::$file = fopen(__FILE__, 'r');
+ }
+
+ return static::$file;
+ }
+
+ public static function tearDownAfterClass()
+ {
+ if (static::$file) {
+ fclose(static::$file);
+ static::$file = null;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/UrlValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/UrlValidatorTest.php
new file mode 100644
index 0000000..bc3bd02
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/UrlValidatorTest.php
@@ -0,0 +1,242 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Bridge\PhpUnit\DnsMock;
+use Symfony\Component\Validator\Constraints\Url;
+use Symfony\Component\Validator\Constraints\UrlValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @group dns-sensitive
+ */
+class UrlValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new UrlValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Url());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Url());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringFromObjectIsValid()
+ {
+ $this->validator->validate(new EmailProvider(), new Url());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Url());
+ }
+
+ /**
+ * @dataProvider getValidUrls
+ */
+ public function testValidUrls($url)
+ {
+ $this->validator->validate($url, new Url());
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidUrls()
+ {
+ return array(
+ array('http://a.pl'),
+ array('http://www.google.com'),
+ array('http://www.google.com.'),
+ array('http://www.google.museum'),
+ array('https://google.com/'),
+ array('https://google.com:80/'),
+ array('http://www.example.coop/'),
+ array('http://www.test-example.com/'),
+ array('http://www.symfony.com/'),
+ array('http://symfony.fake/blog/'),
+ array('http://symfony.com/?'),
+ array('http://symfony.com/search?type=&q=url+validator'),
+ array('http://symfony.com/#'),
+ array('http://symfony.com/#?'),
+ array('http://www.symfony.com/doc/current/book/validation.html#supported-constraints'),
+ array('http://very.long.domain.name.com/'),
+ array('http://localhost/'),
+ array('http://myhost123/'),
+ array('http://127.0.0.1/'),
+ array('http://127.0.0.1:80/'),
+ array('http://[::1]/'),
+ array('http://[::1]:80/'),
+ array('http://[1:2:3::4:5:6:7]/'),
+ array('http://sãopaulo.com/'),
+ array('http://xn--sopaulo-xwa.com/'),
+ array('http://sãopaulo.com.br/'),
+ array('http://xn--sopaulo-xwa.com.br/'),
+ array('http://пример.испытание/'),
+ array('http://xn--e1afmkfd.xn--80akhbyknj4f/'),
+ array('http://مثال.إختبار/'),
+ array('http://xn--mgbh0fb.xn--kgbechtv/'),
+ array('http://例子.测试/'),
+ array('http://xn--fsqu00a.xn--0zwm56d/'),
+ array('http://例子.測試/'),
+ array('http://xn--fsqu00a.xn--g6w251d/'),
+ array('http://例え.テスト/'),
+ array('http://xn--r8jz45g.xn--zckzah/'),
+ array('http://مثال.آزمایشی/'),
+ array('http://xn--mgbh0fb.xn--hgbk6aj7f53bba/'),
+ array('http://실례.테스트/'),
+ array('http://xn--9n2bp8q.xn--9t4b11yi5a/'),
+ array('http://العربية.idn.icann.org/'),
+ array('http://xn--ogb.idn.icann.org/'),
+ array('http://xn--e1afmkfd.xn--80akhbyknj4f.xn--e1afmkfd/'),
+ array('http://xn--espaa-rta.xn--ca-ol-fsay5a/'),
+ array('http://xn--d1abbgf6aiiy.xn--p1ai/'),
+ array('http://☎.com/'),
+ array('http://username:password@symfony.com'),
+ array('http://user.name:password@symfony.com'),
+ array('http://username:pass.word@symfony.com'),
+ array('http://user.name:pass.word@symfony.com'),
+ array('http://user-name@symfony.com'),
+ array('http://symfony.com?'),
+ array('http://symfony.com?query=1'),
+ array('http://symfony.com/?query=1'),
+ array('http://symfony.com#'),
+ array('http://symfony.com#fragment'),
+ array('http://symfony.com/#fragment'),
+ array('http://symfony.com/#one_more%20test'),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidUrls
+ */
+ public function testInvalidUrls($url)
+ {
+ $constraint = new Url(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($url, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$url.'"')
+ ->setCode(Url::INVALID_URL_ERROR)
+ ->assertRaised();
+ }
+
+ public function getInvalidUrls()
+ {
+ return array(
+ array('google.com'),
+ array('://google.com'),
+ array('http ://google.com'),
+ array('http:/google.com'),
+ array('http://goog_le.com'),
+ array('http://google.com::aa'),
+ array('http://google.com:aa'),
+ array('ftp://google.fr'),
+ array('faked://google.fr'),
+ array('http://127.0.0.1:aa/'),
+ array('ftp://[::1]/'),
+ array('http://[::1'),
+ array('http://hello.☎/'),
+ array('http://:password@symfony.com'),
+ array('http://:password@@symfony.com'),
+ array('http://username:passwordsymfony.com'),
+ array('http://usern@me:password@symfony.com'),
+ array('http://example.com/exploit.html?<script>alert(1);</script>'),
+ array('http://example.com/exploit.html?hel lo'),
+ array('http://example.com/exploit.html?not_a%hex'),
+ array('http://'),
+ );
+ }
+
+ /**
+ * @dataProvider getValidCustomUrls
+ */
+ public function testCustomProtocolIsValid($url)
+ {
+ $constraint = new Url(array(
+ 'protocols' => array('ftp', 'file', 'git'),
+ ));
+
+ $this->validator->validate($url, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidCustomUrls()
+ {
+ return array(
+ array('ftp://google.com'),
+ array('file://127.0.0.1'),
+ array('git://[::1]/'),
+ );
+ }
+
+ /**
+ * @dataProvider getCheckDns
+ * @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
+ */
+ public function testCheckDns($violation)
+ {
+ DnsMock::withMockedHosts(array('example.com' => array(array('type' => $violation ? '' : 'A'))));
+
+ $constraint = new Url(array(
+ 'checkDNS' => true,
+ 'dnsMessage' => 'myMessage',
+ ));
+
+ $this->validator->validate('http://example.com', $constraint);
+
+ if (!$violation) {
+ $this->assertNoViolation();
+ } else {
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"example.com"')
+ ->setCode(Url::INVALID_URL_ERROR)
+ ->assertRaised();
+ }
+ }
+
+ public function getCheckDns()
+ {
+ return array(array(true), array(false));
+ }
+}
+
+class EmailProvider
+{
+ public function __toString()
+ {
+ return '';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/UuidValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/UuidValidatorTest.php
new file mode 100644
index 0000000..05a6068
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/UuidValidatorTest.php
@@ -0,0 +1,221 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use Symfony\Component\Validator\Constraints\Uuid;
+use Symfony\Component\Validator\Constraints\UuidValidator;
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @author Colin O'Dell <colinodell@gmail.com>
+ */
+class UuidValidatorTest extends AbstractConstraintValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5;
+ }
+
+ protected function createValidator()
+ {
+ return new UuidValidator();
+ }
+
+ public function testNullIsValid()
+ {
+ $this->validator->validate(null, new Uuid());
+
+ $this->assertNoViolation();
+ }
+
+ public function testEmptyStringIsValid()
+ {
+ $this->validator->validate('', new Uuid());
+
+ $this->assertNoViolation();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsUuidConstraintCompatibleType()
+ {
+ $constraint = $this->getMockForAbstractClass('Symfony\\Component\\Validator\\Constraint');
+
+ $this->validator->validate('216fff40-98d9-11e3-a5e2-0800200c9a66', $constraint);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
+ */
+ public function testExpectsStringCompatibleType()
+ {
+ $this->validator->validate(new \stdClass(), new Uuid());
+ }
+
+ /**
+ * @dataProvider getValidStrictUuids
+ */
+ public function testValidStrictUuids($uuid, $versions = null)
+ {
+ $constraint = new Uuid();
+
+ if (null !== $versions) {
+ $constraint->versions = $versions;
+ }
+
+ $this->validator->validate($uuid, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidStrictUuids()
+ {
+ return array(
+ array('216fff40-98d9-11e3-a5e2-0800200c9a66'), // Version 1 UUID in lowercase
+ array('216fff40-98d9-11e3-a5e2-0800200c9a66', array(Uuid::V1_MAC)),
+ array('216FFF40-98D9-11E3-A5E2-0800200C9A66'), // Version 1 UUID in UPPERCASE
+ array('456daefb-5aa6-41b5-8dbc-068b05a8b201'), // Version 4 UUID in lowercase
+ array('456daEFb-5AA6-41B5-8DBC-068B05A8B201'), // Version 4 UUID in mixed case
+ array('456daEFb-5AA6-41B5-8DBC-068B05A8B201', array(Uuid::V4_RANDOM)),
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidStrictUuids
+ */
+ public function testInvalidStrictUuids($uuid, $code, $versions = null)
+ {
+ $constraint = new Uuid(array(
+ 'message' => 'testMessage',
+ ));
+
+ if (null !== $versions) {
+ $constraint->versions = $versions;
+ }
+
+ $this->validator->validate($uuid, $constraint);
+
+ $this->buildViolation('testMessage')
+ ->setParameter('{{ value }}', '"'.$uuid.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidStrictUuids()
+ {
+ return array(
+ array('216fff40-98d9-11e3-a5e2_0800200c9a66', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216gff40-98d9-11e3-a5e2-0800200c9a66', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216Gff40-98d9-11e3-a5e2-0800200c9a66', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216fff40-98d9-11e3-a5e-20800200c9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216f-ff40-98d9-11e3-a5e2-0800200c9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800-200c9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800200c-9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216fff40-98d9-11e3-a5e20800200c9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216fff4098d911e3a5e20800200c9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800200c9a6', Uuid::TOO_SHORT_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800200c9a666', Uuid::TOO_LONG_ERROR),
+ array('216fff40-98d9-01e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-61e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-71e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-81e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-91e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-a1e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-b1e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-c1e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-d1e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-e1e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-f1e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR, array(Uuid::V2_DCE, Uuid::V3_MD5, Uuid::V4_RANDOM, Uuid::V5_SHA1)),
+ array('216fff40-98d9-21e3-a5e2-0800200c9a66', Uuid::INVALID_VERSION_ERROR, array(Uuid::V1_MAC, Uuid::V3_MD5, Uuid::V4_RANDOM, Uuid::V5_SHA1)),
+ array('216fff40-98d9-11e3-05e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-15e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-25e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-35e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-45e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-55e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-65e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-75e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-c5e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-d5e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-e5e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+ array('216fff40-98d9-11e3-f5e2-0800200c9a66', Uuid::INVALID_VARIANT_ERROR),
+
+ // Non-standard UUID allowed by some other systems
+ array('{216fff40-98d9-11e3-a5e2-0800200c9a66}', Uuid::INVALID_CHARACTERS_ERROR),
+ array('[216fff40-98d9-11e3-a5e2-0800200c9a66]', Uuid::INVALID_CHARACTERS_ERROR),
+ );
+ }
+
+ /**
+ * @dataProvider getValidNonStrictUuids
+ */
+ public function testValidNonStrictUuids($uuid)
+ {
+ $constraint = new Uuid(array(
+ 'strict' => false,
+ ));
+
+ $this->validator->validate($uuid, $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function getValidNonStrictUuids()
+ {
+ return array(
+ array('216fff40-98d9-11e3-a5e2-0800200c9a66'), // Version 1 UUID in lowercase
+ array('216FFF40-98D9-11E3-A5E2-0800200C9A66'), // Version 1 UUID in UPPERCASE
+ array('456daefb-5aa6-41b5-8dbc-068b05a8b201'), // Version 4 UUID in lowercase
+ array('456DAEFb-5AA6-41B5-8DBC-068b05a8B201'), // Version 4 UUID in mixed case
+
+ // Non-standard UUIDs allowed by some other systems
+ array('216f-ff40-98d9-11e3-a5e2-0800-200c-9a66'), // Non-standard dash positions (every 4 chars)
+ array('216fff40-98d911e3-a5e20800-200c9a66'), // Non-standard dash positions (every 8 chars)
+ array('216fff4098d911e3a5e20800200c9a66'), // No dashes at all
+ array('{216fff40-98d9-11e3-a5e2-0800200c9a66}'), // Wrapped with curly braces
+ array('[216fff40-98d9-11e3-a5e2-0800200c9a66]'), // Wrapped with squared braces
+ );
+ }
+
+ /**
+ * @dataProvider getInvalidNonStrictUuids
+ */
+ public function testInvalidNonStrictUuids($uuid, $code)
+ {
+ $constraint = new Uuid(array(
+ 'strict' => false,
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($uuid, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->setParameter('{{ value }}', '"'.$uuid.'"')
+ ->setCode($code)
+ ->assertRaised();
+ }
+
+ public function getInvalidNonStrictUuids()
+ {
+ return array(
+ array('216fff40-98d9-11e3-a5e2_0800200c9a66', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216gff40-98d9-11e3-a5e2-0800200c9a66', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216Gff40-98d9-11e3-a5e2-0800200c9a66', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216fff40-98d9-11e3-a5e2_0800200c9a6', Uuid::INVALID_CHARACTERS_ERROR),
+ array('216fff40-98d9-11e3-a5e-20800200c9a66', Uuid::INVALID_HYPHEN_PLACEMENT_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800200c9a6', Uuid::TOO_SHORT_ERROR),
+ array('216fff40-98d9-11e3-a5e2-0800200c9a666', Uuid::TOO_LONG_ERROR),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Constraints/ValidTest.php b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ValidTest.php
new file mode 100644
index 0000000..83722fd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Constraints/ValidTest.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Constraints;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Valid;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ValidTest extends TestCase
+{
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testRejectGroupsOption()
+ {
+ new Valid(array('groups' => 'foo'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/CallbackClass.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/CallbackClass.php
new file mode 100644
index 0000000..0f6a2f4
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/CallbackClass.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\ExecutionContextInterface;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CallbackClass
+{
+ public static function callback($object, ExecutionContextInterface $context)
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ClassConstraint.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ClassConstraint.php
new file mode 100644
index 0000000..a4dc777
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ClassConstraint.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+class ClassConstraint extends Constraint
+{
+ public function getTargets()
+ {
+ return self::CLASS_CONSTRAINT;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintA.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintA.php
new file mode 100644
index 0000000..8a196dc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintA.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+/** @Annotation */
+class ConstraintA extends Constraint
+{
+ public $property1;
+ public $property2;
+
+ public function getDefaultOption()
+ {
+ return 'property2';
+ }
+
+ public function getTargets()
+ {
+ return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintAValidator.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintAValidator.php
new file mode 100644
index 0000000..b3b85c8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintAValidator.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use Symfony\Component\Validator\ExecutionContextInterface;
+
+class ConstraintAValidator extends ConstraintValidator
+{
+ public static $passedContext;
+
+ public function initialize(ExecutionContextInterface $context)
+ {
+ parent::initialize($context);
+
+ self::$passedContext = $context;
+ }
+
+ public function validate($value, Constraint $constraint)
+ {
+ if ('VALID' != $value) {
+ $this->context->addViolation('message', array('param' => 'value'));
+
+ return;
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintB.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintB.php
new file mode 100644
index 0000000..6258923
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintB.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+/** @Annotation */
+class ConstraintB extends Constraint
+{
+ public function getTargets()
+ {
+ return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintC.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintC.php
new file mode 100644
index 0000000..b0418b8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintC.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+/** @Annotation */
+class ConstraintC extends Constraint
+{
+ public $option1;
+
+ public function getRequiredOptions()
+ {
+ return array('option1');
+ }
+
+ public function getTargets()
+ {
+ return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValue.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValue.php
new file mode 100644
index 0000000..4ebd981
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValue.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+/** @Annotation */
+class ConstraintWithValue extends Constraint
+{
+ public $property;
+ public $value;
+
+ public function getDefaultOption()
+ {
+ return 'property';
+ }
+
+ public function getTargets()
+ {
+ return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValueAsDefault.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValueAsDefault.php
new file mode 100644
index 0000000..a975e07
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ConstraintWithValueAsDefault.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+/** @Annotation */
+class ConstraintWithValueAsDefault extends Constraint
+{
+ public $property;
+ public $value;
+
+ public function getDefaultOption()
+ {
+ return 'value';
+ }
+
+ public function getTargets()
+ {
+ return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Countable.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Countable.php
new file mode 100644
index 0000000..afc4237
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Countable.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+class Countable implements \Countable
+{
+ private $content;
+
+ public function __construct(array $content)
+ {
+ $this->content = $content;
+ }
+
+ public function count()
+ {
+ return \count($this->content);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/CustomArrayObject.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/CustomArrayObject.php
new file mode 100644
index 0000000..feb2531
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/CustomArrayObject.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+/**
+ * This class is a hand written simplified version of PHP native `ArrayObject`
+ * class, to show that it behaves differently than the PHP native implementation.
+ */
+class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable
+{
+ private $array;
+
+ public function __construct(array $array = null)
+ {
+ $this->array = $array ?: array();
+ }
+
+ public function offsetExists($offset)
+ {
+ return array_key_exists($offset, $this->array);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->array[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ if (null === $offset) {
+ $this->array[] = $value;
+ } else {
+ $this->array[$offset] = $value;
+ }
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->array[$offset]);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->array);
+ }
+
+ public function count()
+ {
+ return \count($this->array);
+ }
+
+ public function serialize()
+ {
+ return serialize($this->array);
+ }
+
+ public function unserialize($serialized)
+ {
+ $this->array = (array) unserialize((string) $serialized);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Entity.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Entity.php
new file mode 100644
index 0000000..e306191
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Entity.php
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraints as Assert;
+use Symfony\Component\Validator\ExecutionContextInterface;
+
+/**
+ * @Symfony\Component\Validator\Tests\Fixtures\ConstraintA
+ * @Assert\GroupSequence({"Foo", "Entity"})
+ * @Assert\Callback({"Symfony\Component\Validator\Tests\Fixtures\CallbackClass", "callback"})
+ */
+class Entity extends EntityParent implements EntityInterfaceB
+{
+ /**
+ * @Assert\NotNull
+ * @Assert\Range(min=3)
+ * @Assert\All({@Assert\NotNull, @Assert\Range(min=3)}),
+ * @Assert\All(constraints={@Assert\NotNull, @Assert\Range(min=3)})
+ * @Assert\Collection(fields={
+ * "foo" = {@Assert\NotNull, @Assert\Range(min=3)},
+ * "bar" = @Assert\Range(min=5)
+ * })
+ * @Assert\Choice(choices={"A", "B"}, message="Must be one of %choices%")
+ */
+ public $firstName;
+ protected $lastName;
+ public $reference;
+ public $reference2;
+ private $internal;
+ public $data = 'Overridden data';
+ public $initialized = false;
+
+ public function __construct($internal = null)
+ {
+ $this->internal = $internal;
+ }
+
+ public function getInternal()
+ {
+ return $this->internal.' from getter';
+ }
+
+ public function setLastName($lastName)
+ {
+ $this->lastName = $lastName;
+ }
+
+ /**
+ * @Assert\NotNull
+ */
+ public function getLastName()
+ {
+ return $this->lastName;
+ }
+
+ public function getValid()
+ {
+ }
+
+ /**
+ * @Assert\IsTrue
+ */
+ public function isValid()
+ {
+ return 'valid';
+ }
+
+ /**
+ * @Assert\IsTrue
+ */
+ public function hasPermissions()
+ {
+ return 'permissions';
+ }
+
+ public function getData()
+ {
+ return 'Overridden data';
+ }
+
+ /**
+ * @Assert\Callback(payload="foo")
+ */
+ public function validateMe(ExecutionContextInterface $context)
+ {
+ }
+
+ /**
+ * @Assert\Callback
+ */
+ public static function validateMeStatic($object, ExecutionContextInterface $context)
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceA.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceA.php
new file mode 100644
index 0000000..a0afcf8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceA.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+interface EntityInterfaceA
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceB.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceB.php
new file mode 100644
index 0000000..93b3894
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityInterfaceB.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+interface EntityInterfaceB extends EntityParentInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParent.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParent.php
new file mode 100644
index 0000000..4674f8b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParent.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraints\NotNull;
+
+class EntityParent implements EntityInterfaceA
+{
+ protected $firstName;
+ private $internal;
+ private $data = 'Data';
+
+ /**
+ * @NotNull
+ */
+ protected $other;
+
+ public function getData()
+ {
+ return 'Data';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParentInterface.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParentInterface.php
new file mode 100644
index 0000000..3aad6fe
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityParentInterface.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+interface EntityParentInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCar.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCar.php
new file mode 100644
index 0000000..0b38487
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCar.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+class EntityStaticCar extends EntityStaticVehicle
+{
+ public static function loadValidatorMetadata(ClassMetadata $metadata)
+ {
+ $metadata->addPropertyConstraint('wheels', new Length(array('max' => 99)));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCarTurbo.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCarTurbo.php
new file mode 100644
index 0000000..abf1edb
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticCarTurbo.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+class EntityStaticCarTurbo extends EntityStaticCar
+{
+ public static function loadValidatorMetadata(ClassMetadata $metadata)
+ {
+ $metadata->addPropertyConstraint('wheels', new Length(array('max' => 99)));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticVehicle.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticVehicle.php
new file mode 100644
index 0000000..9ce7293
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/EntityStaticVehicle.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+class EntityStaticVehicle
+{
+ public $wheels;
+
+ public static function loadValidatorMetadata(ClassMetadata $metadata)
+ {
+ $metadata->addPropertyConstraint('wheels', new Length(array('max' => 99)));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraint.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraint.php
new file mode 100644
index 0000000..03019fc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraint.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+class FailingConstraint extends Constraint
+{
+ public $message = 'Failed';
+
+ public function getTargets()
+ {
+ return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraintValidator.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraintValidator.php
new file mode 100644
index 0000000..a019dd6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FailingConstraintValidator.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+class FailingConstraintValidator extends ConstraintValidator
+{
+ public function validate($value, Constraint $constraint)
+ {
+ $this->context->addViolation($constraint->message, array());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeClassMetadata.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeClassMetadata.php
new file mode 100644
index 0000000..8c76a21
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeClassMetadata.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+class FakeClassMetadata extends ClassMetadata
+{
+ public function addCustomPropertyMetadata($propertyName, $metadata)
+ {
+ if (!isset($this->members[$propertyName])) {
+ $this->members[$propertyName] = array();
+ }
+
+ $this->members[$propertyName][] = $metadata;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeMetadataFactory.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeMetadataFactory.php
new file mode 100644
index 0000000..dbc255f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FakeMetadataFactory.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Exception\NoSuchMetadataException;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\MetadataInterface;
+
+class FakeMetadataFactory implements MetadataFactoryInterface
+{
+ protected $metadatas = array();
+
+ public function getMetadataFor($class)
+ {
+ $hash = null;
+
+ if (\is_object($class)) {
+ $hash = spl_object_hash($class);
+ $class = \get_class($class);
+ }
+
+ if (!\is_string($class)) {
+ throw new NoSuchMetadataException(sprintf('No metadata for type %s', \gettype($class)));
+ }
+
+ if (!isset($this->metadatas[$class])) {
+ if (isset($this->metadatas[$hash])) {
+ return $this->metadatas[$hash];
+ }
+
+ throw new NoSuchMetadataException(sprintf('No metadata for "%s"', $class));
+ }
+
+ return $this->metadatas[$class];
+ }
+
+ public function hasMetadataFor($class)
+ {
+ $hash = null;
+
+ if (\is_object($class)) {
+ $hash = spl_object_hash($class);
+ $class = \get_class($class);
+ }
+
+ if (!\is_string($class)) {
+ return false;
+ }
+
+ return isset($this->metadatas[$class]) || isset($this->metadatas[$hash]);
+ }
+
+ public function addMetadata($metadata)
+ {
+ $this->metadatas[$metadata->getClassName()] = $metadata;
+ }
+
+ public function addMetadataForValue($value, MetadataInterface $metadata)
+ {
+ $key = \is_object($value) ? spl_object_hash($value) : $value;
+ $this->metadatas[$key] = $metadata;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FilesLoader.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FilesLoader.php
new file mode 100644
index 0000000..a4d6a6a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/FilesLoader.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Mapping\Loader\FilesLoader as BaseFilesLoader;
+use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
+
+abstract class FilesLoader extends BaseFilesLoader
+{
+ protected $timesCalled = 0;
+ protected $loader;
+
+ public function __construct(array $paths, LoaderInterface $loader)
+ {
+ $this->loader = $loader;
+ parent::__construct($paths);
+ }
+
+ protected function getFileLoaderInstance($file)
+ {
+ ++$this->timesCalled;
+
+ return $this->loader;
+ }
+
+ public function getTimesCalled()
+ {
+ return $this->timesCalled;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php
new file mode 100644
index 0000000..be7191f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+class GroupSequenceProviderChildEntity extends GroupSequenceProviderEntity
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderEntity.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderEntity.php
new file mode 100644
index 0000000..2b0beaf
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/GroupSequenceProviderEntity.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraints as Assert;
+use Symfony\Component\Validator\GroupSequenceProviderInterface;
+
+/**
+ * @Assert\GroupSequenceProvider
+ */
+class GroupSequenceProviderEntity implements GroupSequenceProviderInterface
+{
+ public $firstName;
+ public $lastName;
+
+ protected $sequence = array();
+
+ public function __construct($sequence)
+ {
+ $this->sequence = $sequence;
+ }
+
+ public function getGroupSequence()
+ {
+ return $this->sequence;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraint.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraint.php
new file mode 100644
index 0000000..6a9eaa7
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraint.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+class InvalidConstraint extends Constraint
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraintValidator.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraintValidator.php
new file mode 100644
index 0000000..bd9a5cf
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/InvalidConstraintValidator.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+class InvalidConstraintValidator
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/LegacyClassMetadata.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/LegacyClassMetadata.php
new file mode 100644
index 0000000..6a832a1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/LegacyClassMetadata.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\ClassBasedInterface;
+use Symfony\Component\Validator\MetadataInterface;
+use Symfony\Component\Validator\PropertyMetadataContainerInterface;
+
+interface LegacyClassMetadata extends MetadataInterface, PropertyMetadataContainerInterface, ClassBasedInterface
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/PropertyConstraint.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/PropertyConstraint.php
new file mode 100644
index 0000000..fadb535
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/PropertyConstraint.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\Constraint;
+
+class PropertyConstraint extends Constraint
+{
+ public function getTargets()
+ {
+ return self::PROPERTY_CONSTRAINT;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Reference.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Reference.php
new file mode 100644
index 0000000..af29735
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/Reference.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+class Reference
+{
+ public $value;
+
+ private $privateValue;
+
+ public function setPrivateValue($privateValue)
+ {
+ $this->privateValue = $privateValue;
+ }
+
+ public function getPrivateValue()
+ {
+ return $this->privateValue;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/StubGlobalExecutionContext.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/StubGlobalExecutionContext.php
new file mode 100644
index 0000000..bd2f5c9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/StubGlobalExecutionContext.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+use Symfony\Component\Validator\ConstraintViolationList;
+use Symfony\Component\Validator\GlobalExecutionContextInterface;
+use Symfony\Component\Validator\ValidationVisitorInterface;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0
+ */
+class StubGlobalExecutionContext implements GlobalExecutionContextInterface
+{
+ private $violations;
+ private $root;
+ private $visitor;
+
+ public function __construct($root = null, ValidationVisitorInterface $visitor = null)
+ {
+ $this->violations = new ConstraintViolationList();
+ $this->root = $root;
+ $this->visitor = $visitor;
+ }
+
+ public function getViolations()
+ {
+ return $this->violations;
+ }
+
+ public function setRoot($root)
+ {
+ $this->root = $root;
+ }
+
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ public function setVisitor(ValidationVisitorInterface $visitor)
+ {
+ $this->visitor = $visitor;
+ }
+
+ public function getVisitor()
+ {
+ return $this->visitor;
+ }
+
+ public function getValidatorFactory()
+ {
+ }
+
+ public function getMetadataFactory()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ToString.php b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ToString.php
new file mode 100644
index 0000000..714fdb9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Fixtures/ToString.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+class ToString
+{
+ public $data;
+
+ public function __toString()
+ {
+ return 'toString';
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/LegacyExecutionContextTest.php b/public/system/storage/vendor/symfony/validator/Tests/LegacyExecutionContextTest.php
new file mode 100644
index 0000000..1130551
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/LegacyExecutionContextTest.php
@@ -0,0 +1,335 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\All;
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\ConstraintValidatorFactory;
+use Symfony\Component\Validator\ConstraintViolation;
+use Symfony\Component\Validator\ConstraintViolationList;
+use Symfony\Component\Validator\ExecutionContext;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\ValidationVisitor;
+
+/**
+ * @group legacy
+ */
+class LegacyExecutionContextTest extends TestCase
+{
+ const TRANS_DOMAIN = 'trans_domain';
+
+ private $visitor;
+ private $violations;
+ private $metadata;
+ private $metadataFactory;
+ private $globalContext;
+ private $translator;
+
+ /**
+ * @var ExecutionContext
+ */
+ private $context;
+
+ protected function setUp()
+ {
+ $this->visitor = $this->getMockBuilder('Symfony\Component\Validator\ValidationVisitor')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->violations = new ConstraintViolationList();
+ $this->metadata = $this->getMockBuilder('Symfony\Component\Validator\MetadataInterface')->getMock();
+ $this->metadataFactory = $this->getMockBuilder('Symfony\Component\Validator\MetadataFactoryInterface')->getMock();
+ $this->globalContext = $this->getMockBuilder('Symfony\Component\Validator\GlobalExecutionContextInterface')->getMock();
+ $this->globalContext->expects($this->any())
+ ->method('getRoot')
+ ->will($this->returnValue('Root'));
+ $this->globalContext->expects($this->any())
+ ->method('getViolations')
+ ->will($this->returnValue($this->violations));
+ $this->globalContext->expects($this->any())
+ ->method('getVisitor')
+ ->will($this->returnValue($this->visitor));
+ $this->globalContext->expects($this->any())
+ ->method('getMetadataFactory')
+ ->will($this->returnValue($this->metadataFactory));
+ $this->translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
+ $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
+ }
+
+ protected function tearDown()
+ {
+ $this->globalContext = null;
+ $this->context = null;
+ }
+
+ public function testInit()
+ {
+ $this->assertCount(0, $this->context->getViolations());
+ $this->assertSame('Root', $this->context->getRoot());
+ $this->assertSame('foo.bar', $this->context->getPropertyPath());
+ $this->assertSame('Group', $this->context->getGroup());
+ }
+
+ public function testClone()
+ {
+ $clone = clone $this->context;
+
+ // Cloning the context keeps the reference to the original violation
+ // list. This way we can efficiently duplicate context instances during
+ // the validation run and only modify the properties that need to be
+ // changed.
+ $this->assertSame($this->context->getViolations(), $clone->getViolations());
+ }
+
+ public function testAddViolation()
+ {
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Error', array('foo' => 'bar'))
+ ->will($this->returnValue('Translated error'));
+
+ $this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');
+
+ $this->assertEquals(new ConstraintViolationList(array(
+ new ConstraintViolation(
+ 'Translated error',
+ 'Error',
+ array('foo' => 'bar'),
+ 'Root',
+ 'foo.bar',
+ 'invalid'
+ ),
+ )), $this->context->getViolations());
+ }
+
+ public function testAddViolationUsesPreconfiguredValueIfNotPassed()
+ {
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Error', array())
+ ->will($this->returnValue('Translated error'));
+
+ $this->context->addViolation('Error');
+
+ $this->assertEquals(new ConstraintViolationList(array(
+ new ConstraintViolation(
+ 'Translated error',
+ 'Error',
+ array(),
+ 'Root',
+ 'foo.bar',
+ 'currentValue'
+ ),
+ )), $this->context->getViolations());
+ }
+
+ public function testAddViolationUsesPassedNullValue()
+ {
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Error', array('foo1' => 'bar1'))
+ ->will($this->returnValue('Translated error'));
+ $this->translator->expects($this->once())
+ ->method('transChoice')
+ ->with('Choice error', 1, array('foo2' => 'bar2'))
+ ->will($this->returnValue('Translated choice error'));
+
+ // passed null value should override preconfigured value "invalid"
+ $this->context->addViolation('Error', array('foo1' => 'bar1'), null);
+ $this->context->addViolation('Choice error', array('foo2' => 'bar2'), null, 1);
+
+ $this->assertEquals(new ConstraintViolationList(array(
+ new ConstraintViolation(
+ 'Translated error',
+ 'Error',
+ array('foo1' => 'bar1'),
+ 'Root',
+ 'foo.bar',
+ null
+ ),
+ new ConstraintViolation(
+ 'Translated choice error',
+ 'Choice error',
+ array('foo2' => 'bar2'),
+ 'Root',
+ 'foo.bar',
+ null,
+ 1
+ ),
+ )), $this->context->getViolations());
+ }
+
+ public function testAddViolationAt()
+ {
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Error', array('foo' => 'bar'))
+ ->will($this->returnValue('Translated error'));
+
+ // override preconfigured property path
+ $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');
+
+ $this->assertEquals(new ConstraintViolationList(array(
+ new ConstraintViolation(
+ 'Translated error',
+ 'Error',
+ array('foo' => 'bar'),
+ 'Root',
+ 'foo.bar.bam.baz',
+ 'invalid'
+ ),
+ )), $this->context->getViolations());
+ }
+
+ public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
+ {
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Error', array())
+ ->will($this->returnValue('Translated error'));
+
+ $this->context->addViolationAt('bam.baz', 'Error');
+
+ $this->assertEquals(new ConstraintViolationList(array(
+ new ConstraintViolation(
+ 'Translated error',
+ 'Error',
+ array(),
+ 'Root',
+ 'foo.bar.bam.baz',
+ 'currentValue'
+ ),
+ )), $this->context->getViolations());
+ }
+
+ public function testAddViolationAtUsesPassedNullValue()
+ {
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('Error', array('foo' => 'bar'))
+ ->will($this->returnValue('Translated error'));
+ $this->translator->expects($this->once())
+ ->method('transChoice')
+ ->with('Choice error', 2, array('foo' => 'bar'))
+ ->will($this->returnValue('Translated choice error'));
+
+ // passed null value should override preconfigured value "invalid"
+ $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null);
+ $this->context->addViolationAt('bam.baz', 'Choice error', array('foo' => 'bar'), null, 2);
+
+ $this->assertEquals(new ConstraintViolationList(array(
+ new ConstraintViolation(
+ 'Translated error',
+ 'Error',
+ array('foo' => 'bar'),
+ 'Root',
+ 'foo.bar.bam.baz',
+ null
+ ),
+ new ConstraintViolation(
+ 'Translated choice error',
+ 'Choice error',
+ array('foo' => 'bar'),
+ 'Root',
+ 'foo.bar.bam.baz',
+ null,
+ 2
+ ),
+ )), $this->context->getViolations());
+ }
+
+ public function testAddViolationPluralTranslationError()
+ {
+ $this->translator->expects($this->once())
+ ->method('transChoice')
+ ->with('foo')
+ ->will($this->throwException(new \InvalidArgumentException()));
+ $this->translator->expects($this->once())
+ ->method('trans')
+ ->with('foo');
+
+ $this->context->addViolation('foo', array(), null, 2);
+ }
+
+ public function testGetPropertyPath()
+ {
+ $this->assertEquals('foo.bar', $this->context->getPropertyPath());
+ }
+
+ public function testGetPropertyPathWithIndexPath()
+ {
+ $this->assertEquals('foo.bar[bam]', $this->context->getPropertyPath('[bam]'));
+ }
+
+ public function testGetPropertyPathWithEmptyPath()
+ {
+ $this->assertEquals('foo.bar', $this->context->getPropertyPath(''));
+ }
+
+ public function testGetPropertyPathWithEmptyCurrentPropertyPath()
+ {
+ $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', '');
+
+ $this->assertEquals('bam.baz', $this->context->getPropertyPath('bam.baz'));
+ }
+
+ public function testGetPropertyPathWithNestedCollectionsAndAllMixed()
+ {
+ $constraints = new Collection(array(
+ 'shelves' => new All(array('constraints' => array(
+ new Collection(array(
+ 'name' => new ConstraintA(),
+ 'books' => new All(array('constraints' => array(
+ new ConstraintA(),
+ ))),
+ )),
+ ))),
+ 'name' => new ConstraintA(),
+ ));
+ $data = array(
+ 'shelves' => array(
+ array(
+ 'name' => 'Research',
+ 'books' => array('foo', 'bar'),
+ ),
+ array(
+ 'name' => 'VALID',
+ 'books' => array('foozy', 'VALID', 'bazzy'),
+ ),
+ ),
+ 'name' => 'Library',
+ );
+ $expectedViolationPaths = array(
+ '[shelves][0][name]',
+ '[shelves][0][books][0]',
+ '[shelves][0][books][1]',
+ '[shelves][1][books][0]',
+ '[shelves][1][books][2]',
+ '[name]',
+ );
+
+ $visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), $this->translator);
+ $context = new ExecutionContext($visitor, $this->translator, self::TRANS_DOMAIN);
+ $context->validateValue($data, $constraints);
+
+ foreach ($context->getViolations() as $violation) {
+ $violationPaths[] = $violation->getPropertyPath();
+ }
+
+ $this->assertEquals($expectedViolationPaths, $violationPaths);
+ }
+}
+
+class ExecutionContextTest_TestClass
+{
+ public $myProperty;
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/LegacyValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/LegacyValidatorTest.php
new file mode 100644
index 0000000..a38f1ab
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/LegacyValidatorTest.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests;
+
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\ConstraintValidatorFactory;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+use Symfony\Component\Validator\Tests\Validator\AbstractLegacyApiTest;
+use Symfony\Component\Validator\Validator as LegacyValidator;
+
+/**
+ * @group legacy
+ */
+class LegacyValidatorTest extends AbstractLegacyApiTest
+{
+ protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array())
+ {
+ $translator = new IdentityTranslator();
+ $translator->setLocale('en');
+
+ return new LegacyValidator($metadataFactory, new ConstraintValidatorFactory(), $translator, 'validators', $objectInitializers);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
+ */
+ public function testValidateValueRejectsValid()
+ {
+ $this->validator->validateValue(new Entity(), new Valid());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/DoctrineCacheTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/DoctrineCacheTest.php
new file mode 100644
index 0000000..19b2922
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/DoctrineCacheTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Cache;
+
+use Doctrine\Common\Cache\ArrayCache;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\Cache\DoctrineCache;
+
+class DoctrineCacheTest extends TestCase
+{
+ private $cache;
+
+ public function testWrite()
+ {
+ $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassName'))
+ ->getMock();
+
+ $meta->expects($this->once())
+ ->method('getClassName')
+ ->will($this->returnValue('bar'));
+
+ $this->cache->write($meta);
+
+ $this->assertInstanceOf(
+ 'Symfony\\Component\\Validator\\Mapping\\ClassMetadata',
+ $this->cache->read('bar'),
+ 'write() stores metadata'
+ );
+ }
+
+ public function testHas()
+ {
+ $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassName'))
+ ->getMock();
+
+ $meta->expects($this->once())
+ ->method('getClassName')
+ ->will($this->returnValue('bar'));
+
+ $this->assertFalse($this->cache->has('bar'), 'has() returns false when there is no entry');
+
+ $this->cache->write($meta);
+ $this->assertTrue($this->cache->has('bar'), 'has() returns true when the is an entry');
+ }
+
+ public function testRead()
+ {
+ $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassName'))
+ ->getMock();
+
+ $meta->expects($this->once())
+ ->method('getClassName')
+ ->will($this->returnValue('bar'));
+
+ $this->assertFalse($this->cache->read('bar'), 'read() returns false when there is no entry');
+
+ $this->cache->write($meta);
+
+ $this->assertInstanceOf(
+ 'Symfony\\Component\\Validator\\Mapping\\ClassMetadata',
+ $this->cache->read('bar'),
+ 'read() returns metadata'
+ );
+ }
+
+ protected function setUp()
+ {
+ $this->cache = new DoctrineCache(new ArrayCache());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/LegacyApcCacheTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/LegacyApcCacheTest.php
new file mode 100644
index 0000000..7102474
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Cache/LegacyApcCacheTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Cache;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\Cache\ApcCache;
+
+/**
+ * @group legacy
+ * @requires extension apc
+ */
+class LegacyApcCacheTest extends TestCase
+{
+ protected function setUp()
+ {
+ if (!filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) || !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
+ $this->markTestSkipped('APC is not enabled.');
+ }
+ }
+
+ public function testWrite()
+ {
+ $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassName'))
+ ->getMock();
+
+ $meta->expects($this->once())
+ ->method('getClassName')
+ ->will($this->returnValue('bar'));
+
+ $cache = new ApcCache('foo');
+ $cache->write($meta);
+
+ $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', apc_fetch('foobar'), '->write() stores metadata in APC');
+ }
+
+ public function testHas()
+ {
+ $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassName'))
+ ->getMock();
+
+ $meta->expects($this->once())
+ ->method('getClassName')
+ ->will($this->returnValue('bar'));
+
+ apc_delete('foobar');
+
+ $cache = new ApcCache('foo');
+ $this->assertFalse($cache->has('bar'), '->has() returns false when there is no entry');
+
+ $cache->write($meta);
+ $this->assertTrue($cache->has('bar'), '->has() returns true when the is an entry');
+ }
+
+ public function testRead()
+ {
+ $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassName'))
+ ->getMock();
+
+ $meta->expects($this->once())
+ ->method('getClassName')
+ ->will($this->returnValue('bar'));
+
+ $cache = new ApcCache('foo');
+ $cache->write($meta);
+
+ $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', $cache->read('bar'), '->read() returns metadata');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/ClassMetadataTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/ClassMetadataTest.php
new file mode 100644
index 0000000..a3f8a8c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/ClassMetadataTest.php
@@ -0,0 +1,323 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
+use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;
+
+class ClassMetadataTest extends TestCase
+{
+ const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
+ const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
+ const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity';
+ const PROVIDERCHILDCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderChildEntity';
+
+ protected $metadata;
+
+ protected function setUp()
+ {
+ $this->metadata = new ClassMetadata(self::CLASSNAME);
+ }
+
+ protected function tearDown()
+ {
+ $this->metadata = null;
+ }
+
+ public function testAddConstraintDoesNotAcceptValid()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+
+ $this->metadata->addConstraint(new Valid());
+ }
+
+ public function testAddConstraintRequiresClassConstraints()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+
+ $this->metadata->addConstraint(new PropertyConstraint());
+ }
+
+ public function testAddPropertyConstraints()
+ {
+ $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
+ $this->metadata->addPropertyConstraint('lastName', new ConstraintB());
+
+ $this->assertEquals(array('firstName', 'lastName'), $this->metadata->getConstrainedProperties());
+ }
+
+ public function testAddMultiplePropertyConstraints()
+ {
+ $this->metadata->addPropertyConstraints('lastName', array(new ConstraintA(), new ConstraintB()));
+
+ $constraints = array(
+ new ConstraintA(array('groups' => array('Default', 'Entity'))),
+ new ConstraintB(array('groups' => array('Default', 'Entity'))),
+ );
+
+ $properties = $this->metadata->getPropertyMetadata('lastName');
+
+ $this->assertCount(1, $properties);
+ $this->assertEquals('lastName', $properties[0]->getName());
+ $this->assertEquals($constraints, $properties[0]->getConstraints());
+ }
+
+ public function testAddGetterConstraints()
+ {
+ $this->metadata->addGetterConstraint('lastName', new ConstraintA());
+ $this->metadata->addGetterConstraint('lastName', new ConstraintB());
+
+ $constraints = array(
+ new ConstraintA(array('groups' => array('Default', 'Entity'))),
+ new ConstraintB(array('groups' => array('Default', 'Entity'))),
+ );
+
+ $properties = $this->metadata->getPropertyMetadata('lastName');
+
+ $this->assertCount(1, $properties);
+ $this->assertEquals('getLastName', $properties[0]->getName());
+ $this->assertEquals($constraints, $properties[0]->getConstraints());
+ }
+
+ public function testAddMultipleGetterConstraints()
+ {
+ $this->metadata->addGetterConstraints('lastName', array(new ConstraintA(), new ConstraintB()));
+
+ $constraints = array(
+ new ConstraintA(array('groups' => array('Default', 'Entity'))),
+ new ConstraintB(array('groups' => array('Default', 'Entity'))),
+ );
+
+ $properties = $this->metadata->getPropertyMetadata('lastName');
+
+ $this->assertCount(1, $properties);
+ $this->assertEquals('getLastName', $properties[0]->getName());
+ $this->assertEquals($constraints, $properties[0]->getConstraints());
+ }
+
+ public function testMergeConstraintsMergesClassConstraints()
+ {
+ $parent = new ClassMetadata(self::PARENTCLASS);
+ $parent->addConstraint(new ConstraintA());
+
+ $this->metadata->mergeConstraints($parent);
+ $this->metadata->addConstraint(new ConstraintA());
+
+ $constraints = array(
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityParent',
+ 'Entity',
+ ))),
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'Entity',
+ ))),
+ );
+
+ $this->assertEquals($constraints, $this->metadata->getConstraints());
+ }
+
+ public function testMergeConstraintsMergesMemberConstraints()
+ {
+ $parent = new ClassMetadata(self::PARENTCLASS);
+ $parent->addPropertyConstraint('firstName', new ConstraintA());
+ $parent->addPropertyConstraint('firstName', new ConstraintB(array('groups' => 'foo')));
+
+ $this->metadata->mergeConstraints($parent);
+ $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
+
+ $constraintA1 = new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityParent',
+ 'Entity',
+ )));
+ $constraintA2 = new ConstraintA(array('groups' => array(
+ 'Default',
+ 'Entity',
+ )));
+ $constraintB = new ConstraintB(array(
+ 'groups' => array('foo'),
+ ));
+
+ $constraints = array(
+ $constraintA1,
+ $constraintB,
+ $constraintA2,
+ );
+
+ $constraintsByGroup = array(
+ 'Default' => array(
+ $constraintA1,
+ $constraintA2,
+ ),
+ 'EntityParent' => array(
+ $constraintA1,
+ ),
+ 'Entity' => array(
+ $constraintA1,
+ $constraintA2,
+ ),
+ 'foo' => array(
+ $constraintB,
+ ),
+ );
+
+ $members = $this->metadata->getPropertyMetadata('firstName');
+
+ $this->assertCount(1, $members);
+ $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName());
+ $this->assertEquals($constraints, $members[0]->getConstraints());
+ $this->assertEquals($constraintsByGroup, $members[0]->constraintsByGroup);
+ }
+
+ public function testMemberMetadatas()
+ {
+ $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
+
+ $this->assertTrue($this->metadata->hasPropertyMetadata('firstName'));
+ $this->assertFalse($this->metadata->hasPropertyMetadata('non_existent_field'));
+ }
+
+ public function testMergeConstraintsKeepsPrivateMembersSeparate()
+ {
+ $parent = new ClassMetadata(self::PARENTCLASS);
+ $parent->addPropertyConstraint('internal', new ConstraintA());
+
+ $this->metadata->mergeConstraints($parent);
+ $this->metadata->addPropertyConstraint('internal', new ConstraintA());
+
+ $parentConstraints = array(
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityParent',
+ 'Entity',
+ ))),
+ );
+ $constraints = array(
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'Entity',
+ ))),
+ );
+
+ $members = $this->metadata->getPropertyMetadata('internal');
+
+ $this->assertCount(2, $members);
+ $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName());
+ $this->assertEquals($parentConstraints, $members[0]->getConstraints());
+ $this->assertEquals(self::CLASSNAME, $members[1]->getClassName());
+ $this->assertEquals($constraints, $members[1]->getConstraints());
+ }
+
+ public function testGetReflectionClass()
+ {
+ $reflClass = new \ReflectionClass(self::CLASSNAME);
+
+ $this->assertEquals($reflClass, $this->metadata->getReflectionClass());
+ }
+
+ public function testSerialize()
+ {
+ $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
+ $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));
+ $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
+ $this->metadata->addGetterConstraint('lastName', new ConstraintB());
+
+ $metadata = unserialize(serialize($this->metadata));
+
+ $this->assertEquals($this->metadata, $metadata);
+ }
+
+ public function testGroupSequencesWorkIfContainingDefaultGroup()
+ {
+ $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup()));
+
+ $this->assertInstanceOf('Symfony\Component\Validator\Constraints\GroupSequence', $this->metadata->getGroupSequence());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
+ */
+ public function testGroupSequencesFailIfNotContainingDefaultGroup()
+ {
+ $this->metadata->setGroupSequence(array('Foo', 'Bar'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
+ */
+ public function testGroupSequencesFailIfContainingDefault()
+ {
+ $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup(), Constraint::DEFAULT_GROUP));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
+ */
+ public function testGroupSequenceFailsIfGroupSequenceProviderIsSet()
+ {
+ $metadata = new ClassMetadata(self::PROVIDERCLASS);
+ $metadata->setGroupSequenceProvider(true);
+ $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
+ */
+ public function testGroupSequenceProviderFailsIfGroupSequenceIsSet()
+ {
+ $metadata = new ClassMetadata(self::PROVIDERCLASS);
+ $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo'));
+ $metadata->setGroupSequenceProvider(true);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
+ */
+ public function testGroupSequenceProviderFailsIfDomainClassIsInvalid()
+ {
+ $metadata = new ClassMetadata('stdClass');
+ $metadata->setGroupSequenceProvider(true);
+ }
+
+ public function testGroupSequenceProvider()
+ {
+ $metadata = new ClassMetadata(self::PROVIDERCLASS);
+ $metadata->setGroupSequenceProvider(true);
+ $this->assertTrue($metadata->isGroupSequenceProvider());
+ }
+
+ public function testMergeConstraintsMergesGroupSequenceProvider()
+ {
+ $parent = new ClassMetadata(self::PROVIDERCLASS);
+ $parent->setGroupSequenceProvider(true);
+
+ $metadata = new ClassMetadata(self::PROVIDERCHILDCLASS);
+ $metadata->mergeConstraints($parent);
+
+ $this->assertTrue($metadata->isGroupSequenceProvider());
+ }
+
+ /**
+ * https://github.com/symfony/symfony/issues/11604.
+ */
+ public function testGetPropertyMetadataReturnsEmptyArrayWithoutConfiguredMetadata()
+ {
+ $this->assertCount(0, $this->metadata->getPropertyMetadata('foo'), '->getPropertyMetadata() returns an empty collection if no metadata is configured for the given property');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/BlackHoleMetadataFactoryTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/BlackHoleMetadataFactoryTest.php
new file mode 100644
index 0000000..a323567
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/BlackHoleMetadataFactoryTest.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Factory;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\Factory\BlackHoleMetadataFactory;
+
+class BlackHoleMetadataFactoryTest extends TestCase
+{
+ /**
+ * @expectedException \LogicException
+ */
+ public function testGetMetadataForThrowsALogicException()
+ {
+ $metadataFactory = new BlackHoleMetadataFactory();
+ $metadataFactory->getMetadataFor('foo');
+ }
+
+ public function testHasMetadataForReturnsFalse()
+ {
+ $metadataFactory = new BlackHoleMetadataFactory();
+
+ $this->assertFalse($metadataFactory->hasMetadataFor('foo'));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php
new file mode 100644
index 0000000..de68522
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php
@@ -0,0 +1,218 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Factory;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
+use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+
+class LazyLoadingMetadataFactoryTest extends TestCase
+{
+ const CLASS_NAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
+ const PARENT_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
+ const INTERFACE_A_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA';
+ const INTERFACE_B_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceB';
+ const PARENT_INTERFACE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParentInterface';
+
+ public function testLoadClassMetadataWithInterface()
+ {
+ $factory = new LazyLoadingMetadataFactory(new TestLoader());
+ $metadata = $factory->getMetadataFor(self::PARENT_CLASS);
+
+ $constraints = array(
+ new ConstraintA(array('groups' => array('Default', 'EntityParent'))),
+ new ConstraintA(array('groups' => array('Default', 'EntityInterfaceA', 'EntityParent'))),
+ );
+
+ $this->assertEquals($constraints, $metadata->getConstraints());
+ }
+
+ public function testMergeParentConstraints()
+ {
+ $factory = new LazyLoadingMetadataFactory(new TestLoader());
+ $metadata = $factory->getMetadataFor(self::CLASS_NAME);
+
+ $constraints = array(
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'Entity',
+ ))),
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityParent',
+ 'Entity',
+ ))),
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityInterfaceA',
+ 'EntityParent',
+ 'Entity',
+ ))),
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityInterfaceB',
+ 'Entity',
+ ))),
+ new ConstraintA(array('groups' => array(
+ 'Default',
+ 'EntityParentInterface',
+ 'EntityInterfaceB',
+ 'Entity',
+ ))),
+ );
+
+ $this->assertEquals($constraints, $metadata->getConstraints());
+ }
+
+ public function testWriteMetadataToCache()
+ {
+ $cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
+ $factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache);
+
+ $parentClassConstraints = array(
+ new ConstraintA(array('groups' => array('Default', 'EntityParent'))),
+ new ConstraintA(array('groups' => array('Default', 'EntityInterfaceA', 'EntityParent'))),
+ );
+ $interfaceAConstraints = array(
+ new ConstraintA(array('groups' => array('Default', 'EntityInterfaceA'))),
+ );
+
+ $cache->expects($this->never())
+ ->method('has');
+ $cache->expects($this->exactly(2))
+ ->method('read')
+ ->withConsecutive(
+ array($this->equalTo(self::PARENT_CLASS)),
+ array($this->equalTo(self::INTERFACE_A_CLASS))
+ )
+ ->will($this->returnValue(false));
+ $cache->expects($this->exactly(2))
+ ->method('write')
+ ->withConsecutive(
+ $this->callback(function ($metadata) use ($interfaceAConstraints) {
+ return $interfaceAConstraints == $metadata->getConstraints();
+ }),
+ $this->callback(function ($metadata) use ($parentClassConstraints) {
+ return $parentClassConstraints == $metadata->getConstraints();
+ })
+ );
+
+ $metadata = $factory->getMetadataFor(self::PARENT_CLASS);
+
+ $this->assertEquals(self::PARENT_CLASS, $metadata->getClassName());
+ $this->assertEquals($parentClassConstraints, $metadata->getConstraints());
+ }
+
+ public function testReadMetadataFromCache()
+ {
+ $loader = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
+ $factory = new LazyLoadingMetadataFactory($loader, $cache);
+
+ $metadata = new ClassMetadata(self::PARENT_CLASS);
+ $metadata->addConstraint(new ConstraintA());
+
+ $parentClass = self::PARENT_CLASS;
+ $interfaceClass = self::INTERFACE_A_CLASS;
+
+ $loader->expects($this->never())
+ ->method('loadClassMetadata');
+
+ $cache->expects($this->never())
+ ->method('has');
+ $cache->expects($this->exactly(2))
+ ->method('read')
+ ->withConsecutive(
+ array(self::PARENT_CLASS),
+ array(self::INTERFACE_A_CLASS)
+ )
+ ->willReturnCallback(function ($name) use ($metadata, $parentClass, $interfaceClass) {
+ if ($parentClass == $name) {
+ return $metadata;
+ }
+
+ return new ClassMetadata($interfaceClass);
+ });
+
+ $this->assertEquals($metadata, $factory->getMetadataFor(self::PARENT_CLASS));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
+ */
+ public function testNonClassNameStringValues()
+ {
+ $testedValue = 'error@example.com';
+ $loader = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
+ $factory = new LazyLoadingMetadataFactory($loader, $cache);
+ $cache
+ ->expects($this->never())
+ ->method('read');
+ $factory->getMetadataFor($testedValue);
+ }
+
+ public function testMetadataCacheWithRuntimeConstraint()
+ {
+ $cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
+ $factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache);
+
+ $cache
+ ->expects($this->any())
+ ->method('write')
+ ->will($this->returnCallback(function ($metadata) { serialize($metadata); }))
+ ;
+
+ $cache->expects($this->any())
+ ->method('read')
+ ->will($this->returnValue(false));
+
+ $metadata = $factory->getMetadataFor(self::PARENT_CLASS);
+ $metadata->addConstraint(new Callback(function () {}));
+
+ $this->assertCount(3, $metadata->getConstraints());
+
+ $metadata = $factory->getMetadataFor(self::CLASS_NAME);
+
+ $this->assertCount(6, $metadata->getConstraints());
+ }
+
+ public function testGroupsFromParent()
+ {
+ $reader = new \Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader();
+ $factory = new LazyLoadingMetadataFactory($reader);
+ $metadata = $factory->getMetadataFor('Symfony\Component\Validator\Tests\Fixtures\EntityStaticCarTurbo');
+ $groups = array();
+
+ foreach ($metadata->getPropertyMetadata('wheels') as $propertyMetadata) {
+ $constraints = $propertyMetadata->getConstraints();
+ $groups = array_replace($groups, $constraints[0]->groups);
+ }
+
+ $this->assertCount(4, $groups);
+ $this->assertContains('Default', $groups);
+ $this->assertContains('EntityStaticCarTurbo', $groups);
+ $this->assertContains('EntityStaticCar', $groups);
+ $this->assertContains('EntityStaticVehicle', $groups);
+ }
+}
+
+class TestLoader implements LoaderInterface
+{
+ public function loadClassMetadata(ClassMetadata $metadata)
+ {
+ $metadata->addConstraint(new ConstraintA());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/GetterMetadataTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/GetterMetadataTest.php
new file mode 100644
index 0000000..05aef47
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/GetterMetadataTest.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\GetterMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+
+class GetterMetadataTest extends TestCase
+{
+ const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
+
+ public function testInvalidPropertyName()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ValidatorException');
+
+ new GetterMetadata(self::CLASSNAME, 'foobar');
+ }
+
+ public function testGetPropertyValueFromPublicGetter()
+ {
+ // private getters don't work yet because ReflectionMethod::setAccessible()
+ // does not exist yet in a stable PHP release
+
+ $entity = new Entity('foobar');
+ $metadata = new GetterMetadata(self::CLASSNAME, 'internal');
+
+ $this->assertEquals('foobar from getter', $metadata->getPropertyValue($entity));
+ }
+
+ public function testGetPropertyValueFromOverriddenPublicGetter()
+ {
+ $entity = new Entity();
+ $metadata = new GetterMetadata(self::CLASSNAME, 'data');
+
+ $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
+ }
+
+ public function testGetPropertyValueFromIsser()
+ {
+ $entity = new Entity();
+ $metadata = new GetterMetadata(self::CLASSNAME, 'valid', 'isValid');
+
+ $this->assertEquals('valid', $metadata->getPropertyValue($entity));
+ }
+
+ public function testGetPropertyValueFromHasser()
+ {
+ $entity = new Entity();
+ $metadata = new GetterMetadata(self::CLASSNAME, 'permissions');
+
+ $this->assertEquals('permissions', $metadata->getPropertyValue($entity));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
+ * @expectedExceptionMessage The hasLastName() method does not exist in class Symfony\Component\Validator\Tests\Fixtures\Entity.
+ */
+ public function testUndefinedMethodNameThrowsException()
+ {
+ new GetterMetadata(self::CLASSNAME, 'lastName', 'hasLastName');
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/LegacyElementMetadataTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/LegacyElementMetadataTest.php
new file mode 100644
index 0000000..1fb2e6e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/LegacyElementMetadataTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\ElementMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
+
+/**
+ * @group legacy
+ */
+class LegacyElementMetadataTest extends TestCase
+{
+ protected $metadata;
+
+ protected function setUp()
+ {
+ $this->metadata = new TestElementMetadata();
+ }
+
+ protected function tearDown()
+ {
+ $this->metadata = null;
+ }
+
+ public function testAddConstraints()
+ {
+ $this->metadata->addConstraint($constraint1 = new ConstraintA());
+ $this->metadata->addConstraint($constraint2 = new ConstraintA());
+
+ $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints());
+ }
+
+ public function testMultipleConstraintsOfTheSameType()
+ {
+ $constraint1 = new ConstraintA(array('property1' => 'A'));
+ $constraint2 = new ConstraintA(array('property1' => 'B'));
+
+ $this->metadata->addConstraint($constraint1);
+ $this->metadata->addConstraint($constraint2);
+
+ $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints());
+ }
+
+ public function testFindConstraintsByGroup()
+ {
+ $constraint1 = new ConstraintA(array('groups' => 'TestGroup'));
+ $constraint2 = new ConstraintB();
+
+ $this->metadata->addConstraint($constraint1);
+ $this->metadata->addConstraint($constraint2);
+
+ $this->assertEquals(array($constraint1), $this->metadata->findConstraints('TestGroup'));
+ }
+
+ public function testSerialize()
+ {
+ $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
+ $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));
+
+ $metadata = unserialize(serialize($this->metadata));
+
+ $this->assertEquals($this->metadata, $metadata);
+ }
+}
+
+class TestElementMetadata extends ElementMetadata
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AbstractStaticMethodLoader.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AbstractStaticMethodLoader.php
new file mode 100644
index 0000000..d032f0e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AbstractStaticMethodLoader.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+
+abstract class AbstractStaticMethodLoader
+{
+ abstract public static function loadMetadata(ClassMetadata $metadata);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AnnotationLoaderTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AnnotationLoaderTest.php
new file mode 100644
index 0000000..6e01193
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/AnnotationLoaderTest.php
@@ -0,0 +1,164 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use Doctrine\Common\Annotations\AnnotationReader;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\All;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\Choice;
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\Constraints\IsTrue;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Range;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+
+class AnnotationLoaderTest extends TestCase
+{
+ public function testLoadClassMetadataReturnsTrueIfSuccessful()
+ {
+ $reader = new AnnotationReader();
+ $loader = new AnnotationLoader($reader);
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $this->assertTrue($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
+ {
+ $loader = new AnnotationLoader(new AnnotationReader());
+ $metadata = new ClassMetadata('\stdClass');
+
+ $this->assertFalse($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadata()
+ {
+ $loader = new AnnotationLoader(new AnnotationReader());
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+ $expected->setGroupSequence(array('Foo', 'Entity'));
+ $expected->addConstraint(new ConstraintA());
+ $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
+ $expected->addConstraint(new Callback(array('callback' => 'validateMe', 'payload' => 'foo')));
+ $expected->addConstraint(new Callback('validateMeStatic'));
+ $expected->addPropertyConstraint('firstName', new NotNull());
+ $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
+ $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
+ $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
+ $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
+ 'foo' => array(new NotNull(), new Range(array('min' => 3))),
+ 'bar' => new Range(array('min' => 5)),
+ ))));
+ $expected->addPropertyConstraint('firstName', new Choice(array(
+ 'message' => 'Must be one of %choices%',
+ 'choices' => array('A', 'B'),
+ )));
+ $expected->addGetterConstraint('lastName', new NotNull());
+ $expected->addGetterMethodConstraint('valid', 'isValid', new IsTrue());
+ $expected->addGetterConstraint('permissions', new IsTrue());
+
+ // load reflection class so that the comparison passes
+ $expected->getReflectionClass();
+
+ $this->assertEquals($expected, $metadata);
+ }
+
+ /**
+ * Test MetaData merge with parent annotation.
+ */
+ public function testLoadParentClassMetadata()
+ {
+ $loader = new AnnotationLoader(new AnnotationReader());
+
+ // Load Parent MetaData
+ $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
+ $loader->loadClassMetadata($parent_metadata);
+
+ $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
+ $expected_parent->addPropertyConstraint('other', new NotNull());
+ $expected_parent->getReflectionClass();
+
+ $this->assertEquals($expected_parent, $parent_metadata);
+ }
+
+ /**
+ * Test MetaData merge with parent annotation.
+ */
+ public function testLoadClassMetadataAndMerge()
+ {
+ $loader = new AnnotationLoader(new AnnotationReader());
+
+ // Load Parent MetaData
+ $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
+ $loader->loadClassMetadata($parent_metadata);
+
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ // Merge parent metaData.
+ $metadata->mergeConstraints($parent_metadata);
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
+ $expected_parent->addPropertyConstraint('other', new NotNull());
+ $expected_parent->getReflectionClass();
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+ $expected->mergeConstraints($expected_parent);
+
+ $expected->setGroupSequence(array('Foo', 'Entity'));
+ $expected->addConstraint(new ConstraintA());
+ $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
+ $expected->addConstraint(new Callback(array('callback' => 'validateMe', 'payload' => 'foo')));
+ $expected->addConstraint(new Callback('validateMeStatic'));
+ $expected->addPropertyConstraint('firstName', new NotNull());
+ $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
+ $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
+ $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
+ $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
+ 'foo' => array(new NotNull(), new Range(array('min' => 3))),
+ 'bar' => new Range(array('min' => 5)),
+ ))));
+ $expected->addPropertyConstraint('firstName', new Choice(array(
+ 'message' => 'Must be one of %choices%',
+ 'choices' => array('A', 'B'),
+ )));
+ $expected->addGetterConstraint('lastName', new NotNull());
+ $expected->addGetterMethodConstraint('valid', 'isValid', new IsTrue());
+ $expected->addGetterConstraint('permissions', new IsTrue());
+
+ // load reflection class so that the comparison passes
+ $expected->getReflectionClass();
+
+ $this->assertEquals($expected, $metadata);
+ }
+
+ public function testLoadGroupSequenceProviderAnnotation()
+ {
+ $loader = new AnnotationLoader(new AnnotationReader());
+
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
+ $expected->setGroupSequenceProvider(true);
+ $expected->getReflectionClass();
+
+ $this->assertEquals($expected, $metadata);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/FilesLoaderTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/FilesLoaderTest.php
new file mode 100644
index 0000000..6fee7b6
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/FilesLoaderTest.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
+
+class FilesLoaderTest extends TestCase
+{
+ public function testCallsGetFileLoaderInstanceForeachPath()
+ {
+ $loader = $this->getFilesLoader($this->getFileLoader());
+ $this->assertEquals(4, $loader->getTimesCalled());
+ }
+
+ public function testCallsActualFileLoaderForMetadata()
+ {
+ $fileLoader = $this->getFileLoader();
+ $fileLoader->expects($this->exactly(4))
+ ->method('loadClassMetadata');
+ $loader = $this->getFilesLoader($fileLoader);
+ $loader->loadClassMetadata(new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'));
+ }
+
+ public function getFilesLoader(LoaderInterface $loader)
+ {
+ return $this->getMockForAbstractClass('Symfony\Component\Validator\Tests\Fixtures\FilesLoader', array(array(
+ __DIR__.'/constraint-mapping.xml',
+ __DIR__.'/constraint-mapping.yaml',
+ __DIR__.'/constraint-mapping.test',
+ __DIR__.'/constraint-mapping.txt',
+ ), $loader));
+ }
+
+ public function getFileLoader()
+ {
+ return $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/LoaderChainTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/LoaderChainTest.php
new file mode 100644
index 0000000..0d28b0a
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/LoaderChainTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
+
+class LoaderChainTest extends TestCase
+{
+ public function testAllLoadersAreCalled()
+ {
+ $metadata = new ClassMetadata('\stdClass');
+
+ $loader1 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $loader1->expects($this->once())
+ ->method('loadClassMetadata')
+ ->with($this->equalTo($metadata));
+
+ $loader2 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $loader2->expects($this->once())
+ ->method('loadClassMetadata')
+ ->with($this->equalTo($metadata));
+
+ $chain = new LoaderChain(array(
+ $loader1,
+ $loader2,
+ ));
+
+ $chain->loadClassMetadata($metadata);
+ }
+
+ public function testReturnsTrueIfAnyLoaderReturnedTrue()
+ {
+ $metadata = new ClassMetadata('\stdClass');
+
+ $loader1 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $loader1->expects($this->any())
+ ->method('loadClassMetadata')
+ ->will($this->returnValue(true));
+
+ $loader2 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $loader2->expects($this->any())
+ ->method('loadClassMetadata')
+ ->will($this->returnValue(false));
+
+ $chain = new LoaderChain(array(
+ $loader1,
+ $loader2,
+ ));
+
+ $this->assertTrue($chain->loadClassMetadata($metadata));
+ }
+
+ public function testReturnsFalseIfNoLoaderReturnedTrue()
+ {
+ $metadata = new ClassMetadata('\stdClass');
+
+ $loader1 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $loader1->expects($this->any())
+ ->method('loadClassMetadata')
+ ->will($this->returnValue(false));
+
+ $loader2 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
+ $loader2->expects($this->any())
+ ->method('loadClassMetadata')
+ ->will($this->returnValue(false));
+
+ $chain = new LoaderChain(array(
+ $loader1,
+ $loader2,
+ ));
+
+ $this->assertFalse($chain->loadClassMetadata($metadata));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php
new file mode 100644
index 0000000..069ccd3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php
@@ -0,0 +1,140 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+
+class StaticMethodLoaderTest extends TestCase
+{
+ private $errorLevel;
+
+ protected function setUp()
+ {
+ $this->errorLevel = error_reporting();
+ }
+
+ protected function tearDown()
+ {
+ error_reporting($this->errorLevel);
+ }
+
+ public function testLoadClassMetadataReturnsTrueIfSuccessful()
+ {
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity');
+
+ $this->assertTrue($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
+ {
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata('\stdClass');
+
+ $this->assertFalse($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadata()
+ {
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $this->assertEquals(StaticLoaderEntity::$invokedWith, $metadata);
+ }
+
+ public function testLoadClassMetadataDoesNotRepeatLoadWithParentClasses()
+ {
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderDocument');
+ $loader->loadClassMetadata($metadata);
+ $this->assertCount(0, $metadata->getConstraints());
+
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata(__NAMESPACE__.'\BaseStaticLoaderDocument');
+ $loader->loadClassMetadata($metadata);
+ $this->assertCount(1, $metadata->getConstraints());
+ }
+
+ public function testLoadClassMetadataIgnoresInterfaces()
+ {
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderInterface');
+
+ $loader->loadClassMetadata($metadata);
+
+ $this->assertCount(0, $metadata->getConstraints());
+ }
+
+ public function testLoadClassMetadataInAbstractClasses()
+ {
+ $loader = new StaticMethodLoader('loadMetadata');
+ $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticLoader');
+
+ $loader->loadClassMetadata($metadata);
+
+ $this->assertCount(1, $metadata->getConstraints());
+ }
+
+ public function testLoadClassMetadataIgnoresAbstractMethods()
+ {
+ // Disable error reporting, as AbstractStaticMethodLoader produces a
+ // strict standards error
+ error_reporting(0);
+
+ $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticMethodLoader');
+
+ $loader = new StaticMethodLoader('loadMetadata');
+ $loader->loadClassMetadata($metadata);
+
+ $this->assertCount(0, $metadata->getConstraints());
+ }
+}
+
+interface StaticLoaderInterface
+{
+ public static function loadMetadata(ClassMetadata $metadata);
+}
+
+abstract class AbstractStaticLoader
+{
+ public static function loadMetadata(ClassMetadata $metadata)
+ {
+ $metadata->addConstraint(new ConstraintA());
+ }
+}
+
+class StaticLoaderEntity
+{
+ public static $invokedWith = null;
+
+ public static function loadMetadata(ClassMetadata $metadata)
+ {
+ self::$invokedWith = $metadata;
+ }
+}
+
+class StaticLoaderDocument extends BaseStaticLoaderDocument
+{
+}
+
+class BaseStaticLoaderDocument
+{
+ public static function loadMetadata(ClassMetadata $metadata)
+ {
+ $metadata->addConstraint(new ConstraintA());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/XmlFileLoaderTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/XmlFileLoaderTest.php
new file mode 100644
index 0000000..100e4fa
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/XmlFileLoaderTest.php
@@ -0,0 +1,136 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\All;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\Choice;
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\Constraints\IsTrue;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Range;
+use Symfony\Component\Validator\Constraints\Regex;
+use Symfony\Component\Validator\Constraints\Traverse;
+use Symfony\Component\Validator\Exception\MappingException;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
+
+class XmlFileLoaderTest extends TestCase
+{
+ public function testLoadClassMetadataReturnsTrueIfSuccessful()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $this->assertTrue($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
+ $metadata = new ClassMetadata('\stdClass');
+
+ $this->assertFalse($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadata()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+ $expected->setGroupSequence(array('Foo', 'Entity'));
+ $expected->addConstraint(new ConstraintA());
+ $expected->addConstraint(new ConstraintB());
+ $expected->addConstraint(new Callback('validateMe'));
+ $expected->addConstraint(new Callback('validateMeStatic'));
+ $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
+ $expected->addConstraint(new Traverse(false));
+ $expected->addPropertyConstraint('firstName', new NotNull());
+ $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
+ $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
+ $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
+ $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
+ $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
+ 'foo' => array(new NotNull(), new Range(array('min' => 3))),
+ 'bar' => array(new Range(array('min' => 5))),
+ ))));
+ $expected->addPropertyConstraint('firstName', new Choice(array(
+ 'message' => 'Must be one of %choices%',
+ 'choices' => array('A', 'B'),
+ )));
+ $expected->addGetterConstraint('lastName', new NotNull());
+ $expected->addGetterConstraint('valid', new IsTrue());
+ $expected->addGetterConstraint('permissions', new IsTrue());
+
+ $this->assertEquals($expected, $metadata);
+ }
+
+ public function testLoadClassMetadataWithNonStrings()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+ $expected->addPropertyConstraint('firstName', new Regex(array('pattern' => '/^1/', 'match' => false)));
+
+ $properties = $metadata->getPropertyMetadata('firstName');
+ $constraints = $properties[0]->getConstraints();
+
+ $this->assertFalse($constraints[0]->match);
+ }
+
+ public function testLoadGroupSequenceProvider()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
+ $expected->setGroupSequenceProvider(true);
+
+ $this->assertEquals($expected, $metadata);
+ }
+
+ public function testThrowExceptionIfDocTypeIsSet()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('\Symfony\Component\Validator\Exception\MappingException');
+ $loader->loadClassMetadata($metadata);
+ }
+
+ /**
+ * @see https://github.com/symfony/symfony/pull/12158
+ */
+ public function testDoNotModifyStateIfExceptionIsThrown()
+ {
+ $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ try {
+ $loader->loadClassMetadata($metadata);
+ } catch (MappingException $e) {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('\Symfony\Component\Validator\Exception\MappingException');
+ $loader->loadClassMetadata($metadata);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/YamlFileLoaderTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/YamlFileLoaderTest.php
new file mode 100644
index 0000000..680c2cc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/YamlFileLoaderTest.php
@@ -0,0 +1,139 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping\Loader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\All;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\Choice;
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\Constraints\IsTrue;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Range;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
+
+class YamlFileLoaderTest extends TestCase
+{
+ public function testLoadClassMetadataReturnsFalseIfEmpty()
+ {
+ $loader = new YamlFileLoader(__DIR__.'/empty-mapping.yml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $this->assertFalse($loader->loadClassMetadata($metadata));
+
+ $r = new \ReflectionProperty($loader, 'classes');
+ $r->setAccessible(true);
+ $this->assertSame(array(), $r->getValue($loader));
+ }
+
+ /**
+ * @dataProvider provideInvalidYamlFiles
+ * @expectedException \InvalidArgumentException
+ */
+ public function testInvalidYamlFiles($path)
+ {
+ $loader = new YamlFileLoader(__DIR__.'/'.$path);
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $loader->loadClassMetadata($metadata);
+ }
+
+ public function provideInvalidYamlFiles()
+ {
+ return array(
+ array('nonvalid-mapping.yml'),
+ array('bad-format.yml'),
+ );
+ }
+
+ /**
+ * @see https://github.com/symfony/symfony/pull/12158
+ */
+ public function testDoNotModifyStateIfExceptionIsThrown()
+ {
+ $loader = new YamlFileLoader(__DIR__.'/nonvalid-mapping.yml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+ try {
+ $loader->loadClassMetadata($metadata);
+ } catch (\InvalidArgumentException $e) {
+ // Call again. Again an exception should be thrown
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('\InvalidArgumentException');
+ $loader->loadClassMetadata($metadata);
+ }
+ }
+
+ public function testLoadClassMetadataReturnsTrueIfSuccessful()
+ {
+ $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $this->assertTrue($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
+ {
+ $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
+ $metadata = new ClassMetadata('\stdClass');
+
+ $this->assertFalse($loader->loadClassMetadata($metadata));
+ }
+
+ public function testLoadClassMetadata()
+ {
+ $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
+ $expected->setGroupSequence(array('Foo', 'Entity'));
+ $expected->addConstraint(new ConstraintA());
+ $expected->addConstraint(new ConstraintB());
+ $expected->addConstraint(new Callback('validateMe'));
+ $expected->addConstraint(new Callback('validateMeStatic'));
+ $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
+ $expected->addPropertyConstraint('firstName', new NotNull());
+ $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
+ $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
+ $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
+ $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
+ $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
+ 'foo' => array(new NotNull(), new Range(array('min' => 3))),
+ 'bar' => array(new Range(array('min' => 5))),
+ ))));
+ $expected->addPropertyConstraint('firstName', new Choice(array(
+ 'message' => 'Must be one of %choices%',
+ 'choices' => array('A', 'B'),
+ )));
+ $expected->addGetterConstraint('lastName', new NotNull());
+ $expected->addGetterConstraint('valid', new IsTrue());
+ $expected->addGetterConstraint('permissions', new IsTrue());
+
+ $this->assertEquals($expected, $metadata);
+ }
+
+ public function testLoadGroupSequenceProvider()
+ {
+ $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
+ $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
+
+ $loader->loadClassMetadata($metadata);
+
+ $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
+ $expected->setGroupSequenceProvider(true);
+
+ $this->assertEquals($expected, $metadata);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/bad-format.yml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/bad-format.yml
new file mode 100644
index 0000000..d2b4ad2
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/bad-format.yml
@@ -0,0 +1,9 @@
+namespaces:
+ custom: Symfony\Component\Validator\Tests\Fixtures\
+
+Symfony\Component\Validator\Tests\Fixtures\Entity:
+ constraints:
+ # Custom constraint
+ - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~
+ # Custom constraint with namespaces prefix
+ - "custom:ConstraintB": ~
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml
new file mode 100644
index 0000000..dfd5edd
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" ?>
+
+<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
+
+ <namespace prefix="custom">Symfony\Component\Validator\Tests\Fixtures\</namespace>
+
+ <class name="Symfony\Component\Validator\Tests\Fixtures\Entity">
+ <property name="firstName">
+ <!-- Constraint with a Boolean -->
+ <constraint name="Regex">
+ <option name="pattern">/^1/</option>
+ <option name="match">false</option>
+ </constraint>
+ </property>
+ </class>
+
+</constraint-mapping>
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.xml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.xml
new file mode 100644
index 0000000..b1426cf
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" ?>
+
+<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
+
+ <namespace prefix="custom">Symfony\Component\Validator\Tests\Fixtures\</namespace>
+
+ <class name="Symfony\Component\Validator\Tests\Fixtures\Entity">
+
+ <group-sequence>
+ <value>Foo</value>
+ <value>Entity</value>
+ </group-sequence>
+
+ <!-- CLASS CONSTRAINTS -->
+
+ <!-- Custom constraint -->
+ <constraint name="Symfony\Component\Validator\Tests\Fixtures\ConstraintA" />
+
+ <!-- Custom constraint with namespace abbreviation-->
+ <constraint name="custom:ConstraintB" />
+
+ <!-- Callbacks -->
+ <constraint name="Callback">validateMe</constraint>
+
+ <constraint name="Callback">validateMeStatic</constraint>
+
+ <constraint name="Callback">
+ <value>Symfony\Component\Validator\Tests\Fixtures\CallbackClass</value>
+ <value>callback</value>
+ </constraint>
+
+ <!-- Traverse with boolean default option -->
+ <constraint name="Traverse">
+ false
+ </constraint>
+
+ <!-- PROPERTY CONSTRAINTS -->
+
+ <property name="firstName">
+
+ <!-- Constraint without value -->
+ <constraint name="NotNull" />
+
+ <!-- Constraint with single value -->
+ <constraint name="Range">
+ <option name="min">3</option>
+ </constraint>
+
+ <!-- Constraint with multiple values -->
+ <constraint name="Choice">
+ <value>A</value>
+ <value>B</value>
+ </constraint>
+
+ <!-- Constraint with child constraints -->
+ <constraint name="All">
+ <constraint name="NotNull" />
+ <constraint name="Range">
+ <option name="min">3</option>
+ </constraint>
+
+ </constraint>
+
+ <!-- Option with child constraints -->
+ <constraint name="All">
+ <option name="constraints">
+ <constraint name="NotNull" />
+ <constraint name="Range">
+ <option name="min">3</option>
+ </constraint>
+ </option>
+ </constraint>
+
+ <!-- Value with child constraints -->
+ <constraint name="Collection">
+ <option name="fields">
+ <value key="foo">
+ <constraint name="NotNull" />
+ <constraint name="Range">
+ <option name="min">3</option>
+ </constraint>
+ </value>
+ <value key="bar">
+ <constraint name="Range">
+ <option name="min">5</option>
+ </constraint>
+ </value>
+ </option>
+ </constraint>
+
+ <!-- Constraint with options -->
+ <constraint name="Choice">
+ <!-- Option with single value -->
+ <option name="message"> Must be one of %choices% </option>
+ <!-- Option with multiple values -->
+ <option name="choices">
+ <value>A</value>
+ <value>B</value>
+ </option>
+ </constraint>
+ </property>
+
+ <!-- GETTER CONSTRAINTS -->
+
+ <getter property="lastName">
+ <constraint name="NotNull" />
+ </getter>
+ <getter property="valid">
+ <constraint name="IsTrue" />
+ </getter>
+ <getter property="permissions">
+ <constraint name="IsTrue" />
+ </getter>
+ </class>
+
+ <class name="Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity">
+
+ <!-- GROUP SEQUENCE PROVIDER -->
+ <group-sequence-provider />
+
+ </class>
+</constraint-mapping>
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.yml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.yml
new file mode 100644
index 0000000..c39168c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/constraint-mapping.yml
@@ -0,0 +1,62 @@
+namespaces:
+ custom: Symfony\Component\Validator\Tests\Fixtures\
+
+Symfony\Component\Validator\Tests\Fixtures\Entity:
+ group_sequence:
+ - Foo
+ - Entity
+
+ constraints:
+ # Custom constraint
+ - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~
+ # Custom constraint with namespaces prefix
+ - "custom:ConstraintB": ~
+ # Callbacks
+ - Callback: validateMe
+ - Callback: validateMeStatic
+ - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback]
+
+ properties:
+ firstName:
+ # Constraint without value
+ - NotNull: ~
+ # Constraint with single value
+ - Range:
+ min: 3
+ # Constraint with multiple values
+ - Choice: [A, B]
+ # Constraint with child constraints
+ - All:
+ - NotNull: ~
+ - Range:
+ min: 3
+ # Option with child constraints
+ - All:
+ constraints:
+ - NotNull: ~
+ - Range:
+ min: 3
+ # Value with child constraints
+ - Collection:
+ fields:
+ foo:
+ - NotNull: ~
+ - Range:
+ min: 3
+ bar:
+ - Range:
+ min: 5
+ # Constraint with options
+ - Choice: { choices: [A, B], message: Must be one of %choices% }
+ dummy:
+
+ getters:
+ lastName:
+ - NotNull: ~
+ valid:
+ - "IsTrue": ~
+ permissions:
+ - "IsTrue": ~
+
+Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity:
+ group_sequence_provider: true
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/empty-mapping.yml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/empty-mapping.yml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/empty-mapping.yml
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/nonvalid-mapping.yml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/nonvalid-mapping.yml
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/nonvalid-mapping.yml
@@ -0,0 +1 @@
+foo
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/withdoctype.xml b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/withdoctype.xml
new file mode 100644
index 0000000..0beacc3
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/Loader/withdoctype.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<!DOCTYPE foo>
+<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
+ <class name="Symfony\Component\Validator\Tests\Fixtures\Entity" />
+</constraint-mapping>
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/MemberMetadataTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/MemberMetadataTest.php
new file mode 100644
index 0000000..f0726c8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/MemberMetadataTest.php
@@ -0,0 +1,120 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\Mapping\MemberMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
+use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
+
+class MemberMetadataTest extends TestCase
+{
+ protected $metadata;
+
+ protected function setUp()
+ {
+ $this->metadata = new TestMemberMetadata(
+ 'Symfony\Component\Validator\Tests\Fixtures\Entity',
+ 'getLastName',
+ 'lastName'
+ );
+ }
+
+ protected function tearDown()
+ {
+ $this->metadata = null;
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyAddValidSetsMemberToCascaded()
+ {
+ $result = $this->metadata->addConstraint(new Valid());
+
+ $this->assertEquals(array(), $this->metadata->getConstraints());
+ $this->assertEquals($result, $this->metadata);
+ $this->assertTrue($this->metadata->isCascaded());
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacyAddOtherConstraintDoesNotSetMemberToCascaded()
+ {
+ $result = $this->metadata->addConstraint($constraint = new ConstraintA());
+
+ $this->assertEquals(array($constraint), $this->metadata->getConstraints());
+ $this->assertEquals($result, $this->metadata);
+ $this->assertFalse($this->metadata->isCascaded());
+ }
+
+ public function testAddConstraintRequiresClassConstraints()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ConstraintDefinitionException');
+
+ $this->metadata->addConstraint(new ClassConstraint());
+ }
+
+ public function testSerialize()
+ {
+ $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
+ $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));
+
+ $metadata = unserialize(serialize($this->metadata));
+
+ $this->assertEquals($this->metadata, $metadata);
+ }
+
+ public function testSerializeCollectionCascaded()
+ {
+ $this->metadata->addConstraint(new Valid(array('traverse' => true)));
+
+ $metadata = unserialize(serialize($this->metadata));
+
+ $this->assertEquals($this->metadata, $metadata);
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testLegacySerializeCollectionCascadedDeeply()
+ {
+ $this->metadata->addConstraint(new Valid(array('traverse' => true)));
+
+ $metadata = unserialize(serialize($this->metadata));
+
+ $this->assertEquals($this->metadata, $metadata);
+ }
+
+ public function testSerializeCollectionNotCascaded()
+ {
+ $this->metadata->addConstraint(new Valid(array('traverse' => false)));
+
+ $metadata = unserialize(serialize($this->metadata));
+
+ $this->assertEquals($this->metadata, $metadata);
+ }
+}
+
+class TestMemberMetadata extends MemberMetadata
+{
+ public function getPropertyValue($object)
+ {
+ }
+
+ protected function newReflectionMember($object)
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Mapping/PropertyMetadataTest.php b/public/system/storage/vendor/symfony/validator/Tests/Mapping/PropertyMetadataTest.php
new file mode 100644
index 0000000..9fea435
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Mapping/PropertyMetadataTest.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Mapping;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Mapping\PropertyMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+
+class PropertyMetadataTest extends TestCase
+{
+ const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
+ const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
+
+ public function testInvalidPropertyName()
+ {
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ValidatorException');
+
+ new PropertyMetadata(self::CLASSNAME, 'foobar');
+ }
+
+ public function testGetPropertyValueFromPrivateProperty()
+ {
+ $entity = new Entity('foobar');
+ $metadata = new PropertyMetadata(self::CLASSNAME, 'internal');
+
+ $this->assertEquals('foobar', $metadata->getPropertyValue($entity));
+ }
+
+ public function testGetPropertyValueFromOverriddenPrivateProperty()
+ {
+ $entity = new Entity('foobar');
+ $metadata = new PropertyMetadata(self::PARENTCLASS, 'data');
+
+ $this->assertTrue($metadata->isPublic($entity));
+ $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
+ }
+
+ public function testGetPropertyValueFromRemovedProperty()
+ {
+ $entity = new Entity('foobar');
+ $metadata = new PropertyMetadata(self::CLASSNAME, 'internal');
+ $metadata->name = 'test';
+
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\ValidatorException');
+ $metadata->getPropertyValue($entity);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Resources/TranslationFilesTest.php b/public/system/storage/vendor/symfony/validator/Tests/Resources/TranslationFilesTest.php
new file mode 100644
index 0000000..64b3f78
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Resources/TranslationFilesTest.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Resources;
+
+use PHPUnit\Framework\TestCase;
+
+class TranslationFilesTest extends TestCase
+{
+ /**
+ * @dataProvider provideTranslationFiles
+ */
+ public function testTranslationFileIsValid($filePath)
+ {
+ if (class_exists('PHPUnit_Util_XML')) {
+ \PHPUnit_Util_XML::loadfile($filePath, false, false, true);
+ } else {
+ \PHPUnit\Util\XML::loadfile($filePath, false, false, true);
+ }
+
+ $this->addToAssertionCount(1);
+ }
+
+ public function provideTranslationFiles()
+ {
+ return array_map(
+ function ($filePath) { return (array) $filePath; },
+ glob(\dirname(\dirname(__DIR__)).'/Resources/translations/*.xlf')
+ );
+ }
+
+ public function testNorwegianAlias()
+ {
+ $this->assertFileEquals(
+ \dirname(\dirname(__DIR__)).'/Resources/translations/validators.nb.xlf',
+ \dirname(\dirname(__DIR__)).'/Resources/translations/validators.no.xlf',
+ 'The NO locale should be an alias for the NB variant of the Norwegian language.'
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Util/PropertyPathTest.php b/public/system/storage/vendor/symfony/validator/Tests/Util/PropertyPathTest.php
new file mode 100644
index 0000000..235e178
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Util/PropertyPathTest.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Util;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Util\PropertyPath;
+
+class PropertyPathTest extends TestCase
+{
+ /**
+ * @dataProvider provideAppendPaths
+ */
+ public function testAppend($basePath, $subPath, $expectedPath, $message)
+ {
+ $this->assertSame($expectedPath, PropertyPath::append($basePath, $subPath), $message);
+ }
+
+ public function provideAppendPaths()
+ {
+ return array(
+ array('foo', '', 'foo', 'It returns the basePath if subPath is empty'),
+ array('', 'bar', 'bar', 'It returns the subPath if basePath is empty'),
+ array('foo', 'bar', 'foo.bar', 'It append the subPath to the basePath'),
+ array('foo', '[bar]', 'foo[bar]', 'It does not include the dot separator if subPath uses the array notation'),
+ array('0', 'bar', '0.bar', 'Leading zeros are kept.'),
+ );
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Validator/Abstract2Dot5ApiTest.php b/public/system/storage/vendor/symfony/validator/Tests/Validator/Abstract2Dot5ApiTest.php
new file mode 100644
index 0000000..0394431
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Validator/Abstract2Dot5ApiTest.php
@@ -0,0 +1,742 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Validator;
+
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\Collection;
+use Symfony\Component\Validator\Constraints\Expression;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\Constraints\NotNull;
+use Symfony\Component\Validator\Constraints\Traverse;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\ConstraintViolationInterface;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
+use Symfony\Component\Validator\Tests\Fixtures\FakeClassMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\Reference;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * Verifies that a validator satisfies the API of Symfony 2.5+.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class Abstract2Dot5ApiTest extends AbstractValidatorTest
+{
+ /**
+ * @var ValidatorInterface
+ */
+ protected $validator;
+
+ /**
+ * @return ValidatorInterface
+ */
+ abstract protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array());
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->validator = $this->createValidator($this->metadataFactory);
+ }
+
+ protected function validate($value, $constraints = null, $groups = null)
+ {
+ return $this->validator->validate($value, $constraints, $groups);
+ }
+
+ protected function validateProperty($object, $propertyName, $groups = null)
+ {
+ return $this->validator->validateProperty($object, $propertyName, $groups);
+ }
+
+ protected function validatePropertyValue($object, $propertyName, $value, $groups = null)
+ {
+ return $this->validator->validatePropertyValue($object, $propertyName, $value, $groups);
+ }
+
+ public function testValidateConstraintWithoutGroup()
+ {
+ $violations = $this->validator->validate(null, new NotNull());
+
+ $this->assertCount(1, $violations);
+ }
+
+ public function testValidateWithEmptyArrayAsConstraint()
+ {
+ $violations = $this->validator->validate('value', array());
+ $this->assertCount(0, $violations);
+ }
+
+ public function testGroupSequenceAbortsAfterFailedGroup()
+ {
+ $entity = new Entity();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message 1');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message 2');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => function () {},
+ 'groups' => 'Group 1',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group 2',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 3',
+ )));
+
+ $sequence = new GroupSequence(array('Group 1', 'Group 2', 'Group 3'));
+ $violations = $this->validator->validate($entity, new Valid(), $sequence);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message 1', $violations[0]->getMessage());
+ }
+
+ public function testGroupSequenceIncludesReferences()
+ {
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Reference violation 1');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Reference violation 2');
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group 1',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 2',
+ )));
+
+ $sequence = new GroupSequence(array('Group 1', 'Entity'));
+ $violations = $this->validator->validate($entity, new Valid(), $sequence);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Reference violation 1', $violations[0]->getMessage());
+ }
+
+ public function testValidateInSeparateContext()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $violations = $context
+ ->getValidator()
+ // Since the validator is not context aware, the group must
+ // be passed explicitly
+ ->validate($value->reference, new Valid(), 'Group')
+ ;
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $test->assertCount(1, $violations);
+ $test->assertSame('Message value', $violations[0]->getMessage());
+ $test->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $test->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $test->assertSame('', $violations[0]->getPropertyPath());
+ // The root is different as we're in a new context
+ $test->assertSame($entity->reference, $violations[0]->getRoot());
+ $test->assertSame($entity->reference, $violations[0]->getInvalidValue());
+ $test->assertNull($violations[0]->getPlural());
+ $test->assertNull($violations[0]->getCode());
+
+ // Verify that this method is called
+ $context->addViolation('Separate violation');
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity->reference, $context->getRoot());
+ $test->assertSame($entity->reference, $context->getValue());
+ $test->assertSame($entity->reference, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validator->validate($entity, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $test->assertSame('Separate violation', $violations[0]->getMessage());
+ }
+
+ public function testValidateInContext()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test) {
+ $previousValue = $context->getValue();
+ $previousObject = $context->getObject();
+ $previousMetadata = $context->getMetadata();
+ $previousPath = $context->getPropertyPath();
+ $previousGroup = $context->getGroup();
+
+ $context
+ ->getValidator()
+ ->inContext($context)
+ ->atPath('subpath')
+ ->validate($value->reference)
+ ;
+
+ // context changes shouldn't leak out of the validate() call
+ $test->assertSame($previousValue, $context->getValue());
+ $test->assertSame($previousObject, $context->getObject());
+ $test->assertSame($previousMetadata, $context->getMetadata());
+ $test->assertSame($previousPath, $context->getPropertyPath());
+ $test->assertSame($previousGroup, $context->getGroup());
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('subpath', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference, $context->getValue());
+ $test->assertSame($entity->reference, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validator->validate($entity, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('subpath', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testValidateArrayInContext()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test) {
+ $previousValue = $context->getValue();
+ $previousObject = $context->getObject();
+ $previousMetadata = $context->getMetadata();
+ $previousPath = $context->getPropertyPath();
+ $previousGroup = $context->getGroup();
+
+ $context
+ ->getValidator()
+ ->inContext($context)
+ ->atPath('subpath')
+ ->validate(array('key' => $value->reference))
+ ;
+
+ // context changes shouldn't leak out of the validate() call
+ $test->assertSame($previousValue, $context->getValue());
+ $test->assertSame($previousObject, $context->getObject());
+ $test->assertSame($previousMetadata, $context->getMetadata());
+ $test->assertSame($previousPath, $context->getPropertyPath());
+ $test->assertSame($previousGroup, $context->getGroup());
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('subpath[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference, $context->getValue());
+ $test->assertSame($entity->reference, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validator->validate($entity, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('subpath[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testTraverseTraversableByDefault()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array('key' => $entity));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity, $traversable) {
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->metadata, $context->getMetadata());
+ $test->assertSame($traversable, $context->getRoot());
+ $test->assertSame($entity, $context->getValue());
+ $test->assertSame($entity, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator'));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($traversable, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($traversable, $violations[0]->getRoot());
+ $this->assertSame($entity, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testTraversalEnabledOnClass()
+ {
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array('key' => $entity));
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $traversableMetadata = new ClassMetadata('ArrayIterator');
+ $traversableMetadata->addConstraint(new Traverse(true));
+
+ $this->metadataFactory->addMetadata($traversableMetadata);
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($traversable, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ public function testTraversalDisabledOnClass()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array('key' => $entity));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test) {
+ $test->fail('Should not be called');
+ };
+
+ $traversableMetadata = new ClassMetadata('ArrayIterator');
+ $traversableMetadata->addConstraint(new Traverse(false));
+
+ $this->metadataFactory->addMetadata($traversableMetadata);
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($traversable, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testExpectTraversableIfTraversalEnabledOnClass()
+ {
+ $entity = new Entity();
+
+ $this->metadata->addConstraint(new Traverse(true));
+
+ $this->validator->validate($entity);
+ }
+
+ public function testReferenceTraversalDisabledOnClass()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator(array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test) {
+ $test->fail('Should not be called');
+ };
+
+ $traversableMetadata = new ClassMetadata('ArrayIterator');
+ $traversableMetadata->addConstraint(new Traverse(false));
+
+ $this->metadataFactory->addMetadata($traversableMetadata);
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $violations = $this->validate($entity, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ public function testReferenceTraversalEnabledOnReferenceDisabledOnClass()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator(array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test) {
+ $test->fail('Should not be called');
+ };
+
+ $traversableMetadata = new ClassMetadata('ArrayIterator');
+ $traversableMetadata->addConstraint(new Traverse(false));
+
+ $this->metadataFactory->addMetadata($traversableMetadata);
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => true,
+ )));
+
+ $violations = $this->validate($entity, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ public function testReferenceTraversalDisabledOnReferenceEnabledOnClass()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator(array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test) {
+ $test->fail('Should not be called');
+ };
+
+ $traversableMetadata = new ClassMetadata('ArrayIterator');
+ $traversableMetadata->addConstraint(new Traverse(true));
+
+ $this->metadataFactory->addMetadata($traversableMetadata);
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => false,
+ )));
+
+ $violations = $this->validate($entity, new Valid(), 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ public function testAddCustomizedViolation()
+ {
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->buildViolation('Message %param%')
+ ->setParameter('%param%', 'value')
+ ->setInvalidValue('Invalid value')
+ ->setPlural(2)
+ ->setCode(42)
+ ->addViolation();
+ };
+
+ $this->metadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validator->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Invalid value', $violations[0]->getInvalidValue());
+ $this->assertSame(2, $violations[0]->getPlural());
+ $this->assertSame(42, $violations[0]->getCode());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnsupportedMetadataException
+ * @group legacy
+ */
+ public function testMetadataMustImplementClassMetadataInterface()
+ {
+ $entity = new Entity();
+
+ $metadata = $this->getMockBuilder('Symfony\Component\Validator\Tests\Fixtures\LegacyClassMetadata')->getMock();
+ $metadata->expects($this->any())
+ ->method('getClassName')
+ ->will($this->returnValue(\get_class($entity)));
+
+ $this->metadataFactory->addMetadata($metadata);
+
+ $this->validator->validate($entity);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnsupportedMetadataException
+ * @group legacy
+ */
+ public function testReferenceMetadataMustImplementClassMetadataInterface()
+ {
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $metadata = $this->getMockBuilder('Symfony\Component\Validator\Tests\Fixtures\LegacyClassMetadata')->getMock();
+ $metadata->expects($this->any())
+ ->method('getClassName')
+ ->will($this->returnValue(\get_class($entity->reference)));
+
+ $this->metadataFactory->addMetadata($metadata);
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $this->validator->validate($entity);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\UnsupportedMetadataException
+ * @group legacy
+ */
+ public function testLegacyPropertyMetadataMustImplementPropertyMetadataInterface()
+ {
+ $entity = new Entity();
+
+ // Legacy interface
+ $propertyMetadata = $this->getMockBuilder('Symfony\Component\Validator\MetadataInterface')->getMock();
+ $metadata = new FakeClassMetadata(\get_class($entity));
+ $metadata->addCustomPropertyMetadata('firstName', $propertyMetadata);
+
+ $this->metadataFactory->addMetadata($metadata);
+
+ $this->validator->validate($entity);
+ }
+
+ public function testNoDuplicateValidationIfClassConstraintInMultipleGroups()
+ {
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => array('Group 1', 'Group 2'),
+ )));
+
+ $violations = $this->validator->validate($entity, new Valid(), array('Group 1', 'Group 2'));
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ public function testNoDuplicateValidationIfPropertyConstraintInMultipleGroups()
+ {
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $this->metadata->addPropertyConstraint('firstName', new Callback(array(
+ 'callback' => $callback,
+ 'groups' => array('Group 1', 'Group 2'),
+ )));
+
+ $violations = $this->validator->validate($entity, new Valid(), array('Group 1', 'Group 2'));
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\RuntimeException
+ */
+ public function testValidateFailsIfNoConstraintsAndNoObjectOrArray()
+ {
+ $this->validate('Foobar');
+ }
+
+ public function testAccessCurrentObject()
+ {
+ $test = $this;
+ $called = false;
+ $entity = new Entity();
+ $entity->firstName = 'Bernhard';
+ $entity->data = array('firstName' => 'Bernhard');
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity, &$called) {
+ $called = true;
+ $test->assertSame($entity, $context->getObject());
+ };
+
+ $this->metadata->addConstraint(new Callback($callback));
+ $this->metadata->addPropertyConstraint('firstName', new Callback($callback));
+ $this->metadata->addPropertyConstraint('data', new Collection(array('firstName' => new Expression('value == this.firstName'))));
+
+ $this->validator->validate($entity);
+
+ $this->assertTrue($called);
+ }
+
+ public function testInitializeObjectsOnFirstValidation()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->initialized = false;
+
+ // prepare initializers that set "initialized" to true
+ $initializer1 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock();
+ $initializer2 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock();
+
+ $initializer1->expects($this->once())
+ ->method('initialize')
+ ->with($entity)
+ ->will($this->returnCallback(function ($object) {
+ $object->initialized = true;
+ }));
+
+ $initializer2->expects($this->once())
+ ->method('initialize')
+ ->with($entity);
+
+ $this->validator = $this->createValidator($this->metadataFactory, array(
+ $initializer1,
+ $initializer2,
+ ));
+
+ // prepare constraint which
+ // * checks that "initialized" is set to true
+ // * validates the object again
+ $callback = function ($object, ExecutionContextInterface $context) use ($test) {
+ $test->assertTrue($object->initialized);
+
+ // validate again in same group
+ $validator = $context->getValidator()->inContext($context);
+
+ $validator->validate($object);
+
+ // validate again in other group
+ $validator->validate($object, null, 'SomeGroup');
+ };
+
+ $this->metadata->addConstraint(new Callback($callback));
+
+ $this->validate($entity);
+
+ $this->assertTrue($entity->initialized);
+ }
+
+ public function testPassConstraintToViolation()
+ {
+ $constraint = new FailingConstraint();
+ $violations = $this->validate('Foobar', $constraint);
+
+ $this->assertCount(1, $violations);
+ $this->assertSame($constraint, $violations[0]->getConstraint());
+ }
+
+ public function testCollectionConstraitViolationHasCorrectContext()
+ {
+ $data = array(
+ 'foo' => 'fooValue',
+ );
+
+ // Missing field must not be the first in the collection validation
+ $constraint = new Collection(array(
+ 'foo' => new NotNull(),
+ 'bar' => new NotNull(),
+ ));
+
+ $violations = $this->validate($data, $constraint);
+
+ $this->assertCount(1, $violations);
+ $this->assertSame($constraint, $violations[0]->getConstraint());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractLegacyApiTest.php b/public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractLegacyApiTest.php
new file mode 100644
index 0000000..4734632
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractLegacyApiTest.php
@@ -0,0 +1,313 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Validator;
+
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\ConstraintViolationInterface;
+use Symfony\Component\Validator\ExecutionContextInterface;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+use Symfony\Component\Validator\Tests\Fixtures\Reference;
+use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface;
+
+/**
+ * Verifies that a validator satisfies the API of Symfony < 2.5.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ * @group legacy
+ */
+abstract class AbstractLegacyApiTest extends AbstractValidatorTest
+{
+ /**
+ * @var LegacyValidatorInterface
+ */
+ protected $validator;
+
+ /**
+ * @param MetadataFactoryInterface $metadataFactory
+ *
+ * @return LegacyValidatorInterface
+ */
+ abstract protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array());
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->validator = $this->createValidator($this->metadataFactory);
+ }
+
+ protected function validate($value, $constraints = null, $groups = null)
+ {
+ if (null === $constraints) {
+ $constraints = new Valid();
+ }
+
+ if ($constraints instanceof Valid) {
+ return $this->validator->validate($value, $groups, $constraints->traverse, $constraints->deep);
+ }
+
+ return $this->validator->validateValue($value, $constraints, $groups);
+ }
+
+ protected function validateProperty($object, $propertyName, $groups = null)
+ {
+ return $this->validator->validateProperty($object, $propertyName, $groups);
+ }
+
+ protected function validatePropertyValue($object, $propertyName, $value, $groups = null)
+ {
+ return $this->validator->validatePropertyValue($object, $propertyName, $value, $groups);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
+ */
+ public function testTraversableTraverseDisabled()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array('key' => $entity));
+
+ $callback = function () use ($test) {
+ $test->fail('Should not be called');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $this->validator->validate($traversable, 'Group');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
+ */
+ public function testRecursiveTraversableRecursiveTraversalDisabled()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array(
+ 2 => new \ArrayIterator(array('key' => $entity)),
+ ));
+
+ $callback = function () use ($test) {
+ $test->fail('Should not be called');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $this->validator->validate($traversable, 'Group');
+ }
+
+ public function testValidateInContext()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test) {
+ $previousValue = $context->getValue();
+ $previousMetadata = $context->getMetadata();
+ $previousPath = $context->getPropertyPath();
+ $previousGroup = $context->getGroup();
+
+ $context->validate($value->reference, 'subpath');
+
+ // context changes shouldn't leak out of the validate() call
+ $test->assertSame($previousValue, $context->getValue());
+ $test->assertSame($previousMetadata, $context->getMetadata());
+ $test->assertSame($previousPath, $context->getPropertyPath());
+ $test->assertSame($previousGroup, $context->getGroup());
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('subpath', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($test->metadataFactory, $context->getMetadataFactory());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference, $context->getValue());
+ $test->assertSame($entity->reference, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validator->validate($entity, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('subpath', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testValidateArrayInContext()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test) {
+ $previousValue = $context->getValue();
+ $previousMetadata = $context->getMetadata();
+ $previousPath = $context->getPropertyPath();
+ $previousGroup = $context->getGroup();
+
+ $context->validate(array('key' => $value->reference), 'subpath');
+
+ // context changes shouldn't leak out of the validate() call
+ $test->assertSame($previousValue, $context->getValue());
+ $test->assertSame($previousMetadata, $context->getMetadata());
+ $test->assertSame($previousPath, $context->getPropertyPath());
+ $test->assertSame($previousGroup, $context->getGroup());
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('subpath[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($test->metadataFactory, $context->getMetadataFactory());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference, $context->getValue());
+ $test->assertSame($entity->reference, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validator->validate($entity, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('subpath[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testAddCustomizedViolation()
+ {
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation(
+ 'Message %param%',
+ array('%param%' => 'value'),
+ 'Invalid value',
+ 2,
+ 'Code'
+ );
+ };
+
+ $this->metadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validator->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Invalid value', $violations[0]->getInvalidValue());
+ $this->assertSame(2, $violations[0]->getPlural());
+ $this->assertSame('Code', $violations[0]->getCode());
+ }
+
+ public function testInitializeObjectsOnFirstValidation()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->initialized = false;
+
+ // prepare initializers that set "initialized" to true
+ $initializer1 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock();
+ $initializer2 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock();
+
+ $initializer1->expects($this->once())
+ ->method('initialize')
+ ->with($entity)
+ ->will($this->returnCallback(function ($object) {
+ $object->initialized = true;
+ }));
+
+ $initializer2->expects($this->once())
+ ->method('initialize')
+ ->with($entity);
+
+ $this->validator = $this->createValidator($this->metadataFactory, array(
+ $initializer1,
+ $initializer2,
+ ));
+
+ // prepare constraint which
+ // * checks that "initialized" is set to true
+ // * validates the object again
+ $callback = function ($object, ExecutionContextInterface $context) use ($test) {
+ $test->assertTrue($object->initialized);
+
+ // validate again in same group
+ $context->validate($object);
+
+ // validate again in other group
+ $context->validate($object, '', 'SomeGroup');
+ };
+
+ $this->metadata->addConstraint(new Callback($callback));
+
+ $this->validate($entity);
+
+ $this->assertTrue($entity->initialized);
+ }
+
+ public function testGetMetadataFactory()
+ {
+ $this->assertSame($this->metadataFactory, $this->validator->getMetadataFactory());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractValidatorTest.php b/public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractValidatorTest.php
new file mode 100644
index 0000000..8dd9adc
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Validator/AbstractValidatorTest.php
@@ -0,0 +1,1284 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Validator;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\Constraints\Callback;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\ConstraintViolationInterface;
+use Symfony\Component\Validator\ExecutionContextInterface;
+use Symfony\Component\Validator\Mapping\ClassMetadata;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
+use Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity;
+use Symfony\Component\Validator\Tests\Fixtures\Reference;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class AbstractValidatorTest extends TestCase
+{
+ const ENTITY_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
+
+ const REFERENCE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\Reference';
+
+ /**
+ * @var FakeMetadataFactory
+ */
+ public $metadataFactory;
+
+ /**
+ * @var ClassMetadata
+ */
+ public $metadata;
+
+ /**
+ * @var ClassMetadata
+ */
+ public $referenceMetadata;
+
+ protected function setUp()
+ {
+ $this->metadataFactory = new FakeMetadataFactory();
+ $this->metadata = new ClassMetadata(self::ENTITY_CLASS);
+ $this->referenceMetadata = new ClassMetadata(self::REFERENCE_CLASS);
+ $this->metadataFactory->addMetadata($this->metadata);
+ $this->metadataFactory->addMetadata($this->referenceMetadata);
+ }
+
+ protected function tearDown()
+ {
+ $this->metadataFactory = null;
+ $this->metadata = null;
+ $this->referenceMetadata = null;
+ }
+
+ abstract protected function validate($value, $constraints = null, $groups = null);
+
+ abstract protected function validateProperty($object, $propertyName, $groups = null);
+
+ abstract protected function validatePropertyValue($object, $propertyName, $value, $groups = null);
+
+ public function testValidate()
+ {
+ $test = $this;
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test) {
+ $test->assertNull($context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame('Bernhard', $context->getRoot());
+ $test->assertSame('Bernhard', $context->getValue());
+ $test->assertSame('Bernhard', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $constraint = new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ ));
+
+ $violations = $this->validate('Bernhard', $constraint, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('', $violations[0]->getPropertyPath());
+ $this->assertSame('Bernhard', $violations[0]->getRoot());
+ $this->assertSame('Bernhard', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testClassConstraint()
+ {
+ $test = $this;
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->metadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity, $context->getValue());
+ $test->assertSame($entity, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testPropertyConstraint()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->firstName = 'Bernhard';
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $propertyMetadatas = $test->metadata->getPropertyMetadata('firstName');
+
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertSame('firstName', $context->getPropertyName());
+ $test->assertSame('firstName', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame('Bernhard', $context->getValue());
+ $test->assertSame('Bernhard', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('firstName', new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('firstName', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Bernhard', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testGetterConstraint()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->setLastName('Schussek');
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $propertyMetadatas = $test->metadata->getPropertyMetadata('lastName');
+
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertSame('lastName', $context->getPropertyName());
+ $test->assertSame('lastName', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame('Schussek', $context->getValue());
+ $test->assertSame('Schussek', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addGetterConstraint('lastName', new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('lastName', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Schussek', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testArray()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $array = array('key' => $entity);
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity, $array) {
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->metadata, $context->getMetadata());
+ $test->assertSame($array, $context->getRoot());
+ $test->assertSame($entity, $context->getValue());
+ $test->assertSame($entity, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($array, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($array, $violations[0]->getRoot());
+ $this->assertSame($entity, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testRecursiveArray()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $array = array(2 => array('key' => $entity));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity, $array) {
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('[2][key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->metadata, $context->getMetadata());
+ $test->assertSame($array, $context->getRoot());
+ $test->assertSame($entity, $context->getValue());
+ $test->assertSame($entity, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($array, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('[2][key]', $violations[0]->getPropertyPath());
+ $this->assertSame($array, $violations[0]->getRoot());
+ $this->assertSame($entity, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testTraversable()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array('key' => $entity));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity, $traversable) {
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->metadata, $context->getMetadata());
+ $test->assertSame($traversable, $context->getRoot());
+ $test->assertSame($entity, $context->getValue());
+ $test->assertSame($entity, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($traversable, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($traversable, $violations[0]->getRoot());
+ $this->assertSame($entity, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testRecursiveTraversable()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $traversable = new \ArrayIterator(array(
+ 2 => new \ArrayIterator(array('key' => $entity)),
+ ));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity, $traversable) {
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('[2][key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->metadata, $context->getMetadata());
+ $test->assertSame($traversable, $context->getRoot());
+ $test->assertSame($entity, $context->getValue());
+ $test->assertSame($entity, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($traversable, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('[2][key]', $violations[0]->getPropertyPath());
+ $this->assertSame($traversable, $violations[0]->getRoot());
+ $this->assertSame($entity, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testReferenceClassConstraint()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('reference', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference, $context->getValue());
+ $test->assertSame($entity->reference, $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference, $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testReferencePropertyConstraint()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+ $entity->reference->value = 'Foobar';
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $propertyMetadatas = $test->referenceMetadata->getPropertyMetadata('value');
+
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertSame('value', $context->getPropertyName());
+ $test->assertSame('reference.value', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame('Foobar', $context->getValue());
+ $test->assertSame('Foobar', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addPropertyConstraint('value', new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference.value', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Foobar', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testReferenceGetterConstraint()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new Reference();
+ $entity->reference->setPrivateValue('Bamboo');
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $propertyMetadatas = $test->referenceMetadata->getPropertyMetadata('privateValue');
+
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertSame('privateValue', $context->getPropertyName());
+ $test->assertSame('reference.privateValue', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame('Bamboo', $context->getValue());
+ $test->assertSame('Bamboo', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addPropertyConstraint('privateValue', new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference.privateValue', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Bamboo', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testsIgnoreNullReference()
+ {
+ $entity = new Entity();
+ $entity->reference = null;
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
+ */
+ public function testFailOnScalarReferences()
+ {
+ $entity = new Entity();
+ $entity->reference = 'string';
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $this->validate($entity);
+ }
+
+ public function testArrayReference()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = array('key' => new Reference());
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('reference[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference['key'], $context->getValue());
+ $test->assertSame($entity->reference['key'], $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference['key'], $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ // https://github.com/symfony/symfony/issues/6246
+ public function testRecursiveArrayReference()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = array(2 => array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('reference[2][key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference[2]['key'], $context->getValue());
+ $test->assertSame($entity->reference[2]['key'], $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference[2][key]', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference[2]['key'], $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testArrayTraversalCannotBeDisabled()
+ {
+ $entity = new Entity();
+ $entity->reference = array('key' => new Reference());
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => false,
+ )));
+ $this->referenceMetadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ public function testRecursiveArrayTraversalCannotBeDisabled()
+ {
+ $entity = new Entity();
+ $entity->reference = array(2 => array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => false,
+ )));
+ $this->referenceMetadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ public function testIgnoreScalarsDuringArrayTraversal()
+ {
+ $entity = new Entity();
+ $entity->reference = array('string', 1234);
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ public function testIgnoreNullDuringArrayTraversal()
+ {
+ $entity = new Entity();
+ $entity->reference = array(null);
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ public function testTraversableReference()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator(array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('reference[key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference['key'], $context->getValue());
+ $test->assertSame($entity->reference['key'], $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference[key]', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference['key'], $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testDisableTraversableTraversal()
+ {
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator(array('key' => new Reference()));
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator'));
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => false,
+ )));
+ $this->referenceMetadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(0, $violations);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
+ */
+ public function testMetadataMustExistIfTraversalIsDisabled()
+ {
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator();
+
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => false,
+ )));
+
+ $this->validate($entity);
+ }
+
+ public function testEnableRecursiveTraversableTraversal()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->reference = new \ArrayIterator(array(
+ 2 => new \ArrayIterator(array('key' => new Reference())),
+ ));
+
+ $callback = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $test->assertSame($test::REFERENCE_CLASS, $context->getClassName());
+ $test->assertNull($context->getPropertyName());
+ $test->assertSame('reference[2][key]', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($test->referenceMetadata, $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame($entity->reference[2]['key'], $context->getValue());
+ $test->assertSame($entity->reference[2]['key'], $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid(array(
+ 'traverse' => true,
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('reference[2][key]', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame($entity->reference[2]['key'], $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testValidateProperty()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->firstName = 'Bernhard';
+ $entity->setLastName('Schussek');
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $propertyMetadatas = $test->metadata->getPropertyMetadata('firstName');
+
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertSame('firstName', $context->getPropertyName());
+ $test->assertSame('firstName', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame('Bernhard', $context->getValue());
+ $test->assertSame('Bernhard', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Other violation');
+ };
+
+ $this->metadata->addPropertyConstraint('firstName', new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->metadata->addPropertyConstraint('lastName', new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validateProperty($entity, 'firstName', 'Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('firstName', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Bernhard', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ /**
+ * Cannot be UnsupportedMetadataException for BC with Symfony < 2.5.
+ *
+ * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
+ * @group legacy
+ */
+ public function testLegacyValidatePropertyFailsIfPropertiesNotSupported()
+ {
+ // $metadata does not implement PropertyMetadataContainerInterface
+ $metadata = $this->getMockBuilder('Symfony\Component\Validator\MetadataInterface')->getMock();
+
+ $this->metadataFactory->addMetadataForValue('VALUE', $metadata);
+
+ $this->validateProperty('VALUE', 'someProperty');
+ }
+
+ /**
+ * https://github.com/symfony/symfony/issues/11604.
+ */
+ public function testValidatePropertyWithoutConstraints()
+ {
+ $entity = new Entity();
+ $violations = $this->validateProperty($entity, 'lastName');
+
+ $this->assertCount(0, $violations, '->validateProperty() returns no violations if no constraints have been configured for the property being validated');
+ }
+
+ public function testValidatePropertyValue()
+ {
+ $test = $this;
+ $entity = new Entity();
+ $entity->setLastName('Schussek');
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test, $entity) {
+ $propertyMetadatas = $test->metadata->getPropertyMetadata('firstName');
+
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertSame('firstName', $context->getPropertyName());
+ $test->assertSame('firstName', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame($entity, $context->getRoot());
+ $test->assertSame('Bernhard', $context->getValue());
+ $test->assertSame('Bernhard', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Other violation');
+ };
+
+ $this->metadata->addPropertyConstraint('firstName', new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->metadata->addPropertyConstraint('lastName', new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validatePropertyValue(
+ $entity,
+ 'firstName',
+ 'Bernhard',
+ 'Group'
+ );
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('firstName', $violations[0]->getPropertyPath());
+ $this->assertSame($entity, $violations[0]->getRoot());
+ $this->assertSame('Bernhard', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ public function testValidatePropertyValueWithClassName()
+ {
+ $test = $this;
+
+ $callback1 = function ($value, ExecutionContextInterface $context) use ($test) {
+ $propertyMetadatas = $test->metadata->getPropertyMetadata('firstName');
+
+ $test->assertSame($test::ENTITY_CLASS, $context->getClassName());
+ $test->assertSame('firstName', $context->getPropertyName());
+ $test->assertSame('', $context->getPropertyPath());
+ $test->assertSame('Group', $context->getGroup());
+ $test->assertSame($propertyMetadatas[0], $context->getMetadata());
+ $test->assertSame('Bernhard', $context->getRoot());
+ $test->assertSame('Bernhard', $context->getValue());
+ $test->assertSame('Bernhard', $value);
+
+ $context->addViolation('Message %param%', array('%param%' => 'value'));
+ };
+
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Other violation');
+ };
+
+ $this->metadata->addPropertyConstraint('firstName', new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group',
+ )));
+ $this->metadata->addPropertyConstraint('lastName', new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group',
+ )));
+
+ $violations = $this->validatePropertyValue(
+ self::ENTITY_CLASS,
+ 'firstName',
+ 'Bernhard',
+ 'Group'
+ );
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Message value', $violations[0]->getMessage());
+ $this->assertSame('Message %param%', $violations[0]->getMessageTemplate());
+ $this->assertSame(array('%param%' => 'value'), $violations[0]->getParameters());
+ $this->assertSame('', $violations[0]->getPropertyPath());
+ $this->assertSame('Bernhard', $violations[0]->getRoot());
+ $this->assertSame('Bernhard', $violations[0]->getInvalidValue());
+ $this->assertNull($violations[0]->getPlural());
+ $this->assertNull($violations[0]->getCode());
+ }
+
+ /**
+ * Cannot be UnsupportedMetadataException for BC with Symfony < 2.5.
+ *
+ * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
+ * @group legacy
+ */
+ public function testLegacyValidatePropertyValueFailsIfPropertiesNotSupported()
+ {
+ // $metadata does not implement PropertyMetadataContainerInterface
+ $metadata = $this->getMockBuilder('Symfony\Component\Validator\MetadataInterface')->getMock();
+
+ $this->metadataFactory->addMetadataForValue('VALUE', $metadata);
+
+ $this->validatePropertyValue('VALUE', 'someProperty', 'someValue');
+ }
+
+ /**
+ * https://github.com/symfony/symfony/issues/11604.
+ */
+ public function testValidatePropertyValueWithoutConstraints()
+ {
+ $entity = new Entity();
+ $violations = $this->validatePropertyValue($entity, 'lastName', 'foo');
+
+ $this->assertCount(0, $violations, '->validatePropertyValue() returns no violations if no constraints have been configured for the property being validated');
+ }
+
+ public function testValidateObjectOnlyOncePerGroup()
+ {
+ $entity = new Entity();
+ $entity->reference = new Reference();
+ $entity->reference2 = $entity->reference;
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->metadata->addPropertyConstraint('reference2', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ public function testValidateDifferentObjectsSeparately()
+ {
+ $entity = new Entity();
+ $entity->reference = new Reference();
+ $entity->reference2 = new Reference();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->metadata->addPropertyConstraint('reference2', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback($callback));
+
+ $violations = $this->validate($entity);
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(2, $violations);
+ }
+
+ public function testValidateSingleGroup()
+ {
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group 1',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group 2',
+ )));
+
+ $violations = $this->validate($entity, null, 'Group 2');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ }
+
+ public function testValidateMultipleGroups()
+ {
+ $entity = new Entity();
+
+ $callback = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Message');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group 1',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback,
+ 'groups' => 'Group 2',
+ )));
+
+ $violations = $this->validate($entity, null, array('Group 1', 'Group 2'));
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(2, $violations);
+ }
+
+ public function testReplaceDefaultGroupByGroupSequenceObject()
+ {
+ $entity = new Entity();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 2');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 3');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => function () {},
+ 'groups' => 'Group 1',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group 2',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 3',
+ )));
+
+ $sequence = new GroupSequence(array('Group 1', 'Group 2', 'Group 3', 'Entity'));
+ $this->metadata->setGroupSequence($sequence);
+
+ $violations = $this->validate($entity, null, 'Default');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Violation in Group 2', $violations[0]->getMessage());
+ }
+
+ public function testReplaceDefaultGroupByGroupSequenceArray()
+ {
+ $entity = new Entity();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 2');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 3');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => function () {},
+ 'groups' => 'Group 1',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group 2',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 3',
+ )));
+
+ $sequence = array('Group 1', 'Group 2', 'Group 3', 'Entity');
+ $this->metadata->setGroupSequence($sequence);
+
+ $violations = $this->validate($entity, null, 'Default');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Violation in Group 2', $violations[0]->getMessage());
+ }
+
+ public function testPropagateDefaultGroupToReferenceWhenReplacingDefaultGroup()
+ {
+ $entity = new Entity();
+ $entity->reference = new Reference();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Default group');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in group sequence');
+ };
+
+ $this->metadata->addPropertyConstraint('reference', new Valid());
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Default',
+ )));
+ $this->referenceMetadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 1',
+ )));
+
+ $sequence = new GroupSequence(array('Group 1', 'Entity'));
+ $this->metadata->setGroupSequence($sequence);
+
+ $violations = $this->validate($entity, null, 'Default');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Violation in Default group', $violations[0]->getMessage());
+ }
+
+ public function testValidateCustomGroupWhenDefaultGroupWasReplaced()
+ {
+ $entity = new Entity();
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in other group');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in group sequence');
+ };
+
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Other Group',
+ )));
+ $this->metadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 1',
+ )));
+
+ $sequence = new GroupSequence(array('Group 1', 'Entity'));
+ $this->metadata->setGroupSequence($sequence);
+
+ $violations = $this->validate($entity, null, 'Other Group');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Violation in other group', $violations[0]->getMessage());
+ }
+
+ public function testReplaceDefaultGroupWithObjectFromGroupSequenceProvider()
+ {
+ $sequence = new GroupSequence(array('Group 1', 'Group 2', 'Group 3', 'Entity'));
+ $entity = new GroupSequenceProviderEntity($sequence);
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 2');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 3');
+ };
+
+ $metadata = new ClassMetadata(\get_class($entity));
+ $metadata->addConstraint(new Callback(array(
+ 'callback' => function () {},
+ 'groups' => 'Group 1',
+ )));
+ $metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group 2',
+ )));
+ $metadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 3',
+ )));
+ $metadata->setGroupSequenceProvider(true);
+
+ $this->metadataFactory->addMetadata($metadata);
+
+ $violations = $this->validate($entity, null, 'Default');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Violation in Group 2', $violations[0]->getMessage());
+ }
+
+ public function testReplaceDefaultGroupWithArrayFromGroupSequenceProvider()
+ {
+ $sequence = array('Group 1', 'Group 2', 'Group 3', 'Entity');
+ $entity = new GroupSequenceProviderEntity($sequence);
+
+ $callback1 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 2');
+ };
+ $callback2 = function ($value, ExecutionContextInterface $context) {
+ $context->addViolation('Violation in Group 3');
+ };
+
+ $metadata = new ClassMetadata(\get_class($entity));
+ $metadata->addConstraint(new Callback(array(
+ 'callback' => function () {},
+ 'groups' => 'Group 1',
+ )));
+ $metadata->addConstraint(new Callback(array(
+ 'callback' => $callback1,
+ 'groups' => 'Group 2',
+ )));
+ $metadata->addConstraint(new Callback(array(
+ 'callback' => $callback2,
+ 'groups' => 'Group 3',
+ )));
+ $metadata->setGroupSequenceProvider(true);
+
+ $this->metadataFactory->addMetadata($metadata);
+
+ $violations = $this->validate($entity, null, 'Default');
+
+ /* @var ConstraintViolationInterface[] $violations */
+ $this->assertCount(1, $violations);
+ $this->assertSame('Violation in Group 2', $violations[0]->getMessage());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidator2Dot5ApiTest.php b/public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidator2Dot5ApiTest.php
new file mode 100644
index 0000000..fd1287f
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidator2Dot5ApiTest.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Validator;
+
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Component\Validator\ConstraintValidatorFactory;
+use Symfony\Component\Validator\Context\LegacyExecutionContextFactory;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Validator\LegacyValidator;
+
+/**
+ * @group legacy
+ */
+class LegacyValidator2Dot5ApiTest extends Abstract2Dot5ApiTest
+{
+ protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array())
+ {
+ $translator = new IdentityTranslator();
+ $translator->setLocale('en');
+
+ $contextFactory = new LegacyExecutionContextFactory($metadataFactory, $translator);
+ $validatorFactory = new ConstraintValidatorFactory();
+
+ return new LegacyValidator($contextFactory, $metadataFactory, $validatorFactory, $objectInitializers);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidatorLegacyApiTest.php b/public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidatorLegacyApiTest.php
new file mode 100644
index 0000000..0b51a11
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Validator/LegacyValidatorLegacyApiTest.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Validator;
+
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Component\Validator\ConstraintValidatorFactory;
+use Symfony\Component\Validator\Context\LegacyExecutionContextFactory;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Validator\LegacyValidator;
+
+/**
+ * @group legacy
+ */
+class LegacyValidatorLegacyApiTest extends AbstractLegacyApiTest
+{
+ protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array())
+ {
+ $translator = new IdentityTranslator();
+ $translator->setLocale('en');
+
+ $contextFactory = new LegacyExecutionContextFactory($metadataFactory, $translator);
+ $validatorFactory = new ConstraintValidatorFactory();
+
+ return new LegacyValidator($contextFactory, $metadataFactory, $validatorFactory, $objectInitializers);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/Validator/RecursiveValidator2Dot5ApiTest.php b/public/system/storage/vendor/symfony/validator/Tests/Validator/RecursiveValidator2Dot5ApiTest.php
new file mode 100644
index 0000000..1313fb9
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/Validator/RecursiveValidator2Dot5ApiTest.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Validator;
+
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Component\Validator\ConstraintValidatorFactory;
+use Symfony\Component\Validator\Context\ExecutionContextFactory;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\Tests\Fixtures\Entity;
+use Symfony\Component\Validator\Validator\RecursiveValidator;
+
+class RecursiveValidator2Dot5ApiTest extends Abstract2Dot5ApiTest
+{
+ protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array())
+ {
+ $translator = new IdentityTranslator();
+ $translator->setLocale('en');
+
+ $contextFactory = new ExecutionContextFactory($translator);
+ $validatorFactory = new ConstraintValidatorFactory();
+
+ return new RecursiveValidator($contextFactory, $metadataFactory, $validatorFactory, $objectInitializers);
+ }
+
+ public function testEmptyGroupsArrayDoesNotTriggerDeprecation()
+ {
+ $entity = new Entity();
+
+ $validatorContext = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock();
+ $validatorContext
+ ->expects($this->once())
+ ->method('validate')
+ ->with($entity, null, array())
+ ->willReturnSelf();
+
+ $validator = $this
+ ->getMockBuilder('Symfony\Component\Validator\Validator\RecursiveValidator')
+ ->disableOriginalConstructor()
+ ->setMethods(array('startContext'))
+ ->getMock();
+ $validator
+ ->expects($this->once())
+ ->method('startContext')
+ ->willReturn($validatorContext);
+
+ $validator->validate($entity, null, array());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Tests/ValidatorBuilderTest.php b/public/system/storage/vendor/symfony/validator/Tests/ValidatorBuilderTest.php
new file mode 100644
index 0000000..77d5864
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Tests/ValidatorBuilderTest.php
@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Validator\ValidatorBuilder;
+use Symfony\Component\Validator\ValidatorBuilderInterface;
+
+class ValidatorBuilderTest extends TestCase
+{
+ /**
+ * @var ValidatorBuilderInterface
+ */
+ protected $builder;
+
+ protected function setUp()
+ {
+ $this->builder = new ValidatorBuilder();
+ }
+
+ protected function tearDown()
+ {
+ $this->builder = null;
+ }
+
+ public function testAddObjectInitializer()
+ {
+ $this->assertSame($this->builder, $this->builder->addObjectInitializer(
+ $this->getMockBuilder('Symfony\Component\Validator\ObjectInitializerInterface')->getMock()
+ ));
+ }
+
+ public function testAddObjectInitializers()
+ {
+ $this->assertSame($this->builder, $this->builder->addObjectInitializers(array()));
+ }
+
+ public function testAddXmlMapping()
+ {
+ $this->assertSame($this->builder, $this->builder->addXmlMapping('mapping'));
+ }
+
+ public function testAddXmlMappings()
+ {
+ $this->assertSame($this->builder, $this->builder->addXmlMappings(array()));
+ }
+
+ public function testAddYamlMapping()
+ {
+ $this->assertSame($this->builder, $this->builder->addYamlMapping('mapping'));
+ }
+
+ public function testAddYamlMappings()
+ {
+ $this->assertSame($this->builder, $this->builder->addYamlMappings(array()));
+ }
+
+ public function testAddMethodMapping()
+ {
+ $this->assertSame($this->builder, $this->builder->addMethodMapping('mapping'));
+ }
+
+ public function testAddMethodMappings()
+ {
+ $this->assertSame($this->builder, $this->builder->addMethodMappings(array()));
+ }
+
+ public function testEnableAnnotationMapping()
+ {
+ $this->assertSame($this->builder, $this->builder->enableAnnotationMapping());
+ }
+
+ public function testDisableAnnotationMapping()
+ {
+ $this->assertSame($this->builder, $this->builder->disableAnnotationMapping());
+ }
+
+ public function testSetMetadataCache()
+ {
+ $this->assertSame($this->builder, $this->builder->setMetadataCache(
+ $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock())
+ );
+ }
+
+ public function testSetConstraintValidatorFactory()
+ {
+ $this->assertSame($this->builder, $this->builder->setConstraintValidatorFactory(
+ $this->getMockBuilder('Symfony\Component\Validator\ConstraintValidatorFactoryInterface')->getMock())
+ );
+ }
+
+ public function testSetTranslator()
+ {
+ $this->assertSame($this->builder, $this->builder->setTranslator(
+ $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock())
+ );
+ }
+
+ public function testSetTranslationDomain()
+ {
+ $this->assertSame($this->builder, $this->builder->setTranslationDomain('TRANS_DOMAIN'));
+ }
+
+ public function testGetValidator()
+ {
+ $this->assertInstanceOf('Symfony\Component\Validator\Validator\RecursiveValidator', $this->builder->getValidator());
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Util/PropertyPath.php b/public/system/storage/vendor/symfony/validator/Util/PropertyPath.php
new file mode 100644
index 0000000..4108a02
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Util/PropertyPath.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Util;
+
+/**
+ * Contains utility methods for dealing with property paths.
+ *
+ * For more extensive functionality, use Symfony's PropertyAccess component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class PropertyPath
+{
+ /**
+ * Appends a path to a given property path.
+ *
+ * If the base path is empty, the appended path will be returned unchanged.
+ * If the base path is not empty, and the appended path starts with a
+ * squared opening bracket ("["), the concatenation of the two paths is
+ * returned. Otherwise, the concatenation of the two paths is returned,
+ * separated by a dot (".").
+ *
+ * @param string $basePath The base path
+ * @param string $subPath The path to append
+ *
+ * @return string The concatenation of the two property paths
+ */
+ public static function append($basePath, $subPath)
+ {
+ if ('' !== (string) $subPath) {
+ if ('[' === $subPath[0]) {
+ return $basePath.$subPath;
+ }
+
+ return '' !== (string) $basePath ? $basePath.'.'.$subPath : $subPath;
+ }
+
+ return $basePath;
+ }
+
+ /**
+ * Not instantiable.
+ */
+ private function __construct()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validation.php b/public/system/storage/vendor/symfony/validator/Validation.php
new file mode 100644
index 0000000..a469b47
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validation.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Entry point for the Validator component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+final class Validation
+{
+ /**
+ * The Validator API provided by Symfony 2.4 and older.
+ *
+ * @deprecated use API_VERSION_2_5_BC instead
+ */
+ const API_VERSION_2_4 = 1;
+
+ /**
+ * The Validator API provided by Symfony 2.5 and newer.
+ */
+ const API_VERSION_2_5 = 2;
+
+ /**
+ * The Validator API provided by Symfony 2.5 and newer with a backwards
+ * compatibility layer for 2.4 and older.
+ */
+ const API_VERSION_2_5_BC = 3;
+
+ /**
+ * Creates a new validator.
+ *
+ * If you want to configure the validator, use
+ * {@link createValidatorBuilder()} instead.
+ *
+ * @return ValidatorInterface The new validator
+ */
+ public static function createValidator()
+ {
+ return self::createValidatorBuilder()->getValidator();
+ }
+
+ /**
+ * Creates a configurable builder for validator objects.
+ *
+ * @return ValidatorBuilderInterface The new builder
+ */
+ public static function createValidatorBuilder()
+ {
+ return new ValidatorBuilder();
+ }
+
+ /**
+ * This class cannot be instantiated.
+ */
+ private function __construct()
+ {
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ValidationVisitor.php b/public/system/storage/vendor/symfony/validator/ValidationVisitor.php
new file mode 100644
index 0000000..14fd88b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ValidationVisitor.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+@trigger_error('The '.__NAMESPACE__.'\ValidationVisitor class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Exception\NoSuchMetadataException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Default implementation of {@link ValidationVisitorInterface} and
+ * {@link GlobalExecutionContextInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface
+{
+ private $root;
+ private $metadataFactory;
+ private $validatorFactory;
+ private $translator;
+ private $translationDomain;
+ private $objectInitializers;
+ private $violations;
+ private $validatedObjects = array();
+
+ /**
+ * Creates a new validation visitor.
+ *
+ * @param mixed $root The value passed to the validator
+ * @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances
+ * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators
+ * @param TranslatorInterface $translator The translator for translating violation messages
+ * @param string|null $translationDomain The domain of the translation messages
+ * @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation
+ *
+ * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface
+ */
+ public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array())
+ {
+ foreach ($objectInitializers as $initializer) {
+ if (!$initializer instanceof ObjectInitializerInterface) {
+ throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface');
+ }
+ }
+
+ $this->root = $root;
+ $this->metadataFactory = $metadataFactory;
+ $this->validatorFactory = $validatorFactory;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ $this->objectInitializers = $objectInitializers;
+ $this->violations = new ConstraintViolationList();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath)
+ {
+ $context = new ExecutionContext(
+ $this,
+ $this->translator,
+ $this->translationDomain,
+ $metadata,
+ $value,
+ $group,
+ $propertyPath
+ );
+
+ $context->validateValue($value, $metadata->findConstraints($group));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false)
+ {
+ if (null === $value) {
+ return;
+ }
+
+ if (\is_object($value)) {
+ $hash = spl_object_hash($value);
+
+ // Exit, if the object is already validated for the current group
+ if (isset($this->validatedObjects[$hash][$group])) {
+ return;
+ }
+
+ // Initialize if the object wasn't initialized before
+ if (!isset($this->validatedObjects[$hash])) {
+ foreach ($this->objectInitializers as $initializer) {
+ if (!$initializer instanceof ObjectInitializerInterface) {
+ throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
+ }
+ $initializer->initialize($value);
+ }
+ }
+
+ // Remember validating this object before starting and possibly
+ // traversing the object graph
+ $this->validatedObjects[$hash][$group] = true;
+ }
+
+ // Validate arrays recursively by default, otherwise every driver needs
+ // to implement special handling for arrays.
+ // https://github.com/symfony/symfony/issues/6246
+ if (\is_array($value) || ($traverse && $value instanceof \Traversable)) {
+ foreach ($value as $key => $element) {
+ // Ignore any scalar values in the collection
+ if (\is_object($element) || \is_array($element)) {
+ // Only repeat the traversal if $deep is set
+ $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
+ }
+ }
+
+ try {
+ $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
+ } catch (NoSuchMetadataException $e) {
+ // Metadata doesn't necessarily have to exist for
+ // traversable objects, because we know how to validate
+ // them anyway. Optionally, additional metadata is supported.
+ }
+ } else {
+ $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getViolations()
+ {
+ return $this->violations;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVisitor()
+ {
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValidatorFactory()
+ {
+ return $this->validatorFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFactory()
+ {
+ return $this->metadataFactory;
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ValidationVisitorInterface.php b/public/system/storage/vendor/symfony/validator/ValidationVisitorInterface.php
new file mode 100644
index 0000000..28d4921
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ValidationVisitorInterface.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Validates values against constraints defined in {@link MetadataInterface}
+ * instances.
+ *
+ * This interface is an implementation of the Visitor design pattern. A value
+ * is validated by first passing it to the {@link validate} method. That method
+ * will determine the matching {@link MetadataInterface} for validating the
+ * value. It then calls the {@link MetadataInterface::accept} method of that
+ * metadata. <tt>accept()</tt> does two things:
+ *
+ * <ol>
+ * <li>It calls {@link visit} to validate the value against the constraints of
+ * the metadata.</li>
+ * <li>It calls <tt>accept()</tt> on all nested metadata instances with the
+ * corresponding values extracted from the current value. For example, if the
+ * current metadata represents a class and the current value is an object of
+ * that class, the metadata contains nested instances for each property of that
+ * class. It forwards the call to these nested metadata with the values of the
+ * corresponding properties in the original object.</li>
+ * </ol>
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+interface ValidationVisitorInterface
+{
+ /**
+ * Validates a value.
+ *
+ * If the value is an array or a traversable object, you can set the
+ * parameter <tt>$traverse</tt> to <tt>true</tt> in order to run through
+ * the collection and validate each element. If these elements can be
+ * collections again and you want to traverse them recursively, set the
+ * parameter <tt>$deep</tt> to <tt>true</tt> as well.
+ *
+ * If you set <tt>$traversable</tt> to <tt>true</tt>, the visitor will
+ * nevertheless try to find metadata for the collection and validate its
+ * constraints. If no such metadata is found, the visitor ignores that and
+ * only iterates the collection.
+ *
+ * If you don't set <tt>$traversable</tt> to <tt>true</tt> and the visitor
+ * does not find metadata for the given value, it will fail with an
+ * exception.
+ *
+ * @param mixed $value The value to validate
+ * @param string $group The validation group to validate
+ * @param string $propertyPath The current property path in the validation graph
+ * @param bool $traverse Whether to traverse the value if it is traversable
+ * @param bool $deep Whether to traverse nested traversable values recursively
+ *
+ * @throws Exception\NoSuchMetadataException if no metadata can be found for
+ * the given value
+ */
+ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false);
+
+ /**
+ * Validates a value against the constraints defined in some metadata.
+ *
+ * This method implements the Visitor design pattern. See also
+ * {@link ValidationVisitorInterface}.
+ *
+ * @param MetadataInterface $metadata The metadata holding the constraints
+ * @param mixed $value The value to validate
+ * @param string $group The validation group to validate
+ * @param string $propertyPath The current property path in the validation graph
+ */
+ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath);
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validator.php b/public/system/storage/vendor/symfony/validator/Validator.php
new file mode 100644
index 0000000..1aa5fd1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validator.php
@@ -0,0 +1,208 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+@trigger_error('The '.__NAMESPACE__.'\Validator class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Validator\Validator\RecursiveValidator class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\Exception\ValidatorException;
+
+/**
+ * Default implementation of {@link ValidatorInterface}.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Validator\RecursiveValidator} instead.
+ */
+class Validator implements ValidatorInterface, Mapping\Factory\MetadataFactoryInterface
+{
+ private $metadataFactory;
+ private $validatorFactory;
+ private $translator;
+ private $translationDomain;
+ private $objectInitializers;
+
+ public function __construct(MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = 'validators', array $objectInitializers = array())
+ {
+ $this->metadataFactory = $metadataFactory;
+ $this->validatorFactory = $validatorFactory;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ $this->objectInitializers = $objectInitializers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFactory()
+ {
+ return $this->metadataFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFor($value)
+ {
+ return $this->metadataFactory->getMetadataFor($value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasMetadataFor($value)
+ {
+ return $this->metadataFactory->hasMetadataFor($value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $groups = null, $traverse = false, $deep = false)
+ {
+ $visitor = $this->createVisitor($value);
+
+ foreach ($this->resolveGroups($groups) as $group) {
+ $visitor->validate($value, $group, '', $traverse, $deep);
+ }
+
+ return $visitor->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws ValidatorException if the metadata for the value does not support properties
+ */
+ public function validateProperty($containingValue, $property, $groups = null)
+ {
+ $visitor = $this->createVisitor($containingValue);
+ $metadata = $this->metadataFactory->getMetadataFor($containingValue);
+
+ if (!$metadata instanceof PropertyMetadataContainerInterface) {
+ $valueAsString = is_scalar($containingValue)
+ ? '"'.$containingValue.'"'
+ : 'the value of type '.\gettype($containingValue);
+
+ throw new ValidatorException(sprintf('The metadata for %s does not support properties.', $valueAsString));
+ }
+
+ foreach ($this->resolveGroups($groups) as $group) {
+ if (!$metadata->hasPropertyMetadata($property)) {
+ continue;
+ }
+
+ foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
+ $propMeta->accept($visitor, $propMeta->getPropertyValue($containingValue), $group, $property);
+ }
+ }
+
+ return $visitor->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws ValidatorException if the metadata for the value does not support properties
+ */
+ public function validatePropertyValue($containingValue, $property, $value, $groups = null)
+ {
+ $visitor = $this->createVisitor(\is_object($containingValue) ? $containingValue : $value);
+ $metadata = $this->metadataFactory->getMetadataFor($containingValue);
+
+ if (!$metadata instanceof PropertyMetadataContainerInterface) {
+ $valueAsString = is_scalar($containingValue)
+ ? '"'.$containingValue.'"'
+ : 'the value of type '.\gettype($containingValue);
+
+ throw new ValidatorException(sprintf('The metadata for %s does not support properties.', $valueAsString));
+ }
+
+ // If $containingValue is passed as class name, take $value as root
+ // and start the traversal with an empty property path
+ $propertyPath = \is_object($containingValue) ? $property : '';
+
+ foreach ($this->resolveGroups($groups) as $group) {
+ if (!$metadata->hasPropertyMetadata($property)) {
+ continue;
+ }
+
+ foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
+ $propMeta->accept($visitor, $value, $group, $propertyPath);
+ }
+ }
+
+ return $visitor->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateValue($value, $constraints, $groups = null)
+ {
+ $context = new ExecutionContext($this->createVisitor($value), $this->translator, $this->translationDomain);
+
+ $constraints = \is_array($constraints) ? $constraints : array($constraints);
+
+ foreach ($constraints as $constraint) {
+ if ($constraint instanceof Valid) {
+ // Why can't the Valid constraint be executed directly?
+ //
+ // It cannot be executed like regular other constraints, because regular
+ // constraints are only executed *if they belong to the validated group*.
+ // The Valid constraint, on the other hand, is always executed and propagates
+ // the group to the cascaded object. The propagated group depends on
+ //
+ // * Whether a group sequence is currently being executed. Then the default
+ // group is propagated.
+ //
+ // * Otherwise the validated group is propagated.
+
+ throw new ValidatorException(sprintf('The constraint %s cannot be validated. Use the method validate() instead.', \get_class($constraint)));
+ }
+
+ $context->validateValue($value, $constraint, '', $groups);
+ }
+
+ return $context->getViolations();
+ }
+
+ /**
+ * @param mixed $root
+ *
+ * @return ValidationVisitor
+ */
+ private function createVisitor($root)
+ {
+ return new ValidationVisitor(
+ $root,
+ $this->metadataFactory,
+ $this->validatorFactory,
+ $this->translator,
+ $this->translationDomain,
+ $this->objectInitializers
+ );
+ }
+
+ /**
+ * @param string|string[]|null $groups
+ *
+ * @return string[]
+ */
+ private function resolveGroups($groups)
+ {
+ return $groups ? (array) $groups : array(Constraint::DEFAULT_GROUP);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validator/ContextualValidatorInterface.php b/public/system/storage/vendor/symfony/validator/Validator/ContextualValidatorInterface.php
new file mode 100644
index 0000000..c8b545b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validator/ContextualValidatorInterface.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Validator;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\ConstraintViolationListInterface;
+
+/**
+ * A validator in a specific execution context.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ContextualValidatorInterface
+{
+ /**
+ * Appends the given path to the property path of the context.
+ *
+ * If called multiple times, the path will always be reset to the context's
+ * original path with the given path appended to it.
+ *
+ * @param string $path The path to append
+ *
+ * @return $this
+ */
+ public function atPath($path);
+
+ /**
+ * Validates a value against a constraint or a list of constraints.
+ *
+ * If no constraint is passed, the constraint
+ * {@link \Symfony\Component\Validator\Constraints\Valid} is assumed.
+ *
+ * @param mixed $value The value to validate
+ * @param Constraint|Constraint[] $constraints The constraint(s) to validate against
+ * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed
+ *
+ * @return $this
+ */
+ public function validate($value, $constraints = null, $groups = null);
+
+ /**
+ * Validates a property of an object against the constraints specified
+ * for this property.
+ *
+ * @param object $object The object
+ * @param string $propertyName The name of the validated property
+ * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed
+ *
+ * @return $this
+ */
+ public function validateProperty($object, $propertyName, $groups = null);
+
+ /**
+ * Validates a value against the constraints specified for an object's
+ * property.
+ *
+ * @param object|string $objectOrClass The object or its class name
+ * @param string $propertyName The name of the property
+ * @param mixed $value The value to validate against the property's constraints
+ * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed
+ *
+ * @return $this
+ */
+ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null);
+
+ /**
+ * Returns the violations that have been generated so far in the context
+ * of the validator.
+ *
+ * @return ConstraintViolationListInterface The constraint violations
+ */
+ public function getViolations();
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validator/LegacyValidator.php b/public/system/storage/vendor/symfony/validator/Validator/LegacyValidator.php
new file mode 100644
index 0000000..c4d818b
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validator/LegacyValidator.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Validator;
+
+@trigger_error('The '.__NAMESPACE__.'\LegacyValidator class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+/**
+ * A validator that supports both the API of Symfony < 2.5 and Symfony 2.5+.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @see \Symfony\Component\Validator\ValidatorInterface
+ * @see \Symfony\Component\Validator\Validator\ValidatorInterface
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+class LegacyValidator extends RecursiveValidator
+{
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validator/RecursiveContextualValidator.php b/public/system/storage/vendor/symfony/validator/Validator/RecursiveContextualValidator.php
new file mode 100644
index 0000000..14456d8
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validator/RecursiveContextualValidator.php
@@ -0,0 +1,831 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Validator;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
+use Symfony\Component\Validator\Context\ExecutionContext;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\NoSuchMetadataException;
+use Symfony\Component\Validator\Exception\RuntimeException;
+use Symfony\Component\Validator\Exception\UnsupportedMetadataException;
+use Symfony\Component\Validator\Exception\ValidatorException;
+use Symfony\Component\Validator\Mapping\CascadingStrategy;
+use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
+use Symfony\Component\Validator\Mapping\GenericMetadata;
+use Symfony\Component\Validator\Mapping\MetadataInterface;
+use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
+use Symfony\Component\Validator\Mapping\TraversalStrategy;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\ObjectInitializerInterface;
+use Symfony\Component\Validator\Util\PropertyPath;
+
+/**
+ * Recursive implementation of {@link ContextualValidatorInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class RecursiveContextualValidator implements ContextualValidatorInterface
+{
+ private $context;
+ private $defaultPropertyPath;
+ private $defaultGroups;
+ private $metadataFactory;
+ private $validatorFactory;
+ private $objectInitializers;
+
+ /**
+ * Creates a validator for the given context.
+ *
+ * @param ExecutionContextInterface $context The execution context
+ * @param MetadataFactoryInterface $metadataFactory The factory for
+ * fetching the metadata
+ * of validated objects
+ * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating
+ * constraint validators
+ * @param ObjectInitializerInterface[] $objectInitializers The object initializers
+ */
+ public function __construct(ExecutionContextInterface $context, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, array $objectInitializers = array())
+ {
+ $this->context = $context;
+ $this->defaultPropertyPath = $context->getPropertyPath();
+ $this->defaultGroups = array($context->getGroup() ?: Constraint::DEFAULT_GROUP);
+ $this->metadataFactory = $metadataFactory;
+ $this->validatorFactory = $validatorFactory;
+ $this->objectInitializers = $objectInitializers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function atPath($path)
+ {
+ $this->defaultPropertyPath = $this->context->getPropertyPath($path);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $constraints = null, $groups = null)
+ {
+ $groups = $groups ? $this->normalizeGroups($groups) : $this->defaultGroups;
+
+ $previousValue = $this->context->getValue();
+ $previousObject = $this->context->getObject();
+ $previousMetadata = $this->context->getMetadata();
+ $previousPath = $this->context->getPropertyPath();
+ $previousGroup = $this->context->getGroup();
+ $previousConstraint = null;
+
+ if ($this->context instanceof ExecutionContext || method_exists($this->context, 'getConstraint')) {
+ $previousConstraint = $this->context->getConstraint();
+ }
+
+ // If explicit constraints are passed, validate the value against
+ // those constraints
+ if (null !== $constraints) {
+ // You can pass a single constraint or an array of constraints
+ // Make sure to deal with an array in the rest of the code
+ if (!\is_array($constraints)) {
+ $constraints = array($constraints);
+ }
+
+ $metadata = new GenericMetadata();
+ $metadata->addConstraints($constraints);
+
+ $this->validateGenericNode(
+ $value,
+ $previousObject,
+ \is_object($value) ? spl_object_hash($value) : null,
+ $metadata,
+ $this->defaultPropertyPath,
+ $groups,
+ null,
+ TraversalStrategy::IMPLICIT,
+ $this->context
+ );
+
+ $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath);
+ $this->context->setGroup($previousGroup);
+
+ if (null !== $previousConstraint) {
+ $this->context->setConstraint($previousConstraint);
+ }
+
+ return $this;
+ }
+
+ // If an object is passed without explicit constraints, validate that
+ // object against the constraints defined for the object's class
+ if (\is_object($value)) {
+ $this->validateObject(
+ $value,
+ $this->defaultPropertyPath,
+ $groups,
+ TraversalStrategy::IMPLICIT,
+ $this->context
+ );
+
+ $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath);
+ $this->context->setGroup($previousGroup);
+
+ return $this;
+ }
+
+ // If an array is passed without explicit constraints, validate each
+ // object in the array
+ if (\is_array($value)) {
+ $this->validateEachObjectIn(
+ $value,
+ $this->defaultPropertyPath,
+ $groups,
+ true,
+ $this->context
+ );
+
+ $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath);
+ $this->context->setGroup($previousGroup);
+
+ return $this;
+ }
+
+ throw new RuntimeException(sprintf('Cannot validate values of type "%s" automatically. Please provide a constraint.', \gettype($value)));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateProperty($object, $propertyName, $groups = null)
+ {
+ $classMetadata = $this->metadataFactory->getMetadataFor($object);
+
+ if (!$classMetadata instanceof ClassMetadataInterface) {
+ // Cannot be UnsupportedMetadataException because of BC with
+ // Symfony < 2.5
+ throw new ValidatorException(sprintf('The metadata factory should return instances of "\Symfony\Component\Validator\Mapping\ClassMetadataInterface", got: "%s".', \is_object($classMetadata) ? \get_class($classMetadata) : \gettype($classMetadata)));
+ }
+
+ $propertyMetadatas = $classMetadata->getPropertyMetadata($propertyName);
+ $groups = $groups ? $this->normalizeGroups($groups) : $this->defaultGroups;
+ $cacheKey = spl_object_hash($object);
+ $propertyPath = PropertyPath::append($this->defaultPropertyPath, $propertyName);
+
+ $previousValue = $this->context->getValue();
+ $previousObject = $this->context->getObject();
+ $previousMetadata = $this->context->getMetadata();
+ $previousPath = $this->context->getPropertyPath();
+ $previousGroup = $this->context->getGroup();
+
+ foreach ($propertyMetadatas as $propertyMetadata) {
+ $propertyValue = $propertyMetadata->getPropertyValue($object);
+
+ $this->validateGenericNode(
+ $propertyValue,
+ $object,
+ $cacheKey.':'.$propertyName,
+ $propertyMetadata,
+ $propertyPath,
+ $groups,
+ null,
+ TraversalStrategy::IMPLICIT,
+ $this->context
+ );
+ }
+
+ $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath);
+ $this->context->setGroup($previousGroup);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null)
+ {
+ $classMetadata = $this->metadataFactory->getMetadataFor($objectOrClass);
+
+ if (!$classMetadata instanceof ClassMetadataInterface) {
+ // Cannot be UnsupportedMetadataException because of BC with
+ // Symfony < 2.5
+ throw new ValidatorException(sprintf('The metadata factory should return instances of "\Symfony\Component\Validator\Mapping\ClassMetadataInterface", got: "%s".', \is_object($classMetadata) ? \get_class($classMetadata) : \gettype($classMetadata)));
+ }
+
+ $propertyMetadatas = $classMetadata->getPropertyMetadata($propertyName);
+ $groups = $groups ? $this->normalizeGroups($groups) : $this->defaultGroups;
+
+ if (\is_object($objectOrClass)) {
+ $object = $objectOrClass;
+ $cacheKey = spl_object_hash($objectOrClass);
+ $propertyPath = PropertyPath::append($this->defaultPropertyPath, $propertyName);
+ } else {
+ // $objectOrClass contains a class name
+ $object = null;
+ $cacheKey = null;
+ $propertyPath = $this->defaultPropertyPath;
+ }
+
+ $previousValue = $this->context->getValue();
+ $previousObject = $this->context->getObject();
+ $previousMetadata = $this->context->getMetadata();
+ $previousPath = $this->context->getPropertyPath();
+ $previousGroup = $this->context->getGroup();
+
+ foreach ($propertyMetadatas as $propertyMetadata) {
+ $this->validateGenericNode(
+ $value,
+ $object,
+ $cacheKey.':'.$propertyName,
+ $propertyMetadata,
+ $propertyPath,
+ $groups,
+ null,
+ TraversalStrategy::IMPLICIT,
+ $this->context
+ );
+ }
+
+ $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath);
+ $this->context->setGroup($previousGroup);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getViolations()
+ {
+ return $this->context->getViolations();
+ }
+
+ /**
+ * Normalizes the given group or list of groups to an array.
+ *
+ * @param string|GroupSequence|(string|GroupSequence)[] $groups The groups to normalize
+ *
+ * @return (string|GroupSequence)[] A group array
+ */
+ protected function normalizeGroups($groups)
+ {
+ if (\is_array($groups)) {
+ return $groups;
+ }
+
+ return array($groups);
+ }
+
+ /**
+ * Validates an object against the constraints defined for its class.
+ *
+ * If no metadata is available for the class, but the class is an instance
+ * of {@link \Traversable} and the selected traversal strategy allows
+ * traversal, the object will be iterated and each nested object will be
+ * validated instead.
+ *
+ * @param object $object The object to cascade
+ * @param string $propertyPath The current property path
+ * @param (string|GroupSequence)[] $groups The validated groups
+ * @param int $traversalStrategy The strategy for traversing the
+ * cascaded object
+ * @param ExecutionContextInterface $context The current execution context
+ *
+ * @throws NoSuchMetadataException If the object has no associated metadata
+ * and does not implement {@link \Traversable}
+ * or if traversal is disabled via the
+ * $traversalStrategy argument
+ * @throws UnsupportedMetadataException If the metadata returned by the
+ * metadata factory does not implement
+ * {@link ClassMetadataInterface}
+ */
+ private function validateObject($object, $propertyPath, array $groups, $traversalStrategy, ExecutionContextInterface $context)
+ {
+ try {
+ $classMetadata = $this->metadataFactory->getMetadataFor($object);
+
+ if (!$classMetadata instanceof ClassMetadataInterface) {
+ throw new UnsupportedMetadataException(sprintf('The metadata factory should return instances of "Symfony\Component\Validator\Mapping\ClassMetadataInterface", got: "%s".', \is_object($classMetadata) ? \get_class($classMetadata) : \gettype($classMetadata)));
+ }
+
+ $this->validateClassNode(
+ $object,
+ spl_object_hash($object),
+ $classMetadata,
+ $propertyPath,
+ $groups,
+ null,
+ $traversalStrategy,
+ $context
+ );
+ } catch (NoSuchMetadataException $e) {
+ // Rethrow if not Traversable
+ if (!$object instanceof \Traversable) {
+ throw $e;
+ }
+
+ // Rethrow unless IMPLICIT or TRAVERSE
+ if (!($traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE))) {
+ throw $e;
+ }
+
+ $this->validateEachObjectIn(
+ $object,
+ $propertyPath,
+ $groups,
+ $traversalStrategy & TraversalStrategy::STOP_RECURSION,
+ $context
+ );
+ }
+ }
+
+ /**
+ * Validates each object in a collection against the constraints defined
+ * for their classes.
+ *
+ * If the parameter $recursive is set to true, nested {@link \Traversable}
+ * objects are iterated as well. Nested arrays are always iterated,
+ * regardless of the value of $recursive.
+ *
+ * @param iterable $collection The collection
+ * @param string $propertyPath The current property path
+ * @param (string|GroupSequence)[] $groups The validated groups
+ * @param bool $stopRecursion Whether to disable
+ * recursive iteration. For
+ * backwards compatibility
+ * with Symfony < 2.5.
+ * @param ExecutionContextInterface $context The current execution context
+ *
+ * @see ClassNode
+ * @see CollectionNode
+ */
+ private function validateEachObjectIn($collection, $propertyPath, array $groups, $stopRecursion, ExecutionContextInterface $context)
+ {
+ if ($stopRecursion) {
+ $traversalStrategy = TraversalStrategy::NONE;
+ } else {
+ $traversalStrategy = TraversalStrategy::IMPLICIT;
+ }
+
+ foreach ($collection as $key => $value) {
+ if (\is_array($value)) {
+ // Arrays are always cascaded, independent of the specified
+ // traversal strategy
+ // (BC with Symfony < 2.5)
+ $this->validateEachObjectIn(
+ $value,
+ $propertyPath.'['.$key.']',
+ $groups,
+ $stopRecursion,
+ $context
+ );
+
+ continue;
+ }
+
+ // Scalar and null values in the collection are ignored
+ // (BC with Symfony < 2.5)
+ if (\is_object($value)) {
+ $this->validateObject(
+ $value,
+ $propertyPath.'['.$key.']',
+ $groups,
+ $traversalStrategy,
+ $context
+ );
+ }
+ }
+ }
+
+ /**
+ * Validates a class node.
+ *
+ * A class node is a combination of an object with a {@link ClassMetadataInterface}
+ * instance. Each class node (conceptionally) has zero or more succeeding
+ * property nodes:
+ *
+ * (Article:class node)
+ * \
+ * ($title:property node)
+ *
+ * This method validates the passed objects against all constraints defined
+ * at class level. It furthermore triggers the validation of each of the
+ * class' properties against the constraints for that property.
+ *
+ * If the selected traversal strategy allows traversal, the object is
+ * iterated and each nested object is validated against its own constraints.
+ * The object is not traversed if traversal is disabled in the class
+ * metadata.
+ *
+ * If the passed groups contain the group "Default", the validator will
+ * check whether the "Default" group has been replaced by a group sequence
+ * in the class metadata. If this is the case, the group sequence is
+ * validated instead.
+ *
+ * @param object $object The validated object
+ * @param string $cacheKey The key for caching
+ * the validated object
+ * @param ClassMetadataInterface $metadata The class metadata of
+ * the object
+ * @param string $propertyPath The property path leading
+ * to the object
+ * @param (string|GroupSequence)[] $groups The groups in which the
+ * object should be validated
+ * @param string[]|null $cascadedGroups The groups in which
+ * cascaded objects should
+ * be validated
+ * @param int $traversalStrategy The strategy used for
+ * traversing the object
+ * @param ExecutionContextInterface $context The current execution context
+ *
+ * @throws UnsupportedMetadataException If a property metadata does not
+ * implement {@link PropertyMetadataInterface}
+ * @throws ConstraintDefinitionException If traversal was enabled but the
+ * object does not implement
+ * {@link \Traversable}
+ *
+ * @see TraversalStrategy
+ */
+ private function validateClassNode($object, $cacheKey, ClassMetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups, $traversalStrategy, ExecutionContextInterface $context)
+ {
+ $context->setNode($object, $object, $metadata, $propertyPath);
+
+ if (!$context->isObjectInitialized($cacheKey)) {
+ foreach ($this->objectInitializers as $initializer) {
+ $initializer->initialize($object);
+ }
+
+ $context->markObjectAsInitialized($cacheKey);
+ }
+
+ foreach ($groups as $key => $group) {
+ // If the "Default" group is replaced by a group sequence, remember
+ // to cascade the "Default" group when traversing the group
+ // sequence
+ $defaultOverridden = false;
+
+ // Use the object hash for group sequences
+ $groupHash = \is_object($group) ? spl_object_hash($group) : $group;
+
+ if ($context->isGroupValidated($cacheKey, $groupHash)) {
+ // Skip this group when validating the properties and when
+ // traversing the object
+ unset($groups[$key]);
+
+ continue;
+ }
+
+ $context->markGroupAsValidated($cacheKey, $groupHash);
+
+ // Replace the "Default" group by the group sequence defined
+ // for the class, if applicable.
+ // This is done after checking the cache, so that
+ // spl_object_hash() isn't called for this sequence and
+ // "Default" is used instead in the cache. This is useful
+ // if the getters below return different group sequences in
+ // every call.
+ if (Constraint::DEFAULT_GROUP === $group) {
+ if ($metadata->hasGroupSequence()) {
+ // The group sequence is statically defined for the class
+ $group = $metadata->getGroupSequence();
+ $defaultOverridden = true;
+ } elseif ($metadata->isGroupSequenceProvider()) {
+ // The group sequence is dynamically obtained from the validated
+ // object
+ /* @var \Symfony\Component\Validator\GroupSequenceProviderInterface $object */
+ $group = $object->getGroupSequence();
+ $defaultOverridden = true;
+
+ if (!$group instanceof GroupSequence) {
+ $group = new GroupSequence($group);
+ }
+ }
+ }
+
+ // If the groups (=[<G1,G2>,G3,G4]) contain a group sequence
+ // (=<G1,G2>), then call validateClassNode() with each entry of the
+ // group sequence and abort if necessary (G1, G2)
+ if ($group instanceof GroupSequence) {
+ $this->stepThroughGroupSequence(
+ $object,
+ $object,
+ $cacheKey,
+ $metadata,
+ $propertyPath,
+ $traversalStrategy,
+ $group,
+ $defaultOverridden ? Constraint::DEFAULT_GROUP : null,
+ $context
+ );
+
+ // Skip the group sequence when validating properties, because
+ // stepThroughGroupSequence() already validates the properties
+ unset($groups[$key]);
+
+ continue;
+ }
+
+ $this->validateInGroup($object, $cacheKey, $metadata, $group, $context);
+ }
+
+ // If no more groups should be validated for the property nodes,
+ // we can safely quit
+ if (0 === \count($groups)) {
+ return;
+ }
+
+ // Validate all properties against their constraints
+ foreach ($metadata->getConstrainedProperties() as $propertyName) {
+ // If constraints are defined both on the getter of a property as
+ // well as on the property itself, then getPropertyMetadata()
+ // returns two metadata objects, not just one
+ foreach ($metadata->getPropertyMetadata($propertyName) as $propertyMetadata) {
+ if (!$propertyMetadata instanceof PropertyMetadataInterface) {
+ throw new UnsupportedMetadataException(sprintf('The property metadata instances should implement "Symfony\Component\Validator\Mapping\PropertyMetadataInterface", got: "%s".', \is_object($propertyMetadata) ? \get_class($propertyMetadata) : \gettype($propertyMetadata)));
+ }
+
+ $propertyValue = $propertyMetadata->getPropertyValue($object);
+
+ $this->validateGenericNode(
+ $propertyValue,
+ $object,
+ $cacheKey.':'.$propertyName,
+ $propertyMetadata,
+ PropertyPath::append($propertyPath, $propertyName),
+ $groups,
+ $cascadedGroups,
+ TraversalStrategy::IMPLICIT,
+ $context
+ );
+ }
+ }
+
+ // If no specific traversal strategy was requested when this method
+ // was called, use the traversal strategy of the class' metadata
+ if ($traversalStrategy & TraversalStrategy::IMPLICIT) {
+ // Keep the STOP_RECURSION flag, if it was set
+ $traversalStrategy = $metadata->getTraversalStrategy()
+ | ($traversalStrategy & TraversalStrategy::STOP_RECURSION);
+ }
+
+ // Traverse only if IMPLICIT or TRAVERSE
+ if (!($traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE))) {
+ return;
+ }
+
+ // If IMPLICIT, stop unless we deal with a Traversable
+ if ($traversalStrategy & TraversalStrategy::IMPLICIT && !$object instanceof \Traversable) {
+ return;
+ }
+
+ // If TRAVERSE, fail if we have no Traversable
+ if (!$object instanceof \Traversable) {
+ // Must throw a ConstraintDefinitionException for backwards
+ // compatibility reasons with Symfony < 2.5
+ throw new ConstraintDefinitionException(sprintf('Traversal was enabled for "%s", but this class does not implement "\Traversable".', \get_class($object)));
+ }
+
+ $this->validateEachObjectIn(
+ $object,
+ $propertyPath,
+ $groups,
+ $traversalStrategy & TraversalStrategy::STOP_RECURSION,
+ $context
+ );
+ }
+
+ /**
+ * Validates a node that is not a class node.
+ *
+ * Currently, two such node types exist:
+ *
+ * - property nodes, which consist of the value of an object's
+ * property together with a {@link PropertyMetadataInterface} instance
+ * - generic nodes, which consist of a value and some arbitrary
+ * constraints defined in a {@link MetadataInterface} container
+ *
+ * In both cases, the value is validated against all constraints defined
+ * in the passed metadata object. Then, if the value is an instance of
+ * {@link \Traversable} and the selected traversal strategy permits it,
+ * the value is traversed and each nested object validated against its own
+ * constraints. Arrays are always traversed.
+ *
+ * @param mixed $value The validated value
+ * @param object|null $object The current object
+ * @param string $cacheKey The key for caching
+ * the validated value
+ * @param MetadataInterface $metadata The metadata of the
+ * value
+ * @param string $propertyPath The property path leading
+ * to the value
+ * @param (string|GroupSequence)[] $groups The groups in which the
+ * value should be validated
+ * @param string[]|null $cascadedGroups The groups in which
+ * cascaded objects should
+ * be validated
+ * @param int $traversalStrategy The strategy used for
+ * traversing the value
+ * @param ExecutionContextInterface $context The current execution context
+ *
+ * @see TraversalStrategy
+ */
+ private function validateGenericNode($value, $object, $cacheKey, MetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups, $traversalStrategy, ExecutionContextInterface $context)
+ {
+ $context->setNode($value, $object, $metadata, $propertyPath);
+
+ foreach ($groups as $key => $group) {
+ if ($group instanceof GroupSequence) {
+ $this->stepThroughGroupSequence(
+ $value,
+ $object,
+ $cacheKey,
+ $metadata,
+ $propertyPath,
+ $traversalStrategy,
+ $group,
+ null,
+ $context
+ );
+
+ // Skip the group sequence when cascading, as the cascading
+ // logic is already done in stepThroughGroupSequence()
+ unset($groups[$key]);
+
+ continue;
+ }
+
+ $this->validateInGroup($value, $cacheKey, $metadata, $group, $context);
+ }
+
+ if (0 === \count($groups)) {
+ return;
+ }
+
+ if (null === $value) {
+ return;
+ }
+
+ $cascadingStrategy = $metadata->getCascadingStrategy();
+
+ // Quit unless we have an array or a cascaded object
+ if (!\is_array($value) && !($cascadingStrategy & CascadingStrategy::CASCADE)) {
+ return;
+ }
+
+ // If no specific traversal strategy was requested when this method
+ // was called, use the traversal strategy of the node's metadata
+ if ($traversalStrategy & TraversalStrategy::IMPLICIT) {
+ // Keep the STOP_RECURSION flag, if it was set
+ $traversalStrategy = $metadata->getTraversalStrategy()
+ | ($traversalStrategy & TraversalStrategy::STOP_RECURSION);
+ }
+
+ // The $cascadedGroups property is set, if the "Default" group is
+ // overridden by a group sequence
+ // See validateClassNode()
+ $cascadedGroups = null !== $cascadedGroups && \count($cascadedGroups) > 0 ? $cascadedGroups : $groups;
+
+ if (\is_array($value)) {
+ // Arrays are always traversed, independent of the specified
+ // traversal strategy
+ // (BC with Symfony < 2.5)
+ $this->validateEachObjectIn(
+ $value,
+ $propertyPath,
+ $cascadedGroups,
+ $traversalStrategy & TraversalStrategy::STOP_RECURSION,
+ $context
+ );
+
+ return;
+ }
+
+ // If the value is a scalar, pass it anyway, because we want
+ // a NoSuchMetadataException to be thrown in that case
+ // (BC with Symfony < 2.5)
+ $this->validateObject(
+ $value,
+ $propertyPath,
+ $cascadedGroups,
+ $traversalStrategy,
+ $context
+ );
+
+ // Currently, the traversal strategy can only be TRAVERSE for a
+ // generic node if the cascading strategy is CASCADE. Thus, traversable
+ // objects will always be handled within validateObject() and there's
+ // nothing more to do here.
+
+ // see GenericMetadata::addConstraint()
+ }
+
+ /**
+ * Sequentially validates a node's value in each group of a group sequence.
+ *
+ * If any of the constraints generates a violation, subsequent groups in the
+ * group sequence are skipped.
+ *
+ * @param mixed $value The validated value
+ * @param object|null $object The current object
+ * @param string $cacheKey The key for caching
+ * the validated value
+ * @param MetadataInterface $metadata The metadata of the
+ * value
+ * @param string $propertyPath The property path leading
+ * to the value
+ * @param int $traversalStrategy The strategy used for
+ * traversing the value
+ * @param GroupSequence $groupSequence The group sequence
+ * @param string|null $cascadedGroup The group that should
+ * be passed to cascaded
+ * objects instead of
+ * the group sequence
+ * @param ExecutionContextInterface $context The execution context
+ */
+ private function stepThroughGroupSequence($value, $object, $cacheKey, MetadataInterface $metadata = null, $propertyPath, $traversalStrategy, GroupSequence $groupSequence, $cascadedGroup, ExecutionContextInterface $context)
+ {
+ $violationCount = \count($context->getViolations());
+ $cascadedGroups = $cascadedGroup ? array($cascadedGroup) : null;
+
+ foreach ($groupSequence->groups as $groupInSequence) {
+ $groups = array($groupInSequence);
+
+ if ($metadata instanceof ClassMetadataInterface) {
+ $this->validateClassNode(
+ $value,
+ $cacheKey,
+ $metadata,
+ $propertyPath,
+ $groups,
+ $cascadedGroups,
+ $traversalStrategy,
+ $context
+ );
+ } else {
+ $this->validateGenericNode(
+ $value,
+ $object,
+ $cacheKey,
+ $metadata,
+ $propertyPath,
+ $groups,
+ $cascadedGroups,
+ $traversalStrategy,
+ $context
+ );
+ }
+
+ // Abort sequence validation if a violation was generated
+ if (\count($context->getViolations()) > $violationCount) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Validates a node's value against all constraints in the given group.
+ *
+ * @param mixed $value The validated value
+ * @param string $cacheKey The key for caching the
+ * validated value
+ * @param MetadataInterface $metadata The metadata of the value
+ * @param string $group The group to validate
+ * @param ExecutionContextInterface $context The execution context
+ */
+ private function validateInGroup($value, $cacheKey, MetadataInterface $metadata, $group, ExecutionContextInterface $context)
+ {
+ $context->setGroup($group);
+
+ foreach ($metadata->findConstraints($group) as $constraint) {
+ // Prevent duplicate validation of constraints, in the case
+ // that constraints belong to multiple validated groups
+ if (null !== $cacheKey) {
+ $constraintHash = spl_object_hash($constraint);
+
+ if ($context->isConstraintValidated($cacheKey, $constraintHash)) {
+ continue;
+ }
+
+ $context->markConstraintAsValidated($cacheKey, $constraintHash);
+ }
+
+ $context->setConstraint($constraint);
+
+ $validator = $this->validatorFactory->getInstance($constraint);
+ $validator->initialize($context);
+ $validator->validate($value, $constraint);
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validator/RecursiveValidator.php b/public/system/storage/vendor/symfony/validator/Validator/RecursiveValidator.php
new file mode 100644
index 0000000..bf0050d
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validator/RecursiveValidator.php
@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Validator;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\Constraints\Valid;
+use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
+use Symfony\Component\Validator\Context\ExecutionContextFactoryInterface;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\MetadataFactoryInterface;
+use Symfony\Component\Validator\ObjectInitializerInterface;
+use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface;
+
+/**
+ * Recursive implementation of {@link ValidatorInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class RecursiveValidator implements ValidatorInterface, LegacyValidatorInterface
+{
+ protected $contextFactory;
+ protected $metadataFactory;
+ protected $validatorFactory;
+ protected $objectInitializers;
+
+ /**
+ * Creates a new validator.
+ *
+ * @param ExecutionContextFactoryInterface $contextFactory The factory for
+ * creating new contexts
+ * @param MetadataFactoryInterface $metadataFactory The factory for
+ * fetching the metadata
+ * of validated objects
+ * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating
+ * constraint validators
+ * @param ObjectInitializerInterface[] $objectInitializers The object initializers
+ */
+ public function __construct(ExecutionContextFactoryInterface $contextFactory, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, array $objectInitializers = array())
+ {
+ $this->contextFactory = $contextFactory;
+ $this->metadataFactory = $metadataFactory;
+ $this->validatorFactory = $validatorFactory;
+ $this->objectInitializers = $objectInitializers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function startContext($root = null)
+ {
+ return new RecursiveContextualValidator(
+ $this->contextFactory->createContext($this, $root),
+ $this->metadataFactory,
+ $this->validatorFactory,
+ $this->objectInitializers
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function inContext(ExecutionContextInterface $context)
+ {
+ return new RecursiveContextualValidator(
+ $context,
+ $this->metadataFactory,
+ $this->validatorFactory,
+ $this->objectInitializers
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFor($object)
+ {
+ return $this->metadataFactory->getMetadataFor($object);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasMetadataFor($object)
+ {
+ return $this->metadataFactory->hasMetadataFor($object);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $groups = null, $traverse = false, $deep = false)
+ {
+ $numArgs = \func_num_args();
+
+ // Use new signature if constraints are given in the second argument
+ if (self::testConstraints($groups) && ($numArgs < 3 || 3 === $numArgs && self::testGroups($traverse))) {
+ // Rename to avoid total confusion ;)
+ $constraints = $groups;
+ $groups = $traverse;
+ } else {
+ @trigger_error('The Symfony\Component\Validator\ValidatorInterface::validate method is deprecated in version 2.5 and will be removed in version 3.0. Use the Symfony\Component\Validator\Validator\ValidatorInterface::validate method instead.', E_USER_DEPRECATED);
+
+ $constraints = new Valid(array('traverse' => $traverse, 'deep' => $deep));
+ }
+
+ return $this->startContext($value)
+ ->validate($value, $constraints, $groups)
+ ->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateProperty($object, $propertyName, $groups = null)
+ {
+ return $this->startContext($object)
+ ->validateProperty($object, $propertyName, $groups)
+ ->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null)
+ {
+ // If a class name is passed, take $value as root
+ return $this->startContext(\is_object($objectOrClass) ? $objectOrClass : $value)
+ ->validatePropertyValue($objectOrClass, $propertyName, $value, $groups)
+ ->getViolations();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateValue($value, $constraints, $groups = null)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated in version 2.5 and will be removed in version 3.0. Use the Symfony\Component\Validator\Validator\ValidatorInterface::validate method instead.', E_USER_DEPRECATED);
+
+ return $this->validate($value, $constraints, $groups);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFactory()
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated in version 2.5 and will be removed in version 3.0. Use the Symfony\Component\Validator\Validator\ValidatorInterface::getMetadataFor or Symfony\Component\Validator\Validator\ValidatorInterface::hasMetadataFor method instead.', E_USER_DEPRECATED);
+
+ return $this->metadataFactory;
+ }
+
+ private static function testConstraints($constraints)
+ {
+ return null === $constraints || $constraints instanceof Constraint || (\is_array($constraints) && (0 === \count($constraints) || current($constraints) instanceof Constraint));
+ }
+
+ private static function testGroups($groups)
+ {
+ return null === $groups || \is_string($groups) || $groups instanceof GroupSequence || (\is_array($groups) && (0 === \count($groups) || \is_string(current($groups)) || current($groups) instanceof GroupSequence));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Validator/ValidatorInterface.php b/public/system/storage/vendor/symfony/validator/Validator/ValidatorInterface.php
new file mode 100644
index 0000000..7815746
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Validator/ValidatorInterface.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Validator;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\GroupSequence;
+use Symfony\Component\Validator\ConstraintViolationListInterface;
+use Symfony\Component\Validator\Context\ExecutionContextInterface;
+use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
+
+/**
+ * Validates PHP values against constraints.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ValidatorInterface extends MetadataFactoryInterface
+{
+ /**
+ * Validates a value against a constraint or a list of constraints.
+ *
+ * If no constraint is passed, the constraint
+ * {@link \Symfony\Component\Validator\Constraints\Valid} is assumed.
+ *
+ * @param mixed $value The value to validate
+ * @param Constraint|Constraint[] $constraints The constraint(s) to validate against
+ * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations
+ * If the list is empty, validation
+ * succeeded
+ */
+ public function validate($value, $constraints = null, $groups = null);
+
+ /**
+ * Validates a property of an object against the constraints specified
+ * for this property.
+ *
+ * @param object $object The object
+ * @param string $propertyName The name of the validated property
+ * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations
+ * If the list is empty, validation
+ * succeeded
+ */
+ public function validateProperty($object, $propertyName, $groups = null);
+
+ /**
+ * Validates a value against the constraints specified for an object's
+ * property.
+ *
+ * @param object|string $objectOrClass The object or its class name
+ * @param string $propertyName The name of the property
+ * @param mixed $value The value to validate against the property's constraints
+ * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations
+ * If the list is empty, validation
+ * succeeded
+ */
+ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null);
+
+ /**
+ * Starts a new validation context and returns a validator for that context.
+ *
+ * The returned validator collects all violations generated within its
+ * context. You can access these violations with the
+ * {@link ContextualValidatorInterface::getViolations()} method.
+ *
+ * @return ContextualValidatorInterface The validator for the new context
+ */
+ public function startContext();
+
+ /**
+ * Returns a validator in the given execution context.
+ *
+ * The returned validator adds all generated violations to the given
+ * context.
+ *
+ * @return ContextualValidatorInterface The validator for that context
+ */
+ public function inContext(ExecutionContextInterface $context);
+}
diff --git a/public/system/storage/vendor/symfony/validator/ValidatorBuilder.php b/public/system/storage/vendor/symfony/validator/ValidatorBuilder.php
new file mode 100644
index 0000000..c99de8c
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ValidatorBuilder.php
@@ -0,0 +1,372 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+use Doctrine\Common\Annotations\AnnotationReader;
+use Doctrine\Common\Annotations\CachedReader;
+use Doctrine\Common\Annotations\Reader;
+use Doctrine\Common\Cache\ArrayCache;
+use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Context\ExecutionContextFactory;
+use Symfony\Component\Validator\Exception\InvalidArgumentException;
+use Symfony\Component\Validator\Exception\ValidatorException;
+use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
+use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
+use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
+use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
+use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
+use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
+use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader;
+use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
+use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader;
+use Symfony\Component\Validator\Validator\RecursiveValidator;
+
+/**
+ * The default implementation of {@link ValidatorBuilderInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class ValidatorBuilder implements ValidatorBuilderInterface
+{
+ private $initializers = array();
+ private $xmlMappings = array();
+ private $yamlMappings = array();
+ private $methodMappings = array();
+
+ /**
+ * @var Reader|null
+ */
+ private $annotationReader;
+
+ /**
+ * @var MetadataFactoryInterface|null
+ */
+ private $metadataFactory;
+
+ /**
+ * @var ConstraintValidatorFactoryInterface|null
+ */
+ private $validatorFactory;
+
+ /**
+ * @var CacheInterface|null
+ */
+ private $metadataCache;
+
+ /**
+ * @var TranslatorInterface|null
+ */
+ private $translator;
+
+ /**
+ * @var string|null
+ */
+ private $translationDomain;
+
+ /**
+ * @var PropertyAccessorInterface|null
+ */
+ private $propertyAccessor;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addObjectInitializer(ObjectInitializerInterface $initializer)
+ {
+ $this->initializers[] = $initializer;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addObjectInitializers(array $initializers)
+ {
+ $this->initializers = array_merge($this->initializers, $initializers);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addXmlMapping($path)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->xmlMappings[] = $path;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addXmlMappings(array $paths)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->xmlMappings = array_merge($this->xmlMappings, $paths);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addYamlMapping($path)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->yamlMappings[] = $path;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addYamlMappings(array $paths)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->yamlMappings = array_merge($this->yamlMappings, $paths);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addMethodMapping($methodName)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->methodMappings[] = $methodName;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addMethodMappings(array $methodNames)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->methodMappings = array_merge($this->methodMappings, $methodNames);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enableAnnotationMapping(Reader $annotationReader = null)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ if (null === $annotationReader) {
+ if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) {
+ throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.');
+ }
+
+ $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache());
+ }
+
+ $this->annotationReader = $annotationReader;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function disableAnnotationMapping()
+ {
+ $this->annotationReader = null;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory)
+ {
+ if (\count($this->xmlMappings) > 0 || \count($this->yamlMappings) > 0 || \count($this->methodMappings) > 0 || null !== $this->annotationReader) {
+ throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.');
+ }
+
+ $this->metadataFactory = $metadataFactory;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMetadataCache(CacheInterface $cache)
+ {
+ if (null !== $this->metadataFactory) {
+ throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.');
+ }
+
+ $this->metadataCache = $cache;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory)
+ {
+ if (null !== $this->propertyAccessor) {
+ throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().');
+ }
+
+ $this->validatorFactory = $validatorFactory;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setTranslator(TranslatorInterface $translator)
+ {
+ $this->translator = $translator;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setTranslationDomain($translationDomain)
+ {
+ $this->translationDomain = $translationDomain;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * The validator will function without a property accessor.
+ */
+ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. The validator will function without a property accessor.', E_USER_DEPRECATED);
+
+ if (null !== $this->validatorFactory) {
+ throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.');
+ }
+
+ $this->propertyAccessor = $propertyAccessor;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @deprecated since version 2.7, to be removed in 3.0.
+ */
+ public function setApiVersion($apiVersion)
+ {
+ @trigger_error('The '.__METHOD__.' method is deprecated in version 2.7 and will be removed in version 3.0.', E_USER_DEPRECATED);
+
+ if (!\in_array($apiVersion, array(Validation::API_VERSION_2_4, Validation::API_VERSION_2_5, Validation::API_VERSION_2_5_BC))) {
+ throw new InvalidArgumentException(sprintf('The requested API version is invalid: "%s"', $apiVersion));
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValidator()
+ {
+ $metadataFactory = $this->metadataFactory;
+
+ if (!$metadataFactory) {
+ $loaders = array();
+
+ if (\count($this->xmlMappings) > 1) {
+ $loaders[] = new XmlFilesLoader($this->xmlMappings);
+ } elseif (1 === \count($this->xmlMappings)) {
+ $loaders[] = new XmlFileLoader($this->xmlMappings[0]);
+ }
+
+ if (\count($this->yamlMappings) > 1) {
+ $loaders[] = new YamlFilesLoader($this->yamlMappings);
+ } elseif (1 === \count($this->yamlMappings)) {
+ $loaders[] = new YamlFileLoader($this->yamlMappings[0]);
+ }
+
+ foreach ($this->methodMappings as $methodName) {
+ $loaders[] = new StaticMethodLoader($methodName);
+ }
+
+ if ($this->annotationReader) {
+ $loaders[] = new AnnotationLoader($this->annotationReader);
+ }
+
+ $loader = null;
+
+ if (\count($loaders) > 1) {
+ $loader = new LoaderChain($loaders);
+ } elseif (1 === \count($loaders)) {
+ $loader = $loaders[0];
+ }
+
+ $metadataFactory = new LazyLoadingMetadataFactory($loader, $this->metadataCache);
+ }
+
+ $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($this->propertyAccessor);
+ $translator = $this->translator;
+
+ if (null === $translator) {
+ $translator = new IdentityTranslator();
+ // Force the locale to be 'en' when no translator is provided rather than relying on the Intl default locale
+ // This avoids depending on Intl or the stub implementation being available. It also ensures that Symfony
+ // validation messages are pluralized properly even when the default locale gets changed because they are in
+ // English.
+ $translator->setLocale('en');
+ }
+
+ $contextFactory = new ExecutionContextFactory($translator, $this->translationDomain);
+
+ return new RecursiveValidator($contextFactory, $metadataFactory, $validatorFactory, $this->initializers);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/ValidatorBuilderInterface.php b/public/system/storage/vendor/symfony/validator/ValidatorBuilderInterface.php
new file mode 100644
index 0000000..1b0bd72
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ValidatorBuilderInterface.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+use Doctrine\Common\Annotations\Reader;
+use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
+
+/**
+ * A configurable builder for ValidatorInterface objects.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ValidatorBuilderInterface
+{
+ /**
+ * Adds an object initializer to the validator.
+ *
+ * @return $this
+ */
+ public function addObjectInitializer(ObjectInitializerInterface $initializer);
+
+ /**
+ * Adds a list of object initializers to the validator.
+ *
+ * @param ObjectInitializerInterface[] $initializers
+ *
+ * @return $this
+ */
+ public function addObjectInitializers(array $initializers);
+
+ /**
+ * Adds an XML constraint mapping file to the validator.
+ *
+ * @param string $path The path to the mapping file
+ *
+ * @return $this
+ */
+ public function addXmlMapping($path);
+
+ /**
+ * Adds a list of XML constraint mapping files to the validator.
+ *
+ * @param string[] $paths The paths to the mapping files
+ *
+ * @return $this
+ */
+ public function addXmlMappings(array $paths);
+
+ /**
+ * Adds a YAML constraint mapping file to the validator.
+ *
+ * @param string $path The path to the mapping file
+ *
+ * @return $this
+ */
+ public function addYamlMapping($path);
+
+ /**
+ * Adds a list of YAML constraint mappings file to the validator.
+ *
+ * @param string[] $paths The paths to the mapping files
+ *
+ * @return $this
+ */
+ public function addYamlMappings(array $paths);
+
+ /**
+ * Enables constraint mapping using the given static method.
+ *
+ * @param string $methodName The name of the method
+ *
+ * @return $this
+ */
+ public function addMethodMapping($methodName);
+
+ /**
+ * Enables constraint mapping using the given static methods.
+ *
+ * @param string[] $methodNames The names of the methods
+ *
+ * @return $this
+ */
+ public function addMethodMappings(array $methodNames);
+
+ /**
+ * Enables annotation based constraint mapping.
+ *
+ * @return $this
+ */
+ public function enableAnnotationMapping(Reader $annotationReader = null);
+
+ /**
+ * Disables annotation based constraint mapping.
+ *
+ * @return $this
+ */
+ public function disableAnnotationMapping();
+
+ /**
+ * Sets the class metadata factory used by the validator.
+ *
+ * @return $this
+ */
+ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory);
+
+ /**
+ * Sets the cache for caching class metadata.
+ *
+ * @return $this
+ */
+ public function setMetadataCache(CacheInterface $cache);
+
+ /**
+ * Sets the constraint validator factory used by the validator.
+ *
+ * @return $this
+ */
+ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory);
+
+ /**
+ * Sets the translator used for translating violation messages.
+ *
+ * @return $this
+ */
+ public function setTranslator(TranslatorInterface $translator);
+
+ /**
+ * Sets the default translation domain of violation messages.
+ *
+ * The same message can have different translations in different domains.
+ * Pass the domain that is used for violation messages by default to this
+ * method.
+ *
+ * @param string $translationDomain The translation domain of the violation messages
+ *
+ * @return $this
+ */
+ public function setTranslationDomain($translationDomain);
+
+ /**
+ * Sets the property accessor for resolving property paths.
+ *
+ * @param PropertyAccessorInterface $propertyAccessor The property accessor
+ *
+ * @return $this
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor);
+
+ /**
+ * Sets the API version that the returned validator should support.
+ *
+ * @param int $apiVersion The required API version
+ *
+ * @return $this
+ *
+ * @see Validation::API_VERSION_2_5
+ * @see Validation::API_VERSION_2_5_BC
+ * @deprecated since version 2.7, to be removed in 3.0.
+ */
+ public function setApiVersion($apiVersion);
+
+ /**
+ * Builds and returns a new validator object.
+ *
+ * @return ValidatorInterface The built validator
+ */
+ public function getValidator();
+}
diff --git a/public/system/storage/vendor/symfony/validator/ValidatorInterface.php b/public/system/storage/vendor/symfony/validator/ValidatorInterface.php
new file mode 100644
index 0000000..570ba99
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/ValidatorInterface.php
@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+/**
+ * Validates values and graphs of objects and arrays.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link \Symfony\Component\Validator\Validator\ValidatorInterface} instead.
+ */
+interface ValidatorInterface
+{
+ /**
+ * Validates a value.
+ *
+ * The accepted values depend on the {@link MetadataFactoryInterface}
+ * implementation.
+ *
+ * The signature changed with Symfony 2.5 (see
+ * {@link Validator\ValidatorInterface::validate()}. This signature will be
+ * disabled in Symfony 3.0.
+ *
+ * @param mixed $value The value to validate
+ * @param array|null $groups The validation groups to validate
+ * @param bool $traverse Whether to traverse the value if it is traversable
+ * @param bool $deep Whether to traverse nested traversable values recursively
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations. If the
+ * list is empty, validation succeeded.
+ */
+ public function validate($value, $groups = null, $traverse = false, $deep = false);
+
+ /**
+ * Validates a property of a value against its current value.
+ *
+ * The accepted values depend on the {@link MetadataFactoryInterface}
+ * implementation.
+ *
+ * @param mixed $containingValue The value containing the property
+ * @param string $property The name of the property to validate
+ * @param array|null $groups The validation groups to validate
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations. If the
+ * list is empty, validation succeeded.
+ */
+ public function validateProperty($containingValue, $property, $groups = null);
+
+ /**
+ * Validate a property of a value against a potential value.
+ *
+ * The accepted values depend on the {@link MetadataFactoryInterface}
+ * implementation.
+ *
+ * @param mixed $containingValue The value containing the property
+ * @param string $property The name of the property to validate
+ * @param string $value The value to validate against the
+ * constraints of the property
+ * @param array|null $groups The validation groups to validate
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations. If the
+ * list is empty, validation succeeded.
+ */
+ public function validatePropertyValue($containingValue, $property, $value, $groups = null);
+
+ /**
+ * Validates a value against a constraint or a list of constraints.
+ *
+ * @param mixed $value The value to validate
+ * @param Constraint|Constraint[] $constraints The constraint(s) to validate against
+ * @param array|null $groups The validation groups to validate
+ *
+ * @return ConstraintViolationListInterface A list of constraint violations. If the
+ * list is empty, validation succeeded.
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Renamed to {@link Validator\ValidatorInterface::validate()}
+ * in Symfony 2.5.
+ */
+ public function validateValue($value, $constraints, $groups = null);
+
+ /**
+ * Returns the factory for metadata instances.
+ *
+ * @return MetadataFactoryInterface The metadata factory
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ * Use {@link Validator\ValidatorInterface::getMetadataFor()} or
+ * {@link Validator\ValidatorInterface::hasMetadataFor()}
+ * instead.
+ */
+ public function getMetadataFactory();
+}
diff --git a/public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilder.php b/public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilder.php
new file mode 100644
index 0000000..284841e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilder.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Violation;
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintViolation;
+use Symfony\Component\Validator\ConstraintViolationList;
+use Symfony\Component\Validator\Util\PropertyPath;
+
+/**
+ * Default implementation of {@link ConstraintViolationBuilderInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @internal You should not instantiate or use this class. Code against
+ * {@link ConstraintViolationBuilderInterface} instead.
+ */
+class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
+{
+ private $violations;
+ private $message;
+ private $parameters;
+ private $root;
+ private $invalidValue;
+ private $propertyPath;
+ private $translator;
+ private $translationDomain;
+ private $plural;
+ private $constraint;
+ private $code;
+
+ /**
+ * @var mixed
+ */
+ private $cause;
+
+ public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, TranslatorInterface $translator, $translationDomain = null)
+ {
+ $this->violations = $violations;
+ $this->message = $message;
+ $this->parameters = $parameters;
+ $this->root = $root;
+ $this->propertyPath = $propertyPath;
+ $this->invalidValue = $invalidValue;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ $this->constraint = $constraint;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function atPath($path)
+ {
+ $this->propertyPath = PropertyPath::append($this->propertyPath, $path);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setParameter($key, $value)
+ {
+ $this->parameters[$key] = $value;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setParameters(array $parameters)
+ {
+ $this->parameters = $parameters;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setTranslationDomain($translationDomain)
+ {
+ $this->translationDomain = $translationDomain;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setInvalidValue($invalidValue)
+ {
+ $this->invalidValue = $invalidValue;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPlural($number)
+ {
+ $this->plural = $number;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCause($cause)
+ {
+ $this->cause = $cause;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addViolation()
+ {
+ if (null === $this->plural) {
+ $translatedMessage = $this->translator->trans(
+ $this->message,
+ $this->parameters,
+ $this->translationDomain
+ );
+ } else {
+ try {
+ $translatedMessage = $this->translator->transChoice(
+ $this->message,
+ $this->plural,
+ $this->parameters,
+ $this->translationDomain
+ );
+ } catch (\InvalidArgumentException $e) {
+ $translatedMessage = $this->translator->trans(
+ $this->message,
+ $this->parameters,
+ $this->translationDomain
+ );
+ }
+ }
+
+ $this->violations->add(new ConstraintViolation(
+ $translatedMessage,
+ $this->message,
+ $this->parameters,
+ $this->root,
+ $this->propertyPath,
+ $this->invalidValue,
+ $this->plural,
+ $this->code,
+ $this->constraint,
+ $this->cause
+ ));
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilderInterface.php b/public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilderInterface.php
new file mode 100644
index 0000000..811b484
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Violation/ConstraintViolationBuilderInterface.php
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Violation;
+
+/**
+ * Builds {@link \Symfony\Component\Validator\ConstraintViolationInterface}
+ * objects.
+ *
+ * Use the various methods on this interface to configure the built violation.
+ * Finally, call {@link addViolation()} to add the violation to the current
+ * execution context.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ConstraintViolationBuilderInterface
+{
+ /**
+ * Stores the property path at which the violation should be generated.
+ *
+ * The passed path will be appended to the current property path of the
+ * execution context.
+ *
+ * @param string $path The property path
+ *
+ * @return $this
+ */
+ public function atPath($path);
+
+ /**
+ * Sets a parameter to be inserted into the violation message.
+ *
+ * @param string $key The name of the parameter
+ * @param string $value The value to be inserted in the parameter's place
+ *
+ * @return $this
+ */
+ public function setParameter($key, $value);
+
+ /**
+ * Sets all parameters to be inserted into the violation message.
+ *
+ * @param array $parameters An array with the parameter names as keys and
+ * the values to be inserted in their place as
+ * values
+ *
+ * @return $this
+ */
+ public function setParameters(array $parameters);
+
+ /**
+ * Sets the translation domain which should be used for translating the
+ * violation message.
+ *
+ * @param string $translationDomain The translation domain
+ *
+ * @return $this
+ *
+ * @see \Symfony\Component\Translation\TranslatorInterface
+ */
+ public function setTranslationDomain($translationDomain);
+
+ /**
+ * Sets the invalid value that caused this violation.
+ *
+ * @param mixed $invalidValue The invalid value
+ *
+ * @return $this
+ */
+ public function setInvalidValue($invalidValue);
+
+ /**
+ * Sets the number which determines how the plural form of the violation
+ * message is chosen when it is translated.
+ *
+ * @param int $number The number for determining the plural form
+ *
+ * @return $this
+ *
+ * @see \Symfony\Component\Translation\TranslatorInterface::transChoice()
+ */
+ public function setPlural($number);
+
+ /**
+ * Sets the violation code.
+ *
+ * @param string|null $code The violation code
+ *
+ * @return $this
+ */
+ public function setCode($code);
+
+ /**
+ * Sets the cause of the violation.
+ *
+ * @param mixed $cause The cause of the violation
+ *
+ * @return $this
+ */
+ public function setCause($cause);
+
+ /**
+ * Adds the violation to the current execution context.
+ */
+ public function addViolation();
+}
diff --git a/public/system/storage/vendor/symfony/validator/Violation/LegacyConstraintViolationBuilder.php b/public/system/storage/vendor/symfony/validator/Violation/LegacyConstraintViolationBuilder.php
new file mode 100644
index 0000000..324e9d1
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/Violation/LegacyConstraintViolationBuilder.php
@@ -0,0 +1,166 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Violation;
+
+@trigger_error('The '.__NAMESPACE__.'\LegacyConstraintViolationBuilder class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+use Symfony\Component\Validator\ExecutionContextInterface;
+
+/**
+ * Backwards-compatible implementation of {@link ConstraintViolationBuilderInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @internal You should not instantiate or use this class. Code against
+ * {@link ConstraintViolationBuilderInterface} instead.
+ *
+ * @deprecated since version 2.5.5, to be removed in 3.0.
+ */
+class LegacyConstraintViolationBuilder implements ConstraintViolationBuilderInterface
+{
+ /**
+ * @var ExecutionContextInterface
+ */
+ private $context;
+
+ /**
+ * @var string
+ */
+ private $message;
+
+ /**
+ * @var array
+ */
+ private $parameters;
+
+ /**
+ * @var mixed
+ */
+ private $invalidValue;
+
+ /**
+ * @var string
+ */
+ private $propertyPath;
+
+ /**
+ * @var int|null
+ */
+ private $plural;
+
+ /**
+ * @var mixed
+ */
+ private $code;
+
+ public function __construct(ExecutionContextInterface $context, $message, array $parameters)
+ {
+ $this->context = $context;
+ $this->message = $message;
+ $this->parameters = $parameters;
+ $this->invalidValue = $context->getValue();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function atPath($path)
+ {
+ $this->propertyPath = $path;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setParameter($key, $value)
+ {
+ $this->parameters[$key] = $value;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setParameters(array $parameters)
+ {
+ $this->parameters = $parameters;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setTranslationDomain($translationDomain)
+ {
+ // can't be set in the old API
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setInvalidValue($invalidValue)
+ {
+ $this->invalidValue = $invalidValue;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPlural($number)
+ {
+ $this->plural = $number;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCause($cause)
+ {
+ // do nothing - we can't save the cause through the old API
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addViolation()
+ {
+ if ($this->propertyPath) {
+ $this->context->addViolationAt($this->propertyPath, $this->message, $this->parameters, $this->invalidValue, $this->plural, $this->code);
+
+ return;
+ }
+
+ $this->context->addViolation($this->message, $this->parameters, $this->invalidValue, $this->plural, $this->code);
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/composer.json b/public/system/storage/vendor/symfony/validator/composer.json
new file mode 100644
index 0000000..99ccc33
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/composer.json
@@ -0,0 +1,58 @@
+{
+ "name": "symfony/validator",
+ "type": "library",
+ "description": "Symfony Validator Component",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.9",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/translation": "~2.4|~3.0.0"
+ },
+ "require-dev": {
+ "symfony/http-foundation": "~2.3|~3.0.0",
+ "symfony/intl": "~2.7.25|^2.8.18|~3.2.5",
+ "symfony/yaml": "^2.0.5|~3.0.0",
+ "symfony/config": "~2.2|~3.0.0",
+ "symfony/property-access": "~2.3|~3.0.0",
+ "symfony/expression-language": "~2.4|~3.0.0",
+ "doctrine/annotations": "~1.0",
+ "doctrine/cache": "~1.0",
+ "egulias/email-validator": "^1.2.1"
+ },
+ "suggest": {
+ "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
+ "doctrine/cache": "For using the default cached annotation reader and metadata cache.",
+ "symfony/http-foundation": "",
+ "symfony/intl": "",
+ "symfony/yaml": "",
+ "symfony/config": "",
+ "egulias/email-validator": "Strict (RFC compliant) email validation",
+ "symfony/property-access": "For using the 2.4 Validator API",
+ "symfony/expression-language": "For using the 2.4 Expression validator"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Validator\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/symfony/validator/phpunit.xml.dist b/public/system/storage/vendor/symfony/validator/phpunit.xml.dist
new file mode 100644
index 0000000..5d07c4e
--- /dev/null
+++ b/public/system/storage/vendor/symfony/validator/phpunit.xml.dist
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
+ backupGlobals="false"
+ colors="true"
+ bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
+>
+ <php>
+ <ini name="error_reporting" value="-1" />
+ </php>
+
+ <testsuites>
+ <testsuite name="Symfony Validator Component Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Resources</directory>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/.gitignore b/public/system/storage/vendor/zoujingli/wechat-php-sdk/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/MIT-LICENSE.txt b/public/system/storage/vendor/zoujingli/wechat-php-sdk/MIT-LICENSE.txt
new file mode 100644
index 0000000..0624076
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/MIT-LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2014-2017 Anyon<zoujingli@qq.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/README.md b/public/system/storage/vendor/zoujingli/wechat-php-sdk/README.md
new file mode 100644
index 0000000..3463565
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/README.md
@@ -0,0 +1,89 @@
+[![Latest Stable Version](https://poser.pugx.org/zoujingli/wechat-php-sdk/v/stable)](https://packagist.org/packages/zoujingli/wechat-php-sdk)
+[![Total Downloads](https://poser.pugx.org/zoujingli/wechat-php-sdk/downloads)](https://packagist.org/packages/zoujingli/wechat-php-sdk)
+[![Latest Unstable Version](https://poser.pugx.org/zoujingli/wechat-php-sdk/v/unstable)](https://packagist.org/packages/zoujingli/wechat-php-sdk)
+[![License](https://poser.pugx.org/zoujingli/wechat-php-sdk/license)](https://packagist.org/packages/zoujingli/wechat-php-sdk)
+
+此`SDK`运行最底要求`PHP`版本`5.3`, 建议在`PHP7`上运行以获取最佳性能。
+
+微信的部分接口需要缓存数据在本地,因此对目录需要有写权限。
+
+我们鼓励大家使用`composer`来管理您的第三方库,方便后期更新操作(尤其是接口类)。
+
+近期`access_token`经常无故失效,`SDK`已加入失败状态检测,自动重新获取`access_token`并返回结果.
+
+此`SDK`已历经数个线上项目验证与考验,可靠性与稳定性极高,欢迎`fork`或`star`此项目。
+
+# 新微信开发工具推荐
+WeChatDeveloper:https://github.com/zoujingli/WeChatDeveloper
+
+**微信SDK开发帮助及交流**
+--
+* **在做微信开发前,必需先阅读微信官方文档,此SDK也是基于之上进行的封装。**
+
+* **文档链接地址**:http://www.kancloud.cn/zoujingli/wechat-php-sdk
+
+* **Think.Admin**:https://github.com/zoujingli/Think.Admin
+
+* **开发交流QQ群:513350915(新)**
+
+**若对您有帮助,可以赞助并支持下作者哦,谢谢!**
+--
+![](http://plugs.ctolog.com/pay.png)
+
+
+**官方接口文档链接**
+--
+* 使用前需先打开微信帐号的开发模式,详细步骤请查看微信公众平台接口使用说明:
+* 微信公众平台: http://mp.weixin.qq.com/wiki/
+* 微信企业平台: http://qydev.weixin.qq.com/wiki/
+* 微信开放平台:https://open.weixin.qq.com/
+* 微信支付接入文档:https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
+* 微信商户平台:https://pay.weixin.qq.com
+
+**微信`SDK`项目源文件托管**
+--
+* SDK 为开源项目,你可以把它用于任何地址,并不受任何约束,欢迎`fork`项目。
+* 通过 [Github](https://github.com/zoujingli/wechat-php-sdk) 下载 SDK 源代码
+* 通过 [OSChina](http://git.oschina.net/zoujingli/wechat-php-sdk) 下载 SDK 源代码
+* 通过 [Composer](https://getcomposer.org) 包管理工具下载 SDK 源代码
+
+**微信`SDK`封装对接及功能**
+--
+* 接入验证 (初级权限)
+* 自动回复(文本、图片、语音、视频、音乐、图文) (初级权限)
+* 菜单操作(查询、创建、删除) (菜单权限)
+* 客服消息(文本、图片、语音、视频、音乐、图文) (认证权限)
+* 二维码(创建临时、永久二维码,获取二维码URL) (服务号、认证权限)
+* 长链接转短链接接口 (服务号、认证权限)
+* 标签操作(查询、创建、修改、移动用户到标签) (认证权限)
+* 网页授权(基本授权,用户信息授权) (服务号、认证权限)
+* 用户信息(查询用户基本信息、获取关注者列表) (认证权限)
+* 多客服功能(客服管理、获取客服记录、客服会话管理) (认证权限)
+* 媒体文件(上传、获取) (认证权限)
+* 高级群发 (认证权限)
+* 模板消息(设置所属行业、添加模板、发送模板消息) (服务号、认证权限)
+* 卡券管理(创建、修改、删除、发放、门店管理等) (认证权限)
+* 语义理解 (服务号、认证权限)
+* 获取微信服务器IP列表 (初级权限)
+* 微信JSAPI授权(获取ticket、获取签名) (初级权限)
+* 数据统计(用户、图文、消息、接口分析数据) (认证权限)
+* 微信支付(网页支付、扫码支付、交易退款、给粉丝打款)(认证服务号并开通支付功能)
+
+**接口权限备注:**
+--
+* 初级权限:基本权限,任何正常的公众号都有此权限
+* 菜单权限:正常的服务号、认证后的订阅号拥有此权限
+* 认证权限:分为订阅号、服务号认证,如前缀服务号则仅认证的服务号有此权限
+* 支付权限:仅认证后的服务号可以申请此权限
+
+**微信开放第三方平台** --- (案例及文档整理中)
+--
+* 公众号授权服务
+* 公众号推送消息代处理
+* 公众号基础业务代处理
+* 公众号支付代发起
+
+**微信`SDK`版权声明**
+--
+* 此SDK基于`MIT`协议发布,任何人可以用在任何地方,不受约束
+* 此SDK部分代码来自互联网,若有异议,可以联系作者进行删除
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Cache.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Cache.php
new file mode 100644
index 0000000..ee10b87
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Cache.php
@@ -0,0 +1,146 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+
+namespace Wechat\Lib;
+
+use Wechat\Loader;
+
+/**
+ * 微信SDK基础缓存类
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016-08-20 17:50
+ */
+class Cache
+{
+
+ /**
+ * 缓存位置
+ * @var string
+ */
+ static public $cachepath;
+
+ /**
+ * 设置缓存
+ * @param string $name
+ * @param string $value
+ * @param int $expired
+ * @return mixed
+ */
+ static public function set($name, $value, $expired = 0)
+ {
+ if (isset(Loader::$callback['CacheSet'])) {
+ return call_user_func_array(Loader::$callback['CacheSet'], func_get_args());
+ }
+ $data = serialize(array('value' => $value, 'expired' => $expired > 0 ? time() + $expired : 0));
+ return self::check() && file_put_contents(self::$cachepath . $name, $data);
+ }
+
+ /**
+ * 读取缓存
+ * @param string $name
+ * @return mixed
+ */
+ static public function get($name)
+ {
+ if (isset(Loader::$callback['CacheGet'])) {
+ return call_user_func_array(Loader::$callback['CacheGet'], func_get_args());
+ }
+ if (self::check() && ($file = self::$cachepath . $name) && file_exists($file) && ($data = file_get_contents($file)) && !empty($data)) {
+ $data = unserialize($data);
+ if (isset($data['expired']) && ($data['expired'] > time() || $data['expired'] === 0)) {
+ return isset($data['value']) ? $data['value'] : null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 删除缓存
+ * @param string $name
+ * @return mixed
+ */
+ static public function del($name)
+ {
+ if (isset(Loader::$callback['CacheDel'])) {
+ return call_user_func_array(Loader::$callback['CacheDel'], func_get_args());
+ }
+ return self::check() && @unlink(self::$cachepath . $name);
+ }
+
+ /**
+ * 输出内容到日志
+ * @param string $line
+ * @param string $filename
+ * @return mixed
+ */
+ static public function put($line, $filename = '')
+ {
+ if (isset(Loader::$callback['CachePut'])) {
+ return call_user_func_array(Loader::$callback['CachePut'], func_get_args());
+ }
+ empty($filename) && $filename = date('Ymd') . '.log';
+ return self::check() && file_put_contents(self::$cachepath . $filename, '[' . date('Y/m/d H:i:s') . "] {$line}\n", FILE_APPEND);
+ }
+
+ /**
+ * 检查缓存目录
+ * @return bool
+ */
+ static protected function check()
+ {
+ empty(self::$cachepath) && self::$cachepath = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Cache' . DIRECTORY_SEPARATOR;
+ self::$cachepath = rtrim(self::$cachepath, '/\\') . DIRECTORY_SEPARATOR;
+ if (!is_dir(self::$cachepath) && !mkdir(self::$cachepath, 0755, true)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 文件缓存,成功返回文件路径
+ * @param string $content 文件内容
+ * @param string $filename 文件名称
+ * @return bool|string
+ */
+ static public function file($content, $filename = '')
+ {
+ if (isset(Loader::$callback['CacheFile'])) {
+ return call_user_func_array(Loader::$callback['CacheFile'], func_get_args());
+ }
+ empty($filename) && $filename = md5($content) . '.' . self::getFileExt($content);
+ if (self::check() && file_put_contents(self::$cachepath . $filename, $content)) {
+ return self::$cachepath . $filename;
+ }
+ return false;
+ }
+
+ /**
+ * 根据文件流读取文件后缀
+ * @param string $content
+ * @return string
+ */
+ static public function getFileExt($content)
+ {
+ $types = array(
+ 255216 => 'jpg', 7173 => 'gif', 6677 => 'bmp', 13780 => 'png',
+ 7368 => 'mp3', 4838 => 'wma', 7784 => 'mid', 6063 => 'xml',
+ );
+ $typeInfo = @unpack("C2chars", substr($content, 0, 2));
+ $typeCode = intval($typeInfo['chars1'] . $typeInfo['chars2']);
+ return isset($types[$typeCode]) ? $types[$typeCode] : 'mp4';
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Common.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Common.php
new file mode 100644
index 0000000..11df686
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Common.php
@@ -0,0 +1,234 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat\Lib;
+
+use Prpcrypt;
+use Wechat\Loader;
+
+/**
+ * 微信SDK基础类
+ *
+ * @category WechatSDK
+ * @subpackage library
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/05/28 11:55
+ */
+class Common
+{
+
+ /** API接口URL需要使用此前缀 */
+ const API_BASE_URL_PREFIX = 'https://api.weixin.qq.com';
+ const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';
+ const GET_TICKET_URL = '/ticket/getticket?';
+ const AUTH_URL = '/token?grant_type=client_credential&';
+ public $token;
+ public $encodingAesKey;
+ public $encrypt_type;
+ public $appid;
+ public $appsecret;
+ public $access_token;
+ public $postxml;
+ public $_msg;
+ public $errCode = 0;
+ public $errMsg = "";
+ public $config = array();
+ private $_retry = false;
+
+ /**
+ * 构造方法
+ * @param array $options
+ */
+ public function __construct($options = array())
+ {
+ $config = Loader::config($options);
+ $this->token = isset($config['token']) ? $config['token'] : '';
+ $this->appid = isset($config['appid']) ? $config['appid'] : '';
+ $this->appsecret = isset($config['appsecret']) ? $config['appsecret'] : '';
+ $this->encodingAesKey = isset($config['encodingaeskey']) ? $config['encodingaeskey'] : '';
+ $this->config = $config;
+ }
+
+ /**
+ * 当前当前错误代码
+ * @return int
+ */
+ public function getErrorCode()
+ {
+ return $this->errCode;
+ }
+
+ /**
+ * 获取当前错误内容
+ * @return string
+ */
+ public function getError()
+ {
+ return $this->errMsg;
+ }
+
+ /**
+ * 获取当前操作公众号APPID
+ * @return string
+ */
+ public function getAppid()
+ {
+ return $this->appid;
+ }
+
+ /**
+ * 获取SDK配置参数
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+
+ /**
+ * 接口验证
+ * @return bool
+ */
+ public function valid()
+ {
+ $encryptStr = "";
+ if ($_SERVER['REQUEST_METHOD'] == "POST") {
+ $postStr = file_get_contents("php://input");
+ $disableEntities = libxml_disable_entity_loader(true);
+ $array = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
+ libxml_disable_entity_loader($disableEntities);
+ $this->encrypt_type = isset($_GET["encrypt_type"]) ? $_GET["encrypt_type"] : '';
+ if ($this->encrypt_type == 'aes') {
+ $encryptStr = $array['Encrypt'];
+ !class_exists('Prpcrypt', false) && require __DIR__ . '/Prpcrypt.php';
+ $pc = new Prpcrypt($this->encodingAesKey);
+ $array = $pc->decrypt($encryptStr, $this->appid);
+ if (!isset($array[0]) || intval($array[0]) > 0) {
+ $this->errCode = $array[0];
+ $this->errMsg = $array[1];
+ Tools::log("Interface Authentication Failed. {$this->errMsg}[{$this->errCode}]", "ERR - {$this->appid}");
+ return false;
+ }
+ $this->postxml = $array[1];
+ empty($this->appid) && $this->appid = $array[2];
+ } else {
+ $this->postxml = $postStr;
+ }
+ } elseif (isset($_GET["echostr"])) {
+ if ($this->checkSignature()) {
+ @ob_clean();
+ exit($_GET["echostr"]);
+ }
+ return false;
+ }
+ if (!$this->checkSignature($encryptStr)) {
+ $this->errMsg = 'Interface authentication failed, please use the correct method to call.';
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 验证来自微信服务器
+ * @param string $str
+ * @return bool
+ */
+ private function checkSignature($str = '')
+ {
+ $signature = isset($_GET["msg_signature"]) ? $_GET["msg_signature"] : (isset($_GET["signature"]) ? $_GET["signature"] : '');
+ $timestamp = isset($_GET["timestamp"]) ? $_GET["timestamp"] : '';
+ $nonce = isset($_GET["nonce"]) ? $_GET["nonce"] : '';
+ $tmpArr = array($this->token, $timestamp, $nonce, $str);
+ sort($tmpArr, SORT_STRING);
+ if (sha1(implode($tmpArr)) == $signature) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 获取公众号访问 access_token
+ * @param string $appid 如在类初始化时已提供,则可为空
+ * @param string $appsecret 如在类初始化时已提供,则可为空
+ * @param string $token 手动指定access_token,非必要情况不建议用
+ * @return bool|string
+ */
+ public function getAccessToken($appid = '', $appsecret = '', $token = '')
+ {
+ if (!$appid || !$appsecret) {
+ list($appid, $appsecret) = array($this->appid, $this->appsecret);
+ }
+ if ($token) {
+ return $this->access_token = $token;
+ }
+ $cache = 'wechat_access_token_' . $appid;
+ if (($access_token = Tools::getCache($cache)) && !empty($access_token)) {
+ return $this->access_token = $access_token;
+ }
+ # 检测事件注册
+ if (isset(Loader::$callback[__FUNCTION__])) {
+ return $this->access_token = call_user_func_array(Loader::$callback[__FUNCTION__], array(&$this, &$cache));
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::AUTH_URL . 'appid=' . $appid . '&secret=' . $appsecret);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (!$json || isset($json['errcode'])) {
+ $this->errCode = $json['errcode'];
+ $this->errMsg = $json['errmsg'];
+ Tools::log("Get New AccessToken Error. {$this->errMsg}[{$this->errCode}]", "ERR - {$this->appid}");
+ return false;
+ }
+ $this->access_token = $json['access_token'];
+ Tools::log("Get New AccessToken Success.", "MSG - {$this->appid}");
+ Tools::setCache($cache, $this->access_token, 5000);
+ return $this->access_token;
+ }
+ return false;
+ }
+
+ /**
+ * 接口失败重试
+ * @param string $method SDK方法名称
+ * @param array $arguments SDK方法参数
+ * @return bool|mixed
+ */
+ protected function checkRetry($method, $arguments = array())
+ {
+ Tools::log("Run {$method} Faild. {$this->errMsg}[{$this->errCode}]", "ERR - {$this->appid}");
+ if (!$this->_retry && in_array($this->errCode, array('40014', '40001', '41001', '42001'))) {
+ ($this->_retry = true) && $this->resetAuth();
+ $this->errCode = 40001;
+ $this->errMsg = 'no access';
+ Tools::log("Retry Run {$method} ...", "MSG - {$this->appid}");
+ return call_user_func_array(array($this, $method), $arguments);
+ }
+ return false;
+ }
+
+ /**
+ * 删除验证数据
+ * @param string $appid 如在类初始化时已提供,则可为空
+ * @return bool
+ */
+ public function resetAuth($appid = '')
+ {
+ $authname = 'wechat_access_token_' . (empty($appid) ? $this->appid : $appid);
+ Tools::log("Reset Auth And Remove Old AccessToken.", "MSG - {$this->appid}");
+ $this->access_token = '';
+ Tools::removeCache($authname);
+ return true;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Prpcrypt.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Prpcrypt.php
new file mode 100644
index 0000000..5830ea4
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Prpcrypt.php
@@ -0,0 +1,196 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+/**
+ * PKCS7算法 加解密
+ * @category WechatSDK
+ * @subpackage library
+ * @date 2016/06/28 11:59
+ */
+class PKCS7Encoder
+{
+
+ public static $block_size = 32;
+
+ /**
+ * 对需要加密的明文进行填充补位
+ * @param string $text 需要进行填充补位操作的明文
+ * @return string 补齐明文字符串
+ */
+ function encode($text)
+ {
+ $amount_to_pad = PKCS7Encoder::$block_size - (strlen($text) % PKCS7Encoder::$block_size);
+ if ($amount_to_pad == 0) {
+ $amount_to_pad = PKCS7Encoder::$block_size;
+ }
+ $pad_chr = chr($amount_to_pad);
+ $tmp = "";
+ for ($index = 0; $index < $amount_to_pad; $index++) {
+ $tmp .= $pad_chr;
+ }
+ return $text . $tmp;
+ }
+
+ /**
+ * 对解密后的明文进行补位删除
+ * @param string $text 解密后的明文
+ * @return string 删除填充补位后的明文
+ */
+ function decode($text)
+ {
+ $pad = ord(substr($text, -1));
+ if ($pad < 1 || $pad > PKCS7Encoder::$block_size) {
+ $pad = 0;
+ }
+ return substr($text, 0, (strlen($text) - $pad));
+ }
+
+}
+
+/**
+ * 接收和推送给公众平台消息的加解密
+ * @category WechatSDK
+ * @subpackage library
+ * @date 2016/06/28 11:59
+ */
+class Prpcrypt
+{
+
+ public $key;
+
+ function __construct($k)
+ {
+ $this->key = base64_decode($k . "=");
+ }
+
+ /**
+ * 对明文进行加密
+ * @param string $text 需要加密的明文
+ * @param string $appid 公众号APPID
+ * @return array
+ */
+ public function encrypt($text, $appid)
+ {
+ try {
+ //获得16位随机字符串,填充到明文之前
+ $random = $this->getRandomStr();//"aaaabbbbccccdddd";
+ $text = $random . pack("N", strlen($text)) . $text . $appid;
+ $iv = substr($this->key, 0, 16);
+ $pkc_encoder = new PKCS7Encoder;
+ $text = $pkc_encoder->encode($text);
+ $encrypted = openssl_encrypt($text, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
+ return array(ErrorCode::$OK, $encrypted);
+ } catch (Exception $e) {
+ return array(ErrorCode::$EncryptAESError, null);
+ }
+ }
+
+ /**
+ * 对密文进行解密
+ * @param string $encrypted 需要解密的密文
+ * @param string $appid 公众号APPID
+ * @return array
+ */
+ public function decrypt($encrypted, $appid)
+ {
+ try {
+ $iv = substr($this->key, 0, 16);
+ $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
+ } catch (Exception $e) {
+ return array(ErrorCode::$DecryptAESError, null);
+ }
+ try {
+ $pkc_encoder = new PKCS7Encoder;
+ $result = $pkc_encoder->decode($decrypted);
+ if (strlen($result) < 16) {
+ return array(ErrorCode::$DecryptAESError, null);
+ }
+ $content = substr($result, 16, strlen($result));
+ $len_list = unpack("N", substr($content, 0, 4));
+ $xml_len = $len_list[1];
+ $xml_content = substr($content, 4, $xml_len);
+ $from_appid = substr($content, $xml_len + 4);
+ return array(0, $xml_content, $from_appid);
+ } catch (Exception $e) {
+ return array(ErrorCode::$IllegalBuffer, null);
+ }
+
+ }
+
+ /**
+ * 随机生成16位字符串
+ * @return string 生成的字符串
+ */
+ function getRandomStr()
+ {
+ $str = "";
+ $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
+ $max = strlen($str_pol) - 1;
+ for ($i = 0; $i < 16; $i++) {
+ $str .= $str_pol[mt_rand(0, $max)];
+ }
+ return $str;
+ }
+
+}
+
+/**
+ * 仅用作类内部使用
+ * 不用于官方API接口的errCode码
+ * Class ErrorCode
+ */
+class ErrorCode
+{
+
+ public static $OK = 0;
+ public static $ValidateSignatureError = 40001;
+ public static $ParseXmlError = 40002;
+ public static $ComputeSignatureError = 40003;
+ public static $IllegalAesKey = 40004;
+ public static $ValidateAppidError = 40005;
+ public static $EncryptAESError = 40006;
+ public static $DecryptAESError = 40007;
+ public static $IllegalBuffer = 40008;
+ public static $EncodeBase64Error = 40009;
+ public static $DecodeBase64Error = 40010;
+ public static $GenReturnXmlError = 40011;
+ public static $errCode = array(
+ '0' => '处理成功',
+ '40001' => '校验签名失败',
+ '40002' => '解析xml失败',
+ '40003' => '计算签名失败',
+ '40004' => '不合法的AESKey',
+ '40005' => '校验AppID失败',
+ '40006' => 'AES加密失败',
+ '40007' => 'AES解密失败',
+ '40008' => '公众平台发送的xml不合法',
+ '40009' => 'Base64编码失败',
+ '40010' => 'Base64解码失败',
+ '40011' => '公众帐号生成回包xml失败'
+ );
+
+ /**
+ * 获取错误消息内容
+ * @param string $err
+ * @return bool
+ */
+ public static function getErrText($err)
+ {
+ if (isset(self::$errCode[$err])) {
+ return self::$errCode[$err];
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Tools.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Tools.php
new file mode 100644
index 0000000..6558a8e
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Lib/Tools.php
@@ -0,0 +1,308 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat\Lib;
+
+use CURLFile;
+
+/**
+ * 微信接口通用类
+ *
+ * @category WechatSDK
+ * @subpackage library
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/05/28 11:55
+ */
+class Tools
+{
+
+ /**
+ * 判断字符串是否经过编码方法
+ * @param string $str
+ * @return bool
+ */
+ static public function isBase64($str)
+ {
+ if ($str == base64_encode(base64_decode($str))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 产生随机字符串
+ * @param int $length 指定字符长度
+ * @param string $str 字符串前缀
+ * @return string
+ */
+ static public function createNoncestr($length = 32, $str = "")
+ {
+ $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
+ for ($i = 0; $i < $length; $i++) {
+ $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
+ }
+ return $str;
+ }
+
+ /**
+ * 数据生成签名
+ * @param array $data 签名数组
+ * @param string $method 签名方法
+ * @return bool|string 签名值
+ */
+ static public function getSignature($data, $method = "sha1")
+ {
+ if (!function_exists($method)) {
+ return false;
+ }
+ ksort($data);
+ $params = array();
+ foreach ($data as $key => $value) {
+ $params[] = "{$key}={$value}";
+ }
+ return $method(join('&', $params));
+ }
+
+ /**
+ * 生成支付签名
+ * @param array $option
+ * @param string $partnerKey
+ * @return string
+ */
+ static public function getPaySign($option, $partnerKey)
+ {
+ ksort($option);
+ $buff = '';
+ foreach ($option as $k => $v) {
+ $buff .= "{$k}={$v}&";
+ }
+ return strtoupper(md5("{$buff}key={$partnerKey}"));
+ }
+
+ /**
+ * XML编码
+ * @param mixed $data 数据
+ * @param string $root 根节点名
+ * @param string $item 数字索引的子节点名
+ * @param string $id 数字索引子节点key转换的属性名
+ * @return string
+ */
+ static public function arr2xml($data, $root = 'xml', $item = 'item', $id = 'id')
+ {
+ return "<{$root}>" . self::_data_to_xml($data, $item, $id) . "</{$root}>";
+ }
+
+ /**
+ * XML内容生成
+ * @param array $data 数据
+ * @param string $item 子节点
+ * @param string $id 节点ID
+ * @param string $content 节点内容
+ * @return string
+ */
+ static private function _data_to_xml($data, $item = 'item', $id = 'id', $content = '')
+ {
+ foreach ($data as $key => $val) {
+ is_numeric($key) && $key = "{$item} {$id}=\"{$key}\"";
+ $content .= "<{$key}>";
+ if (is_array($val) || is_object($val)) {
+ $content .= self::_data_to_xml($val);
+ } elseif (is_numeric($val)) {
+ $content .= $val;
+ } else {
+ $content .= '<![CDATA[' . preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/", '', $val) . ']]>';
+ }
+ list($_key, ) = explode(' ', $key . ' ');
+ $content .= "</$_key>";
+ }
+ return $content;
+ }
+
+ /**
+ * 将xml转为array
+ * @param string $xml
+ * @return array
+ */
+ static public function xml2arr($xml)
+ {
+ $disableEntities = libxml_disable_entity_loader(true);
+ $result = json_decode(Tools::json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
+ libxml_disable_entity_loader($disableEntities);
+ return $result;
+ }
+
+ /**
+ * 生成安全JSON数据
+ * @param array $array
+ * @return string
+ */
+ static public function json_encode($array)
+ {
+ return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function ($matches) {
+ return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE");
+ }, json_encode($array));
+ }
+
+ /**
+ * 以get方式提交请求
+ * @param $url
+ * @return bool|mixed
+ */
+ static public function httpGet($url)
+ {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($curl, CURLOPT_SSLVERSION, 1);
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
+ return (intval($status["http_code"]) === 200) ? $content : false;
+ }
+
+ /**
+ * 以post方式提交请求
+ * @param string $url
+ * @param array|string $data
+ * @return bool|mixed
+ */
+ static public function httpPost($url, $data)
+ {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildPost($data));
+ list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
+ return (intval($status["http_code"]) === 200) ? $content : false;
+ }
+
+ /**
+ * 使用证书,以post方式提交xml到对应的接口url
+ * @param string $url POST提交的内容
+ * @param array $data 请求的地址
+ * @param string $ssl_cer 证书Cer路径 | 证书内容
+ * @param string $ssl_key 证书Key路径 | 证书内容
+ * @param int $second 设置请求超时时间
+ * @return bool|mixed
+ */
+ static public function httpsPost($url, $data, $ssl_cer = null, $ssl_key = null, $second = 30)
+ {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_TIMEOUT, $second);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ if (!is_null($ssl_cer) && file_exists($ssl_cer) && is_file($ssl_cer)) {
+ curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
+ curl_setopt($curl, CURLOPT_SSLCERT, $ssl_cer);
+ }
+ if (!is_null($ssl_key) && file_exists($ssl_key) && is_file($ssl_key)) {
+ curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
+ curl_setopt($curl, CURLOPT_SSLKEY, $ssl_key);
+ }
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildPost($data));
+ list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
+ return (intval($status["http_code"]) === 200) ? $content : false;
+ }
+
+ /**
+ * POST数据过滤处理
+ * @param array $data
+ * @return array
+ */
+ static private function _buildPost(&$data)
+ {
+ if (is_array($data)) {
+ foreach ($data as &$value) {
+ if (is_string($value) && $value[0] === '@' && class_exists('CURLFile', false)) {
+ $filename = realpath(trim($value, '@'));
+ file_exists($filename) && $value = new CURLFile($filename);
+ }
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 读取微信客户端IP
+ * @return null|string
+ */
+ static public function getAddress()
+ {
+ foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP', 'REMOTE_ADDR') as $header) {
+ if (!isset($_SERVER[$header]) || ($spoof = $_SERVER[$header]) === null) {
+ continue;
+ }
+ sscanf($spoof, '%[^,]', $spoof);
+ if (!filter_var($spoof, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+ $spoof = null;
+ } else {
+ return $spoof;
+ }
+ }
+ return '0.0.0.0';
+ }
+
+ /**
+ * 设置缓存,按需重载
+ * @param string $cachename
+ * @param mixed $value
+ * @param int $expired
+ * @return bool
+ */
+ static public function setCache($cachename, $value, $expired = 0)
+ {
+ return Cache::set($cachename, $value, $expired);
+ }
+
+ /**
+ * 获取缓存,按需重载
+ * @param string $cachename
+ * @return mixed
+ */
+ static public function getCache($cachename)
+ {
+ return Cache::get($cachename);
+ }
+
+ /**
+ * 清除缓存,按需重载
+ * @param string $cachename
+ * @return bool
+ */
+ static public function removeCache($cachename)
+ {
+ return Cache::del($cachename);
+ }
+
+ /**
+ * SDK日志处理方法
+ * @param string $msg 日志行内容
+ * @param string $type 日志级别
+ */
+ static public function log($msg, $type = 'MSG')
+ {
+ Cache::put($type . ' - ' . $msg);
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Loader.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Loader.php
new file mode 100644
index 0000000..ff396b0
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/Loader.php
@@ -0,0 +1,129 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+
+namespace Wechat;
+
+use Wechat\Lib\Cache;
+
+/**
+ * 注册SDK自动加载机制
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/10/26 10:21
+ */
+spl_autoload_register(function ($class) {
+ if (0 === stripos($class, 'Wechat\\')) {
+ $filename = dirname(__DIR__) . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
+ file_exists($filename) && require($filename);
+ }
+});
+
+/**
+ * 微信SDK加载器
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016-08-21 11:06
+ */
+class Loader
+{
+
+ /**
+ * 事件注册函数
+ * @var array
+ */
+ static public $callback = array();
+
+ /**
+ * 配置参数
+ * @var array
+ */
+ static protected $config = array();
+
+ /**
+ * 对象缓存
+ * @var array
+ */
+ static protected $cache = array();
+
+ /**
+ * 动态注册SDK事件处理函数
+ * @param string $event 事件名称(getAccessToken|getJsTicket)
+ * @param string $method 处理方法(可以是普通方法或者类中的方法)
+ * @param string|null $class 处理对象(可以直接使用的类实例)
+ */
+ static public function register($event, $method, $class = null)
+ {
+ if (!empty($class) && class_exists($class, false) && method_exists($class, $method)) {
+ self::$callback[$event] = array($class, $method);
+ } else {
+ self::$callback[$event] = $method;
+ }
+ }
+
+ /**
+ * 获取微信SDK接口对象(别名函数)
+ * @param string $type 接口类型(Card|Custom|Device|Extends|Media|Menu|Oauth|Pay|Receive|Script|User|Poi)
+ * @param array $config SDK配置(token,appid,appsecret,encodingaeskey,mch_id,partnerkey,ssl_cer,ssl_key,qrc_img)
+ * @return WechatCard|WechatCustom|WechatDevice|WechatExtends|WechatMedia|WechatMenu|WechatOauth|WechatPay|WechatPoi|WechatReceive|WechatScript|WechatService|WechatUser
+ */
+ static public function & get_instance($type, $config = array())
+ {
+ return self::get($type, $config);
+ }
+
+ /**
+ * 获取微信SDK接口对象
+ * @param string $type 接口类型(Card|Custom|Device|Extends|Media|Menu|Oauth|Pay|Receive|Script|User|Poi)
+ * @param array $config SDK配置(token,appid,appsecret,encodingaeskey,mch_id,partnerkey,ssl_cer,ssl_key,qrc_img)
+ * @return WechatCard|WechatCustom|WechatDevice|WechatExtends|WechatMedia|WechatMenu|WechatOauth|WechatPay|WechatPoi|WechatReceive|WechatScript|WechatService|WechatUser
+ */
+ static public function & get($type, $config = array())
+ {
+ $index = md5(strtolower($type) . md5(json_encode(self::$config)));
+ if (!isset(self::$cache[$index])) {
+ $basicName = 'Wechat' . ucfirst(strtolower($type));
+ $className = "\\Wechat\\{$basicName}";
+ // 注册类的无命名空间别名,兼容未带命名空间的老版本SDK
+ !class_exists($basicName, false) && class_alias($className, $basicName);
+ self::$cache[$index] = new $className(self::config($config));
+ }
+ return self::$cache[$index];
+ }
+
+ /**
+ * 设置配置参数
+ * @param array $config
+ * @return array
+ */
+ static public function config($config = array())
+ {
+ !empty($config) && self::$config = array_merge(self::$config, $config);
+ if (!empty(self::$config['cachepath'])) {
+ Cache::$cachepath = self::$config['cachepath'];
+ }
+ if (empty(self::$config['component_verify_ticket'])) {
+ self::$config['component_verify_ticket'] = Cache::get('component_verify_ticket');
+ }
+ if (empty(self::$config['token']) && !empty(self::$config['component_token'])) {
+ self::$config['token'] = self::$config['component_token'];
+ }
+ if (empty(self::$config['appsecret']) && !empty(self::$config['component_appsecret'])) {
+ self::$config['appsecret'] = self::$config['component_appsecret'];
+ }
+ if (empty(self::$config['encodingaeskey']) && !empty(self::$config['component_encodingaeskey'])) {
+ self::$config['encodingaeskey'] = self::$config['component_encodingaeskey'];
+ }
+ return self::$config;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCard.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCard.php
new file mode 100644
index 0000000..b6dd385
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCard.php
@@ -0,0 +1,819 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信卡卷
+ */
+class WechatCard extends Common
+{
+
+ /** 卡券相关地址 */
+ const CARD_CREATE = '/card/create?';
+ // 删除卡卷
+ const CARD_DELETE = '/card/delete?';
+ // 更新卡卷信息
+ const CARD_UPDATE = '/card/update?';
+ // 获取卡卷详细信息
+ const CARD_GET = '/card/get?';
+ // 读取粉丝拥有的卡卷列表
+ const CARD_USER_GET_LIST = '/card/user/getcardlist?';
+ // 卡卷核查接口
+ const CARD_CHECKCODE = '/card/code/checkcode?';
+ // 卡卷图文群发获取HTML
+ const CARD_SET_SELFCONSUMECELL = '/card/selfconsumecell/set?';
+ const CARD_SEND_HTML = '/card/mpnews/gethtml?';
+ const CARD_BATCHGET = '/card/batchget?';
+ const CARD_MODIFY_STOCK = '/card/modifystock?';
+ const CARD_GETCOLORS = '/card/getcolors?';
+ const CARD_QRCODE_CREATE = '/card/qrcode/create?';
+ const CARD_CODE_CONSUME = '/card/code/consume?';
+ const CARD_CODE_DECRYPT = '/card/code/decrypt?';
+ const CARD_CODE_GET = '/card/code/get?';
+ const CARD_CODE_UPDATE = '/card/code/update?';
+ const CARD_CODE_UNAVAILABLE = '/card/code/unavailable?';
+ const CARD_TESTWHILELIST_SET = '/card/testwhitelist/set?';
+ const CARD_MEETINGCARD_UPDATEUSER = '/card/meetingticket/updateuser?'; //更新会议门票
+ const CARD_MEMBERCARD_ACTIVATE = '/card/membercard/activate?'; //激活会员卡
+ const CARD_MEMBERCARD_UPDATEUSER = '/card/membercard/updateuser?'; //更新会员卡
+ const CARD_MOVIETICKET_UPDATEUSER = '/card/movieticket/updateuser?'; //更新电影票(未加方法)
+ const CARD_BOARDINGPASS_CHECKIN = '/card/boardingpass/checkin?'; //飞机票-在线选座(未加方法)
+ /** 更新红包金额 */
+ const CARD_LUCKYMONEY_UPDATE = '/card/luckymoney/updateuserbalance?';
+ /*买单接口*/
+ const CARD_PAYCELL_SET = '/card/paycell/set?';
+ /*设置开卡字段接口*/
+ const CARD_MEMBERCARD_ACTIVATEUSERFORM_SET = '/card/membercard/activateuserform/set?';
+
+ /**
+ * 获取微信卡券 api_ticket
+ * @param string $appid
+ * @param string $jsapi_ticket
+ * @return bool|string
+ */
+ public function getJsCardTicket($appid = '', $jsapi_ticket = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $appid = empty($appid) ? $this->appid : $appid;
+ if ($jsapi_ticket) {
+ return $jsapi_ticket;
+ }
+ $authname = 'wechat_jsapi_ticket_wxcard_' . $appid;
+ if (($jsapi_ticket = Tools::getCache($authname))) {
+ return $jsapi_ticket;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::GET_TICKET_URL . "access_token={$this->access_token}&type=wx_card");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ $expire = $json['expires_in'] ? intval($json['expires_in']) - 100 : 3600;
+ Tools::setCache($authname, $json['ticket'], $expire);
+ return $json['ticket'];
+ }
+ return false;
+ }
+
+ /**
+ * 生成选择卡卷JS签名包
+ * @param string $cardid 卡券Id
+ * @param string $cardtype 卡券类型
+ * @param string $shopid 门店Id
+ * @return array
+ */
+ public function createChooseCardJsPackage($cardid = null, $cardtype = null, $shopid = null)
+ {
+ $data = array();
+ $data['api_ticket'] = $this->getJsCardTicket();
+ $data['app_id'] = $this->appid;
+ $data['timestamp'] = time();
+ $data['nonceStr'] = Tools::createNoncestr();
+ !empty($cardid) && $data['cardId'] = $cardid;
+ !empty($cardtype) && $data['cardType'] = $cardtype;
+ !empty($shopid) && $data['shopId'] = $shopid;
+ $data['cardSign'] = $this->getTicketSignature($data);
+ $data['signType'] = 'SHA1';
+ unset($data['api_ticket'], $data['app_id']);
+ return $data;
+ }
+
+ /**
+ * 生成添加卡卷JS签名包
+ * @param string|null $cardid 卡卷ID
+ * @param array $data 其它限定参数
+ * @return array
+ */
+ public function createAddCardJsPackage($cardid = null, $data = array())
+ {
+ $cardList = array();
+ if (is_array($cardid)) {
+ foreach ($cardid as $id) {
+ $cardList[] = array('cardId' => $id, 'cardExt' => json_encode($this->_cardSign($id, $data)));
+ }
+ } else {
+ $cardList[] = array('cardId' => $cardid, 'cardExt' => json_encode($this->_cardSign($cardid, $data)));
+ }
+ return array('cardList' => $cardList);
+ }
+
+ /**
+ * 卡券数据签名
+ * @param null|string $cardid
+ * @param array $attr
+ * @return array
+ */
+ private function _cardSign($cardid = null, $attr = array())
+ {
+ unset($attr['outer_id']);
+ $attr['cardId'] = $cardid;
+ $attr['timestamp'] = time();
+ $attr['api_ticket'] = $this->getJsCardTicket();
+ $attr['nonce_str'] = Tools::createNoncestr();
+ $attr['signature'] = $this->getTicketSignature($attr);
+ unset($attr['api_ticket']);
+ return $attr;
+ }
+
+ /**
+ * 获取微信卡券签名
+ * @param array $arrdata 签名数组
+ * @param string $method 签名方法
+ * @return bool|string 签名值
+ */
+ public function getTicketSignature($arrdata, $method = "sha1")
+ {
+ if (!function_exists($method)) {
+ return false;
+ }
+ $newArray = array();
+ foreach ($arrdata as $value) {
+ array_push($newArray, (string)$value);
+ }
+ sort($newArray, SORT_STRING);
+ return $method(implode($newArray));
+ }
+
+ /**
+ * 创建卡券
+ * @param array $data 卡券数据
+ * @return bool|array 返回数组中card_id为卡券ID
+ */
+ public function createCard($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CREATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 更改卡券信息
+ * 调用该接口更新信息后会重新送审,卡券状态变更为待审核。已被用户领取的卡券会实时更新票面信息。
+ * @param string $data
+ * @return bool
+ */
+ public function updateCard($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_UPDATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 删除卡券
+ * 允许商户删除任意一类卡券。删除卡券后,该卡券对应已生成的领取用二维码、添加到卡包 JS API 均会失效。
+ * 注意:删除卡券不能删除已被用户领取,保存在微信客户端中的卡券,已领取的卡券依旧有效。
+ * @param string $card_id 卡券ID
+ * @return bool
+ */
+ public function delCard($card_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('card_id' => $card_id);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_DELETE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 获取粉丝下所有卡卷列表
+ * @param $openid 粉丝openid
+ * @param string $card_id 卡卷ID(可不给)
+ * @return bool|array
+ */
+ public function getCardList($openid, $card_id = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid' => $openid);
+ !empty($card_id) && $data['card_id'] = $card_id;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_USER_GET_LIST . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取图文消息群发卡券HTML
+ * @param string $card_id 卡卷ID
+ * @return bool|array
+ */
+ public function getCardMpHtml($card_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('card_id' => $card_id);
+ !empty($card_id) && $data['card_id'] = $card_id;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_SEND_HTML . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 卡卷code核查
+ * @param string $card_id 卡卷ID
+ * @param array $code_list 卡卷code列表(一维数组)
+ * @return bool|array
+ */
+ public function checkCardCodeList($card_id, $code_list)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('card_id' => $card_id, 'code' => $code_list);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CHECKCODE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 查询卡券详情
+ * @param string $card_id 卡卷ID
+ * @return bool|array
+ */
+ public function getCardInfo($card_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('card_id' => $card_id);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_GET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取颜色列表
+ * 获得卡券的最新颜色列表,用于创建卡券
+ * @return bool|array
+ */
+ public function getCardColors()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::CARD_GETCOLORS . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 生成卡券二维码
+ * 成功则直接返回ticket值,可以用 getQRUrl($ticket) 换取二维码url
+ * @param string $card_id 卡券ID 必须
+ * @param string $code 指定卡券 code 码,只能被领一次。use_custom_code 字段为 true 的卡券必须填写,非自定义 code 不必填写。
+ * @param string $openid 指定领取者的 openid,只有该用户能领取。bind_openid 字段为 true 的卡券必须填写,非自定义 openid 不必填写。
+ * @param int $expire_seconds 指定二维码的有效时间,范围是 60 ~ 1800 秒。不填默认为永久有效。
+ * @param bool $is_unique_code 指定下发二维码,生成的二维码随机分配一个 code,领取后不可再次扫描。填写 true 或 false。默认 false。
+ * @param string $balance 红包余额,以分为单位。红包类型必填(LUCKY_MONEY),其他卡券类型不填。
+ * @return bool|string
+ */
+ public function createCardQrcode($card_id, $code = '', $openid = '', $expire_seconds = 0, $is_unique_code = false, $balance = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $card = array('card_id' => $card_id);
+ !empty($code) && $card['code'] = $code;
+ !empty($openid) && $card['openid'] = $openid;
+ !empty($is_unique_code) && $card['is_unique_code'] = $is_unique_code;
+ !empty($balance) && $card['balance'] = $balance;
+ $data = array('action_name' => "QR_CARD");
+ !empty($expire_seconds) && $data['expire_seconds'] = $expire_seconds;
+ $data['action_info'] = array('card' => $card);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_QRCODE_CREATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 消耗 code
+ * 自定义 code(use_custom_code 为 true)的优惠券,在 code 被核销时,必须调用此接口。
+ * @param string $code 要消耗的序列号
+ * @param string $card_id 要消耗序列号所述的 card_id,创建卡券时use_custom_code 填写 true 时必填。
+ * @return bool|array
+ * {
+ * "errcode":0,
+ * "errmsg":"ok",
+ * "card":{"card_id":"pFS7Fjg8kV1IdDz01r4SQwMkuCKc"},
+ * "openid":"oFS7Fjl0WsZ9AMZqrI80nbIq8xrA"
+ * }
+ */
+ public function consumeCardCode($code, $card_id = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('code' => $code);
+ !empty($card_id) && $data['card_id'] = $card_id;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CODE_CONSUME . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * code 解码
+ * @param string $encrypt_code 通过 choose_card_info 获取的加密字符串
+ * @return bool|array
+ * {
+ * "errcode":0,
+ * "errmsg":"ok",
+ * "code":"751234212312"
+ * }
+ */
+ public function decryptCardCode($encrypt_code)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('encrypt_code' => $encrypt_code,);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CODE_DECRYPT . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 查询 code 的有效性(非自定义 code)
+ * @param string $code
+ * @return bool|array
+ * {
+ * "errcode":0,
+ * "errmsg":"ok",
+ * "openid":"oFS7Fjl0WsZ9AMZqrI80nbIq8xrA", //用户 openid
+ * "card":{
+ * "card_id":"pFS7Fjg8kV1IdDz01r4SQwMkuCKc",
+ * "begin_time": 1404205036, //起始使用时间
+ * "end_time": 1404205036, //结束时间
+ * }
+ * }
+ */
+ public function checkCardCode($code)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('code' => $code);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CODE_GET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量查询卡列表
+ * @param int $offset 开始拉取的偏移,默认为0从头开始
+ * @param int $count 需要查询的卡片的数量(数量最大50,默认50)
+ * @return bool|array
+ * {
+ * "errcode":0,
+ * "errmsg":"ok",
+ * "card_id_list":["ph_gmt7cUVrlRk8swPwx7aDyF-pg"], //卡 id 列表
+ * "total_num":1 //该商户名下 card_id 总数
+ * }
+ */
+ public function getCardIdList($offset = 0, $count = 50)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $count > 50 && $count = 50;
+ $data = array('offset' => $offset, 'count' => $count);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_BATCHGET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 更改 code
+ * 为确保转赠后的安全性,微信允许自定义code的商户对已下发的code进行更改。
+ * 注:为避免用户疑惑,建议仅在发生转赠行为后(发生转赠后,微信会通过事件推送的方式告知商户被转赠的卡券code)对用户的code进行更改。
+ * @param string $code 卡券的 code 编码
+ * @param string $card_id 卡券 ID
+ * @param string $new_code 新的卡券 code 编码
+ * @return bool
+ */
+ public function updateCardCode($code, $card_id, $new_code)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('code' => $code, 'card_id' => $card_id, 'new_code' => $new_code);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CODE_UPDATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 设置卡券失效
+ * 设置卡券失效的操作不可逆
+ * @param string $code 需要设置为失效的 code
+ * @param string $card_id 自定义 code 的卡券必填。非自定义 code 的卡券不填。
+ * @return bool
+ */
+ public function unavailableCardCode($code, $card_id = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('code' => $code);
+ !empty($card_id) && $data['card_id'] = $card_id;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_CODE_UNAVAILABLE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 库存修改
+ * @param string $data
+ * @return bool
+ */
+ public function modifyCardStock($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_MODIFY_STOCK . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 更新门票
+ * @param string $data
+ * @return bool
+ */
+ public function updateMeetingCard($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_MEETINGCARD_UPDATEUSER . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 激活/绑定会员卡
+ * @param string $data 具体结构请参看卡券开发文档(6.1.1 激活/绑定会员卡)章节
+ * @return bool
+ */
+ public function activateMemberCard($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_MEMBERCARD_ACTIVATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 会员卡交易
+ * 会员卡交易后每次积分及余额变更需通过接口通知微信,便于后续消息通知及其他扩展功能。
+ * @param string $data 具体结构请参看卡券开发文档(6.1.2 会员卡交易)章节
+ * @return bool|array
+ */
+ public function updateMemberCard($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_MEMBERCARD_UPDATEUSER . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 设置卡券测试白名单
+ * @param array $openid 测试的 openid 列表
+ * @param array $user 测试的微信号列表
+ * @return bool
+ */
+ public function setCardTestWhiteList($openid = array(), $user = array())
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array();
+ count($openid) > 0 && $data['openid'] = $openid;
+ count($user) > 0 && $data['username'] = $user;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_TESTWHILELIST_SET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 更新红包金额
+ * @param string $code 红包的序列号
+ * @param int $balance 红包余额
+ * @param string $card_id 自定义 code 的卡券必填。非自定义 code 可不填。
+ * @return bool|array
+ */
+ public function updateLuckyMoney($code, $balance, $card_id = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('code' => $code, 'balance' => $balance);
+ !empty($card_id) && $data['card_id'] = $card_id;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_LUCKYMONEY_UPDATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 设置自助核销接口
+ * @param string $card_id 卡券ID
+ * @param bool $is_openid 是否开启自助核销功能,填true/false,默认为false
+ * @param bool $need_verify_cod 用户核销时是否需要输入验证码,填true/false,默认为false
+ * @param bool $need_remark_amount 用户核销时是否需要备注核销金额,填true/false,默认为false
+ * @return bool|array
+ */
+ public function setSelfconsumecell($card_id, $is_openid = false, $need_verify_cod = false, $need_remark_amount = false)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array(
+ 'card_id' => $card_id,
+ 'is_open' => $is_openid,
+ 'need_verify_cod' => $need_verify_cod,
+ 'need_remark_amount' => $need_remark_amount,
+ );
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_SET_SELFCONSUMECELL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 设置买单接口
+ * @param string $card_id
+ * @param bool $is_openid
+ * @return bool|mixed
+ */
+ public function setPaycell($card_id, $is_openid = true)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('card_id' => $card_id, 'is_open' => $is_openid,);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_PAYCELL_SET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 设置开卡字段信息接口
+ * @param array $data
+ * @return bool|array
+ */
+ public function setMembercardActivateuserform($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CARD_MEMBERCARD_ACTIVATEUSERFORM_SET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCustom.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCustom.php
new file mode 100644
index 0000000..76e6ded
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatCustom.php
@@ -0,0 +1,385 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+class WechatCustom extends Common
+{
+
+ /** 多客服相关地址 */
+ const CUSTOM_SERVICE_GET_RECORD = '/customservice/getrecord?';
+ const CUSTOM_SERVICE_GET_KFLIST = '/customservice/getkflist?';
+ const CUSTOM_SERVICE_GET_ONLINEKFLIST = '/customservice/getonlinekflist?';
+ const CUSTOM_SESSION_CREATE = '/customservice/kfsession/create?';
+ const CUSTOM_SESSION_CLOSE = '/customservice/kfsession/close?';
+ const CUSTOM_SESSION_SWITCH = '/customservice/kfsession/switch?';
+ const CUSTOM_SESSION_GET = '/customservice/kfsession/getsession?';
+ const CUSTOM_SESSION_GET_LIST = '/customservice/kfsession/getsessionlist?';
+ const CUSTOM_SESSION_GET_WAIT = '/customservice/kfsession/getwaitcase?';
+ const CS_KF_ACCOUNT_ADD_URL = '/customservice/kfaccount/add?';
+ const CS_KF_ACCOUNT_UPDATE_URL = '/customservice/kfaccount/update?';
+ const CS_KF_ACCOUNT_DEL_URL = '/customservice/kfaccount/del?';
+ const CS_KF_ACCOUNT_UPLOAD_HEADIMG_URL = '/customservice/kfaccount/uploadheadimg?';
+ const CUSTOM_SERVICE_GET_MSG_LIST = '/customservice/msgrecord/getmsglist?';
+
+ /**
+ * 获取多客服会话记录
+ * @param array $data 数据结构 {"starttime":123456789,"endtime":987654321,"openid":"OPENID","pagesize":10,"pageindex":1,}
+ * @return bool|array
+ */
+ public function getCustomServiceMessage($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::CUSTOM_SERVICE_GET_RECORD . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取多客服客服基本信息
+ *
+ * @return bool|array
+ */
+ public function getCustomServiceKFlist()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::CUSTOM_SERVICE_GET_KFLIST . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取多客服在线客服接待信息
+ *
+ * @return bool|array
+ */
+ public function getCustomServiceOnlineKFlist()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::CUSTOM_SERVICE_GET_ONLINEKFLIST . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 创建指定多客服会话
+ * @tutorial 当用户已被其他客服接待或指定客服不在线则会失败
+ * @param string $openid //用户openid
+ * @param string $kf_account //客服账号
+ * @param string $text //附加信息,文本会展示在客服人员的多客服客户端,可为空
+ * @return bool|array
+ */
+ public function createKFSession($openid, $kf_account, $text = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array("openid" => $openid, "kf_account" => $kf_account);
+ $text !== '' && $data["text"] = $text;
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CUSTOM_SESSION_CREATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 关闭指定多客服会话
+ * @tutorial 当用户被其他客服接待时则会失败
+ * @param string $openid //用户openid
+ * @param string $kf_account //客服账号
+ * @param string $text //附加信息,文本会展示在客服人员的多客服客户端,可为空
+ * @return bool | array //成功返回json数组
+ * {
+ * "errcode": 0,
+ * "errmsg": "ok",
+ * }
+ */
+ public function closeKFSession($openid, $kf_account, $text = '')
+ {
+ $data = array("openid" => $openid, "kf_account" => $kf_account);
+ if ($text) {
+ $data["text"] = $text;
+ }
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CUSTOM_SESSION_CLOSE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取用户会话状态
+ * @param string $openid //用户openid
+ * @return bool | array //成功返回json数组
+ * {
+ * "errcode" : 0,
+ * "errmsg" : "ok",
+ * "kf_account" : "test1@test", //正在接待的客服
+ * "createtime": 123456789, //会话接入时间
+ * }
+ */
+ public function getKFSession($openid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::CUSTOM_SESSION_GET . "access_token={$this->access_token}" . '&openid=' . $openid);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取聊天记录
+ * @param array $data 数据结构 {"starttime" : 987654321,"endtime" : 987654321,"msgid" : 1,"number" : 10000}
+ * @return bool|array
+ */
+ public function getCustomMsgList($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CUSTOM_SERVICE_GET_MSG_LIST . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取指定客服的会话列表
+ * @param string $kf_account //用户openid
+ * @return bool | array //成功返回json数组
+ * array(
+ * 'sessionlist' => array (
+ * array (
+ * 'openid'=>'OPENID', //客户 openid
+ * 'createtime'=>123456789, //会话创建时间,UNIX 时间戳
+ * ),
+ * array (
+ * 'openid'=>'OPENID', //客户 openid
+ * 'createtime'=>123456789, //会话创建时间,UNIX 时间戳
+ * ),
+ * )
+ * )
+ */
+ public function getKFSessionlist($kf_account)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::CUSTOM_SESSION_GET_LIST . "access_token={$this->access_token}" . '&kf_account=' . $kf_account);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取未接入会话列表
+ * @return bool|array
+ */
+ public function getKFSessionWait()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::CUSTOM_SESSION_GET_WAIT . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 添加客服账号
+ *
+ * @param string $account 完整客服账号(账号前缀@公众号微信号,账号前缀最多10个字符)
+ * @param string $nickname 客服昵称,最长6个汉字或12个英文字符
+ * @param string $password 客服账号明文登录密码,会自动加密
+ * @return bool|array
+ */
+ public function addKFAccount($account, $nickname, $password)
+ {
+ $data = array("kf_account" => $account, "nickname" => $nickname, "password" => md5($password));
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CS_KF_ACCOUNT_ADD_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 修改客服账号信息
+ *
+ * @param string $account //完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符
+ * @param string $nickname //客服昵称,最长6个汉字或12个英文字符
+ * @param string $password //客服账号明文登录密码,会自动加密
+ * @return bool|array
+ * 成功返回结果
+ * {
+ * "errcode": 0,
+ * "errmsg": "ok",
+ * }
+ */
+ public function updateKFAccount($account, $nickname, $password)
+ {
+ $data = array("kf_account" => $account, "nickname" => $nickname, "password" => md5($password));
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CS_KF_ACCOUNT_UPDATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除客服账号
+ * @param string $account 完整客服账号(账号前缀@公众号微信号,账号前缀最多10个字符)
+ * @return bool|array
+ */
+ public function deleteKFAccount($account)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::CS_KF_ACCOUNT_DEL_URL . "access_token={$this->access_token}" . '&kf_account=' . $account);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 上传客服头像
+ * @param string $account 完整客服账号(账号前缀@公众号微信号,账号前缀最多10个字符)
+ * @param string $imgfile 头像文件完整路径,如:'D:\user.jpg'。头像文件必须JPG格式,像素建议640*640
+ * @return bool|array
+ */
+ public function setKFHeadImg($account, $imgfile)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::CS_KF_ACCOUNT_UPLOAD_HEADIMG_URL . "access_token={$this->access_token}&kf_account={$account}", array('media' => '@' . $imgfile));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatDevice.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatDevice.php
new file mode 100644
index 0000000..932321a
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatDevice.php
@@ -0,0 +1,467 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信设备相关SDK
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016-08-22 10:35
+ */
+class WechatDevice extends Common
+{
+
+ const SHAKEAROUND_DEVICE_APPLYID = '/shakearound/device/applyid?'; //申请设备ID
+ const SHAKEAROUND_DEVICE_APPLYSTATUS = '/shakearound/device/applystatus?'; //查询设备ID申请审核状态
+ const SHAKEAROUND_DEVICE_UPDATE = '/shakearound/device/update?'; //编辑设备信息
+ const SHAKEAROUND_DEVICE_SEARCH = '/shakearound/device/search?'; //查询设备列表
+ const SHAKEAROUND_DEVICE_BINDLOCATION = '/shakearound/device/bindlocation?'; //配置设备与门店ID的关系
+ const SHAKEAROUND_DEVICE_BINDPAGE = '/shakearound/device/bindpage?'; //配置设备与页面的绑定关系
+ const SHAKEAROUND_MATERIAL_ADD = '/shakearound/material/add?'; //上传摇一摇图片素材
+ const SHAKEAROUND_PAGE_ADD = '/shakearound/page/add?'; //增加页面
+ const SHAKEAROUND_PAGE_UPDATE = '/shakearound/page/update?'; //编辑页面
+ const SHAKEAROUND_PAGE_SEARCH = '/shakearound/page/search?'; //查询页面列表
+ const SHAKEAROUND_PAGE_DELETE = '/shakearound/page/delete?'; //删除页面
+ const SHAKEAROUND_USER_GETSHAKEINFO = '/shakearound/user/getshakeinfo?'; //获取摇周边的设备及用户信息
+ const SHAKEAROUND_STATISTICS_DEVICE = '/shakearound/statistics/device?'; //以设备为维度的数据统计接口
+ const SHAKEAROUND_STATISTICS_PAGE = '/shakearound/statistics/page?'; //以页面为维度的数据统计接口
+
+
+ /**
+ * 申请设备ID
+ * @param array $data
+ * @return bool|array
+ */
+ public function applyShakeAroundDevice($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_APPLYID . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 查询设备ID申请审核状态
+ * @param int $apply_id
+ * @return bool|array
+ */
+ public function applyStatusShakeAroundDevice($apply_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array("apply_id" => $apply_id);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_APPLYSTATUS . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 编辑设备信息
+ * @param array $data
+ * @return bool
+ */
+ public function updateShakeAroundDevice($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_UPDATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * 查询设备列表
+ * @param $data
+ * @return bool|array
+ */
+ public function searchShakeAroundDevice($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_SEARCH . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 配置设备与门店的关联关系
+ * @param string $device_id 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
+ * @param int $poi_id 待关联的门店ID
+ * @param string $uuid UUID、major、minor,三个信息需填写完整,若填了设备编号,则可不填此信息
+ * @param int $major
+ * @param int $minor
+ * @return bool|array
+ */
+ public function bindLocationShakeAroundDevice($device_id, $poi_id, $uuid = '', $major = 0, $minor = 0)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (!$device_id) {
+ if (!$uuid || !$major || !$minor) {
+ return false;
+ }
+ $device_identifier = array('uuid' => $uuid, 'major' => $major, 'minor' => $minor);
+ } else {
+ $device_identifier = array('device_id' => $device_id);
+ }
+ $data = array('device_identifier' => $device_identifier, 'poi_id' => $poi_id);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_BINDLOCATION . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 配置设备与其他公众账号门店的关联关系
+ * @param type $device_identifier 设备信息
+ * @param type $poi_id 待关联的门店ID
+ * @param type $poi_appid 目标微信appid
+ * @return boolean
+ */
+ public function bindLocationOtherShakeAroundDevice($device_identifier, $poi_id, $poi_appid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('device_identifier' => $device_identifier, 'poi_id' => $poi_id, "type" => 2, "poi_appid" => $poi_appid);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_BINDLOCATION . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 配置设备与页面的关联关系
+ * @param string $device_id 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
+ * @param array $page_ids 待关联的页面列表
+ * @param int $bind 关联操作标志位, 0 为解除关联关系,1 为建立关联关系
+ * @param int $append 新增操作标志位, 0 为覆盖,1 为新增
+ * @param string $uuid UUID、major、minor,三个信息需填写完整,若填了设备编号,则可不填此信息
+ * @param int $major
+ * @param int $minor
+ * @return bool|array
+ */
+ public function bindPageShakeAroundDevice($device_id, $page_ids = array(), $bind = 1, $append = 1, $uuid = '', $major = 0, $minor = 0)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (!$device_id) {
+ if (!$uuid || !$major || !$minor) {
+ return false;
+ }
+ $device_identifier = array('uuid' => $uuid, 'major' => $major, 'minor' => $minor);
+ } else {
+ $device_identifier = array('device_id' => $device_id);
+ }
+ $data = array('device_identifier' => $device_identifier, 'page_ids' => $page_ids, 'bind' => $bind, 'append' => $append);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_DEVICE_BINDPAGE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 上传在摇一摇页面展示的图片素材
+ * @param array $data {"media":'@Path\filename.jpg'}
+ * @return bool|array
+ */
+ public function uploadShakeAroundMedia($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_MATERIAL_ADD . "access_token={$this->access_token}", $data);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 增加摇一摇出来的页面信息
+ * @param string $title 在摇一摇页面展示的主标题,不超过6 个字
+ * @param string $description 在摇一摇页面展示的副标题,不超过7 个字
+ * @param string $icon_url 在摇一摇页面展示的图片, 格式限定为:jpg,jpeg,png,gif; 建议120*120 , 限制不超过200*200
+ * @param string $page_url 跳转链接
+ * @param string $comment 页面的备注信息,不超过15 个字,可不填
+ * @return bool|array
+ */
+ public function addShakeAroundPage($title, $description, $icon_url, $page_url, $comment = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array("title" => $title, "description" => $description, "icon_url" => $icon_url, "page_url" => $page_url, "comment" => $comment);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_PAGE_ADD . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 编辑摇一摇出来的页面信息
+ * @param int $page_id
+ * @param string $title 在摇一摇页面展示的主标题,不超过6 个字
+ * @param string $description 在摇一摇页面展示的副标题,不超过7 个字
+ * @param string $icon_url 在摇一摇页面展示的图片, 格式限定为:jpg,jpeg,png,gif; 建议120*120 , 限制不超过200*200
+ * @param string $page_url 跳转链接
+ * @param string $comment 页面的备注信息,不超过15 个字,可不填
+ * @return bool|array
+ */
+ public function updateShakeAroundPage($page_id, $title, $description, $icon_url, $page_url, $comment = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array("page_id" => $page_id, "title" => $title, "description" => $description, "icon_url" => $icon_url, "page_url" => $page_url, "comment" => $comment);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_PAGE_UPDATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 查询已有的页面
+ * @param array $page_ids
+ * @param int $begin
+ * @param int $count
+ * @return bool|mixed
+ */
+ public function searchShakeAroundPage($page_ids = array(), $begin = 0, $count = 1)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (!empty($page_ids)) {
+ $data = array('page_ids' => $page_ids);
+ } else {
+ $data = array('begin' => $begin, 'count' => $count);
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_PAGE_SEARCH . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 删除已有的页面
+ * @param array $page_ids
+ * @return bool|array
+ */
+ public function deleteShakeAroundPage($page_ids = array())
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('page_ids' => $page_ids);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_PAGE_DELETE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 获取设备信息
+ * @param string $ticket 摇周边业务的ticket(可在摇到的URL中得到,ticket生效时间为30 分钟)
+ * @return bool|array
+ */
+ public function getShakeInfoShakeAroundUser($ticket)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('ticket' => $ticket);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_USER_GETSHAKEINFO . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 以设备为维度的数据统计接口
+ * @param int $device_id 设备编号,若填了UUID、major、minor,即可不填设备编号,二者选其一
+ * @param int $begin_date 起始日期时间戳,最长时间跨度为30 天
+ * @param int $end_date 结束日期时间戳,最长时间跨度为30 天
+ * @param string $uuid UUID、major、minor,三个信息需填写完成,若填了设备编辑,即可不填此信息,二者选其一
+ * @param int $major
+ * @param int $minor
+ * @return bool|array
+ */
+ public function deviceShakeAroundStatistics($device_id, $begin_date, $end_date, $uuid = '', $major = 0, $minor = 0)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (!$device_id) {
+ if (!$uuid || !$major || !$minor) {
+ return false;
+ }
+ $device_identifier = array('uuid' => $uuid, 'major' => $major, 'minor' => $minor);
+ } else {
+ $device_identifier = array('device_id' => $device_id);
+ }
+ $data = array('device_identifier' => $device_identifier, 'begin_date' => $begin_date, 'end_date' => $end_date);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_STATISTICS_DEVICE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ /**
+ * 以页面为维度的数据统计接口
+ * @param int $page_id 指定页面的ID
+ * @param int $begin_date 起始日期时间戳,最长时间跨度为30 天
+ * @param int $end_date 结束日期时间戳,最长时间跨度为30 天
+ * @return bool|array
+ */
+ public function pageShakeAroundStatistics($page_id, $begin_date, $end_date)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('page_id' => $page_id, 'begin_date' => $begin_date, 'end_date' => $end_date);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SHAKEAROUND_STATISTICS_DEVICE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatExtends.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatExtends.php
new file mode 100644
index 0000000..f03c15b
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatExtends.php
@@ -0,0 +1,209 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信扩展功能
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016-08-22 10:32
+ */
+class WechatExtends extends Common
+{
+
+ const QR_LIMIT_SCENE = 1;
+
+ /** 语义理解 */
+ const SEMANTIC_API_URL = '/semantic/semproxy/search?';
+ const QRCODE_IMG_URL = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=';
+ const QRCODE_CREATE_URL = '/qrcode/create?';
+ const SHORT_URL = '/shorturl?';
+ const QR_SCENE = 0;
+
+ /** 数据分析接口 */
+ static $DATACUBE_URL_ARR = array(//用户分析
+ 'user' => array(
+ 'summary' => '/datacube/getusersummary?', //获取用户增减数据(getusersummary)
+ 'cumulate' => '/datacube/getusercumulate?', //获取累计用户数据(getusercumulate)
+ ),
+ 'article' => array(//图文分析
+ 'summary' => '/datacube/getarticlesummary?', //获取图文群发每日数据(getarticlesummary)
+ 'total' => '/datacube/getarticletotal?', //获取图文群发总数据(getarticletotal)
+ 'read' => '/datacube/getuserread?', //获取图文统计数据(getuserread)
+ 'readhour' => '/datacube/getuserreadhour?', //获取图文统计分时数据(getuserreadhour)
+ 'share' => '/datacube/getusershare?', //获取图文分享转发数据(getusershare)
+ 'sharehour' => '/datacube/getusersharehour?', //获取图文分享转发分时数据(getusersharehour)
+ ),
+ 'upstreammsg' => array(//消息分析
+ 'summary' => '/datacube/getupstreammsg?', //获取消息发送概况数据(getupstreammsg)
+ 'hour' => '/datacube/getupstreammsghour?', //获取消息分送分时数据(getupstreammsghour)
+ 'week' => '/datacube/getupstreammsgweek?', //获取消息发送周数据(getupstreammsgweek)
+ 'month' => '/datacube/getupstreammsgmonth?', //获取消息发送月数据(getupstreammsgmonth)
+ 'dist' => '/datacube/getupstreammsgdist?', //获取消息发送分布数据(getupstreammsgdist)
+ 'distweek' => '/datacube/getupstreammsgdistweek?', //获取消息发送分布周数据(getupstreammsgdistweek)
+ 'distmonth' => '/datacube/getupstreammsgdistmonth?', //获取消息发送分布月数据(getupstreammsgdistmonth)
+ ),
+ 'interface' => array(//接口分析
+ 'summary' => '/datacube/getinterfacesummary?', //获取接口分析数据(getinterfacesummary)
+ 'summaryhour' => '/datacube/getinterfacesummaryhour?', //获取接口分析分时数据(getinterfacesummaryhour)
+ )
+ );
+
+ /**
+ * 获取二维码图片
+ * @param string $ticket 传入由getQRCode方法生成的ticket参数
+ * @return string url 返回http地址
+ */
+ public function getQRUrl($ticket)
+ {
+ return self::QRCODE_IMG_URL . urlencode($ticket);
+ }
+
+ /**
+ * 长链接转短链接接口
+ * @param string $long_url 传入要转换的长url
+ * @return bool|string url 成功则返回转换后的短url
+ */
+ public function getShortUrl($long_url)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('action' => 'long2short', 'long_url' => $long_url);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::SHORT_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json['short_url'];
+ }
+ return false;
+ }
+
+ /**
+ * 创建二维码ticket
+ * @param int|string $scene_id 自定义追踪id,临时二维码只能用数值型
+ * @param int $type 0:临时二维码;1:永久二维码(此时expire参数无效);2:永久二维码(此时expire参数无效)
+ * @param int $expire 临时二维码有效期,最大为2592000秒(30天)
+ * @return bool|array ('ticket'=>'qrcode字串','expire_seconds'=>2592000,'url'=>'二维码图片解析后的地址')
+ */
+ public function getQRCode($scene_id, $type = 0, $expire = 2592000)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $type = ($type && is_string($scene_id)) ? 2 : $type;
+ $data = array(
+ 'action_name' => $type ? ($type == 2 ? "QR_LIMIT_STR_SCENE" : "QR_LIMIT_SCENE") : "QR_SCENE",
+ 'expire_seconds' => $expire,
+ 'action_info' => array('scene' => ($type == 2 ? array('scene_str' => $scene_id) : array('scene_id' => $scene_id)))
+ );
+ if ($type == 1) {
+ unset($data['expire_seconds']);
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::QRCODE_CREATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 语义理解接口
+ * @param string $uid 用户唯一id(非开发者id),用户区分公众号下的不同用户(建议填入用户openid)
+ * @param string $query 输入文本串
+ * @param string $category 需要使用的服务类型,多个用“,”隔开,不能为空
+ * @param float $latitude 纬度坐标,与经度同时传入;与城市二选一传入
+ * @param float $longitude 经度坐标,与纬度同时传入;与城市二选一传入
+ * @param string $city 城市名称,与经纬度二选一传入
+ * @param string $region 区域名称,在城市存在的情况下可省略;与经纬度二选一传入
+ * @return bool|array
+ */
+ public function querySemantic($uid, $query, $category, $latitude = 0.00, $longitude = 0.00, $city = "", $region = "")
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array(
+ 'query' => $query,
+ 'category' => $category,
+ 'appid' => $this->appid,
+ 'uid' => ''
+ );
+ //地理坐标或城市名称二选一
+ if ($latitude) {
+ $data['latitude'] = $latitude;
+ $data['longitude'] = $longitude;
+ } elseif ($city) {
+ $data['city'] = $city;
+ } elseif ($region) {
+ $data['region'] = $region;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::SEMANTIC_API_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取统计数据
+ * @param string $type 数据分类(user|article|upstreammsg|interface)分别为(用户分析|图文分析|消息分析|接口分析)
+ * @param string $subtype 数据子分类,参考 DATACUBE_URL_ARR 常量定义部分 或者README.md说明文档
+ * @param string $begin_date 开始时间
+ * @param string $end_date 结束时间
+ * @return bool|array 成功返回查询结果数组,其定义请看官方文档
+ */
+ public function getDatacube($type, $subtype, $begin_date, $end_date = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (!isset(self::$DATACUBE_URL_ARR[$type]) || !isset(self::$DATACUBE_URL_ARR[$type][$subtype])) {
+ return false;
+ }
+ $data = array('begin_date' => $begin_date, 'end_date' => $end_date ? $end_date : $begin_date);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::$DATACUBE_URL_ARR[$type][$subtype] . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return isset($json['list']) ? $json['list'] : $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatHardware.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatHardware.php
new file mode 100644
index 0000000..c01114b
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatHardware.php
@@ -0,0 +1,160 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+class WechatHardware extends Common
+{
+
+ const DEVICE_AUTHORIZE_DEVICE = '/device/authorize_device?'; //设备设全
+ const DEVICE_GETQRCODE = '/device/getqrcode?'; //设备授权新接口
+ const DEVICE_CREATE_QRCODE = '/device/create_qrcode?'; //获取设备二维码
+ const DEVICE_GET_STAT = '/device/get_stat?'; //获取设备状态
+ const DEVICE_TRANSMSG = '/device/transmsg?'; //主动发送消息给设备
+ const DEVICE_COMPEL_UNBINDHTTPS = '/device/compel_unbind?'; //强制解绑用户和设备
+
+ /**
+ * 强制解绑用户和设备
+ * @param $data
+ * @return bool|mixed
+ */
+ public function deviceCompelUnbindhttps($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::DEVICE_COMPEL_UNBINDHTTPS . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+
+ public function transmsg($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::DEVICE_TRANSMSG . "access_token={$this->access_token}", Tools::json_encode($data));
+ //dump($result);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ public function getQrcode($product_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::DEVICE_GETQRCODE . "access_token={$this->access_token}&product_id=$product_id");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 设备授权
+ * @param $data
+ * @return bool|mixed
+ */
+ public function deviceAuthorize($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::DEVICE_AUTHORIZE_DEVICE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取设备二维码
+ * @param $data
+ * @return bool|mixed
+ */
+ public function getDeviceQrcode($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::DEVICE_CREATE_QRCODE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取设备状态
+ * @param $device_id
+ * @return bool|mixed
+ */
+ public function getDeviceStat($device_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::DEVICE_GET_STAT . "access_token={$this->access_token}&device_id=$device_id");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+} \ No newline at end of file
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMedia.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMedia.php
new file mode 100644
index 0000000..3208179
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMedia.php
@@ -0,0 +1,430 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Cache;
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信媒体素材管理类
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/10/26 14:47
+ */
+class WechatMedia extends Common
+{
+
+ const MEDIA_UPLOAD_URL = '/media/upload?';
+ const MEDIA_UPLOADIMG_URL = '/media/uploadimg?';
+ const MEDIA_GET_URL = '/media/get?';
+ const MEDIA_VIDEO_UPLOAD = '/media/uploadvideo?';
+ const MEDIA_FOREVER_UPLOAD_URL = '/material/add_material?';
+ const MEDIA_FOREVER_NEWS_UPLOAD_URL = '/material/add_news?';
+ const MEDIA_FOREVER_NEWS_UPDATE_URL = '/material/update_news?';
+ const MEDIA_FOREVER_GET_URL = '/material/get_material?';
+ const MEDIA_FOREVER_DEL_URL = '/material/del_material?';
+ const MEDIA_FOREVER_COUNT_URL = '/material/get_materialcount?';
+ const MEDIA_FOREVER_BATCHGET_URL = '/material/batchget_material?';
+ const MEDIA_UPLOADNEWS_URL = '/media/uploadnews?';
+
+ /**
+ * 上传临时素材,有效期为3天(认证后的订阅号可用)
+ * 注意:上传大文件时可能需要先调用 set_time_limit(0) 避免超时
+ * 注意:数组的键值任意,但文件名前必须加@,使用单引号以避免本地路径斜杠被转义
+ * 注意:临时素材的media_id是可复用的!
+ * @param array $data {"media":'@Path\filename.jpg'}
+ * @param string $type 类型:图片:image 语音:voice 视频:video 缩略图:thumb
+ * @return bool|array
+ */
+ public function uploadMedia($data, $type)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (Tools::isBase64($data['media'])) {
+ $cache_file = Cache::file(base64_decode($data['media']));
+ $data['media'] = "@{$cache_file}";
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_UPLOAD_URL . "access_token={$this->access_token}&type={$type}", $data);
+ !empty($cache_file) && @unlink($cache_file);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取临时素材(认证后的订阅号可用)
+ * @param string $media_id 媒体文件id
+ * @param bool $is_video 是否为视频文件,默认为否
+ * @return bool|array
+ */
+ public function getMedia($media_id, $is_video = false)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::MEDIA_GET_URL . "access_token={$this->access_token}" . '&media_id=' . $media_id);
+ if ($result) {
+ if (is_string($result)) {
+ $json = json_decode($result, true);
+ if (isset($json['errcode'])) {
+ $this->errCode = $json['errcode'];
+ $this->errMsg = $json['errmsg'];
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ }
+ return $result;
+ }
+ return false;
+ }
+
+ /**
+ * 获取临时素材(认证后的订阅号可用) 包含返回的http头信息
+ * @param string $media_id 媒体文件id
+ * @param bool $is_video 是否为视频文件,默认为否
+ * @return bool|array
+ */
+ public function getMediaWithHttpInfo($media_id, $is_video = false)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $url_prefix = $is_video ? str_replace('https', 'http', self::API_URL_PREFIX) : self::API_URL_PREFIX;
+ $url = $url_prefix . self::MEDIA_GET_URL . "access_token={$this->access_token}" . '&media_id=' . $media_id;
+ $oCurl = curl_init();
+ if (stripos($url, "https://") !== false) {
+ curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($oCurl, CURLOPT_SSLVERSION, 1);
+ }
+ curl_setopt($oCurl, CURLOPT_URL, $url);
+ curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
+ $sContent = curl_exec($oCurl);
+ $aStatus = curl_getinfo($oCurl);
+ $result = array();
+ if (intval($aStatus["http_code"]) !== 200) {
+ return false;
+ }
+ if ($sContent) {
+ if (is_string($sContent)) {
+ $json = json_decode($sContent, true);
+ if (isset($json['errcode'])) {
+ $this->errCode = $json['errcode'];
+ $this->errMsg = $json['errmsg'];
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ }
+ $result['content'] = $sContent;
+ $result['info'] = $aStatus;
+ return $result;
+ }
+ return false;
+ }
+
+ /**
+ * 上传图片,本接口所上传的图片不占用公众号的素材库中图片数量的5000个的限制。图片仅支持jpg/png格式,大小必须在1MB以下。 (认证后的订阅号可用)
+ * 注意:上传大文件时可能需要先调用 set_time_limit(0) 避免超时
+ * 注意:数组的键值任意,但文件名前必须加@,使用单引号以避免本地路径斜杠被转义
+ * @param array $data {"media":'@Path\filename.jpg'}
+ * @return bool|array
+ */
+ public function uploadImg($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ if (Tools::isBase64($data['media'])) {
+ $cache_file = Cache::file(base64_decode($data['media']));
+ $data['media'] = "@{$cache_file}";
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_UPLOADIMG_URL . "access_token={$this->access_token}", $data);
+ !empty($cache_file) && @unlink($cache_file);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 上传永久素材(认证后的订阅号可用)
+ * 新增的永久素材也可以在公众平台官网素材管理模块中看到
+ * 注意:上传大文件时可能需要先调用 set_time_limit(0) 避免超时
+ * 注意:数组的键值任意,但文件名前必须加@,使用单引号以避免本地路径斜杠被转义
+ * @param array $data {"media":'@Path\filename.jpg'}, 支持base64格式
+ * @param string $type 类型:图片:image 语音:voice 视频:video 缩略图:thumb
+ * @param bool $is_video 是否为视频文件,默认为否
+ * @param array $video_info 视频信息数组,非视频素材不需要提供 array('title'=>'视频标题','introduction'=>'描述')
+ * @return bool|array
+ */
+ public function uploadForeverMedia($data, $type, $is_video = false, $video_info = array())
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $is_video && ($data['description'] = Tools::json_encode($video_info));
+ if (Tools::isBase64($data['media'])) {
+ $cache_file = Cache::file(base64_decode($data['media']));
+ $data['media'] = "@{$cache_file}";
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_FOREVER_UPLOAD_URL . "access_token={$this->access_token}&type={$type}", $data);
+ !empty($cache_file) && @unlink($cache_file);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 上传永久图文素材(认证后的订阅号可用)
+ * 新增的永久素材也可以在公众平台官网素材管理模块中看到
+ * @param array $data 消息结构{"articles":[{...}]}
+ * @return bool|array
+ */
+ public function uploadForeverArticles($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_FOREVER_NEWS_UPLOAD_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 修改永久图文素材(认证后的订阅号可用)
+ * 永久素材也可以在公众平台官网素材管理模块中看到
+ * @param string $media_id 图文素材id
+ * @param array $data 消息结构{"articles":[{...}]}
+ * @param int $index 更新的文章在图文素材的位置,第一篇为0,仅多图文使用
+ * @return bool|array
+ */
+ public function updateForeverArticles($media_id, $data, $index = 0)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ !isset($data['index']) && $data['index'] = $index;
+ !isset($data['media_id']) && $data['media_id'] = $media_id;
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_FOREVER_NEWS_UPDATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取永久素材(认证后的订阅号可用)
+ * 返回图文消息数组或二进制数据,失败返回false
+ * @param string $media_id 媒体文件id
+ * @param bool $is_video 是否为视频文件,默认为否
+ * @return bool|array
+ */
+ public function getForeverMedia($media_id, $is_video = false)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('media_id' => $media_id);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_FOREVER_GET_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ if (is_string($result) && ($json = json_decode($result, true))) {
+ if (isset($json['errcode'])) {
+ $this->errCode = $json['errcode'];
+ $this->errMsg = $json['errmsg'];
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return $result;
+ }
+ return false;
+ }
+
+ /**
+ * 删除永久素材(认证后的订阅号可用)
+ * @param string $media_id 媒体文件id
+ * @return bool
+ */
+ public function delForeverMedia($media_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('media_id' => $media_id);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_FOREVER_DEL_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 获取永久素材列表(认证后的订阅号可用)
+ * @param string $type 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
+ * @param int $offset 全部素材的偏移位置,0表示从第一个素材
+ * @param int $count 返回素材的数量,取值在1到20之间
+ * @return bool|array
+ * 返回数组格式:
+ * array(
+ * 'total_count'=>0, //该类型的素材的总数
+ * 'item_count'=>0, //本次调用获取的素材的数量
+ * 'item'=>array() //素材列表数组,内容定义请参考官方文档
+ * )
+ */
+ public function getForeverList($type, $offset, $count)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('type' => $type, 'offset' => $offset, 'count' => $count);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_FOREVER_BATCHGET_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取永久素材总数(认证后的订阅号可用)
+ * @return bool|array
+ * 返回数组格式:
+ * array(
+ * 'voice_count'=>0, //语音总数量
+ * 'video_count'=>0, //视频总数量
+ * 'image_count'=>0, //图片总数量
+ * 'news_count'=>0 //图文总数量
+ * )
+ */
+ public function getForeverCount()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::MEDIA_FOREVER_COUNT_URL . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 上传图文消息素材,用于群发(认证后的订阅号可用)
+ * @param array $data 消息结构{"articles":[{...}]}
+ * @return bool|array
+ */
+ public function uploadArticles($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_UPLOADNEWS_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 上传视频素材(认证后的订阅号可用)
+ * @param array $data 消息结构
+ * {
+ * "media_id"=>"", //通过上传媒体接口得到的MediaId
+ * "title"=>"TITLE", //视频标题
+ * "description"=>"Description" //视频描述
+ * }
+ * @return bool|array
+ * {
+ * "type":"video",
+ * "media_id":"mediaid",
+ * "created_at":1398848981
+ * }
+ */
+ public function uploadMpVideo($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MEDIA_VIDEO_UPLOAD . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMenu.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMenu.php
new file mode 100644
index 0000000..0e7ab9b
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMenu.php
@@ -0,0 +1,183 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信菜单操作SDK
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/06/28 11:52
+ */
+class WechatMenu extends Common
+{
+
+ /** 创建自定义菜单 */
+ const MENU_ADD_URL = '/menu/create?';
+ /* 获取自定义菜单 */
+ const MENU_GET_URL = '/menu/get?';
+ /* 删除自定义菜单 */
+ const MENU_DEL_URL = '/menu/delete?';
+
+ /** 添加个性菜单 */
+ const COND_MENU_ADD_URL = '/menu/addconditional?';
+ /* 删除个性菜单 */
+ const COND_MENU_DEL_URL = '/menu/delconditional?';
+ /* 测试个性菜单 */
+ const COND_MENU_TRY_URL = '/menu/trymatch?';
+
+ /**
+ * 创建自定义菜单
+ * @param array $data 菜单数组数据
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN 文档
+ * @return bool
+ */
+ public function createMenu($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::MENU_ADD_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 获取所有菜单
+ * @return bool|array
+ */
+ public function getMenu()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::MENU_GET_URL . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除所有菜单
+ * @return bool
+ */
+ public function deleteMenu()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::MENU_DEL_URL . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 创建个性菜单
+ * @param array $data 菜单数组数据
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN 文档
+ * @return bool|string
+ */
+ public function createCondMenu($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::COND_MENU_ADD_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json['menuid'];
+ }
+ return false;
+ }
+
+ /**
+ * 删除个性菜单
+ * @param string $menuid 菜单ID
+ * @return bool
+ */
+ public function deleteCondMenu($menuid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('menuid' => $menuid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::COND_MENU_DEL_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 测试并返回个性化菜单
+ * @param string $openid 粉丝openid
+ * @return bool
+ */
+ public function tryCondMenu($openid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('user_id' => $openid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::COND_MENU_TRY_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMessage.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMessage.php
new file mode 100644
index 0000000..3b71685
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatMessage.php
@@ -0,0 +1,352 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信模板消息
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/06/28 11:29
+ */
+class WechatMessage extends Common
+{
+
+ /**
+ * 获取模板列表
+ * @return bool|array
+ */
+ public function getAllPrivateTemplate()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/template/get_all_private_template?access_token={$this->access_token}", []);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取设置的行业信息
+ * @return bool|array
+ */
+ public function getTMIndustry()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/template/get_industry?access_token={$this->access_token}", []);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除模板消息
+ * @param string $tpl_id
+ * @return bool
+ */
+ public function delPrivateTemplate($tpl_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('template_id' => $tpl_id);
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/template/del_private_template?access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 模板消息 设置所属行业
+ * @param string $id1 公众号模板消息所属行业编号,参看官方开发文档 行业代码
+ * @param string $id2 同$id1。但如果只有一个行业,此参数可省略
+ * @return bool|mixed
+ */
+ public function setTMIndustry($id1, $id2 = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array();
+ !empty($id1) && $data['industry_id1'] = $id1;
+ !empty($id2) && $data['industry_id2'] = $id2;
+ $json = Tools::json_encode($data);
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/template/api_set_industry?access_token={$this->access_token}", $json);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 模板消息 添加消息模板
+ * 成功返回消息模板的调用id
+ * @param string $tpl_id 模板库中模板的编号,有“TM**”和“OPENTMTM**”等形式
+ * @return bool|string
+ */
+ public function addTemplateMessage($tpl_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = Tools::json_encode(array('template_id_short' => $tpl_id));
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/template/api_add_template?access_token={$this->access_token}", $data);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json['template_id'];
+ }
+ return false;
+ }
+
+ /**
+ * 发送模板消息
+ * @param array $data 消息结构
+ * {
+ * "touser":"OPENID",
+ * "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
+ * "url":"http://weixin.qq.com/download",
+ * "topcolor":"#FF0000",
+ * "data":{
+ * "参数名1": {
+ * "value":"参数",
+ * "color":"#173177" //参数颜色
+ * },
+ * "Date":{
+ * "value":"06月07日 19时24分",
+ * "color":"#173177"
+ * },
+ * "CardNumber":{
+ * "value":"0426",
+ * "color":"#173177"
+ * },
+ * "Type":{
+ * "value":"消费",
+ * "color":"#173177"
+ * }
+ * }
+ * }
+ * @return bool|array
+ */
+ public function sendTemplateMessage($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/template/send?access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 根据标签进行群发 ( 订阅号与服务号认证后均可用 )
+ * @param array $data 消息结构
+ * 注意: 视频需要在调用uploadMedia()方法后,再使用 uploadMpVideo() 方法生成,
+ * 然后获得的 mediaid 才能用于群发,且消息类型为 mpvideo 类型。
+ * @return bool|array
+ * {
+ * "touser"=>array(
+ * "OPENID1",
+ * "OPENID2"
+ * ),
+ * "msgtype"=>"mpvideo",
+ * // 在下面5种类型中选择对应的参数内容
+ * // mpnews | voice | image | mpvideo => array( "media_id"=>"MediaId")
+ * // text => array ( "content" => "hello")
+ * }
+ */
+ public function sendMassMessage($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/mass/send?access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 根据标签进行群发 ( 订阅号与服务号认证后均可用 )
+ * @param array $data 消息结构
+ * 注意:视频需要在调用uploadMedia()方法后,再使用 uploadMpVideo() 方法生成,
+ * 然后获得的 mediaid 才能用于群发,且消息类型为 mpvideo 类型。
+ * @return bool|array
+ * {
+ * "filter"=>array(
+ * "is_to_all"=>False, //是否群发给所有用户.True不用分组id,False需填写分组id
+ * "group_id"=>"2" //群发的分组id
+ * ),
+ * "msgtype"=>"mpvideo",
+ * // 在下面5种类型中选择对应的参数内容
+ * // mpnews | voice | image | mpvideo => array( "media_id"=>"MediaId")
+ * // text => array ( "content" => "hello")
+ * }
+ */
+ public function sendGroupMassMessage($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/mass/sendall?access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除群发图文消息 ( 订阅号与服务号认证后均可用 )
+ * @param string $msg_id 消息ID
+ * @return bool
+ */
+ public function deleteMassMessage($msg_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = Tools::json_encode(array('msg_id' => $msg_id));
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/mass/delete?access_token={$this->access_token}", $data);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 预览群发消息 ( 订阅号与服务号认证后均可用 )
+ * @param array $data
+ * 注意: 视频需要在调用uploadMedia()方法后,再使用 uploadMpVideo() 方法生成,
+ * 然后获得的 mediaid 才能用于群发,且消息类型为 mpvideo 类型。
+ * @消息结构
+ * {
+ * "touser"=>"OPENID",
+ * "msgtype"=>"mpvideo",
+ * // 在下面5种类型中选择对应的参数内容
+ * // mpnews | voice | image | mpvideo => array( "media_id"=>"MediaId")
+ * // text => array ( "content" => "hello")
+ * }
+ * @return bool|array
+ */
+ public function previewMassMessage($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/mass/preview?access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 查询群发消息发送状态 ( 订阅号与服务号认证后均可用 )
+ * @param string $msg_id 消息ID
+ * @return bool|array
+ * {
+ * "msg_id":201053012, //群发消息后返回的消息id
+ * "msg_status":"SEND_SUCCESS", //消息发送后的状态,SENDING表示正在发送 SEND_SUCCESS表示发送成功
+ * }
+ */
+ public function queryMassMessage($msg_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = Tools::json_encode(array('msg_id' => $msg_id));
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/mass/get?access_token={$this->access_token}", $data);
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatOauth.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatOauth.php
new file mode 100644
index 0000000..8d99fed
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatOauth.php
@@ -0,0 +1,138 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信网页授权
+ */
+class WechatOauth extends Common
+{
+
+ const OAUTH_PREFIX = 'https://open.weixin.qq.com/connect/oauth2';
+ const OAUTH_AUTHORIZE_URL = '/authorize?';
+ const OAUTH_TOKEN_URL = '/sns/oauth2/access_token?';
+ const OAUTH_REFRESH_URL = '/sns/oauth2/refresh_token?';
+ const OAUTH_USERINFO_URL = '/sns/userinfo?';
+ const OAUTH_AUTH_URL = '/sns/auth?';
+
+ /**
+ * Oauth 授权跳转接口
+ * @param string $callback 授权回跳地址
+ * @param string $state 为重定向后会带上state参数(填写a-zA-Z0-9的参数值,最多128字节)
+ * @param string $scope 授权类类型(可选值snsapi_base|snsapi_userinfo)
+ * @return string
+ */
+ public function getOauthRedirect($callback, $state = '', $scope = 'snsapi_base')
+ {
+ $redirect_uri = urlencode($callback);
+ return self::OAUTH_PREFIX . self::OAUTH_AUTHORIZE_URL . "appid={$this->appid}&redirect_uri={$redirect_uri}&response_type=code&scope={$scope}&state={$state}#wechat_redirect";
+ }
+
+ /**
+ * 通过 code 获取 AccessToken 和 openid
+ * @return bool|array
+ */
+ public function getOauthAccessToken()
+ {
+ $code = isset($_GET['code']) ? $_GET['code'] : '';
+ if (empty($code)) {
+ Tools::log("getOauthAccessToken Fail, Because there is no access to the code value in get.", "MSG - {$this->appid}");
+ return false;
+ }
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::OAUTH_TOKEN_URL . "appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ Tools::log("WechatOauth::getOauthAccessToken Fail.{$this->errMsg} [{$this->errCode}]", "ERR - {$this->appid}");
+ return false;
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 刷新access token并续期
+ * @param string $refresh_token
+ * @return bool|array
+ */
+ public function getOauthRefreshToken($refresh_token)
+ {
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::OAUTH_REFRESH_URL . "appid={$this->appid}&grant_type=refresh_token&refresh_token={$refresh_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ Tools::log("WechatOauth::getOauthRefreshToken Fail.{$this->errMsg} [{$this->errCode}]", "ERR - {$this->appid}");
+ return false;
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取授权后的用户资料
+ * @param string $access_token
+ * @param string $openid
+ * @return bool|array {openid,nickname,sex,province,city,country,headimgurl,privilege,[unionid]}
+ * 注意:unionid字段 只有在用户将公众号绑定到微信开放平台账号后,才会出现。建议调用前用isset()检测一下
+ */
+ public function getOauthUserInfo($access_token, $openid)
+ {
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::OAUTH_USERINFO_URL . "access_token={$access_token}&openid={$openid}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ Tools::log("WechatOauth::getOauthUserInfo Fail.{$this->errMsg} [{$this->errCode}]", "ERR - {$this->appid}");
+ return false;
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 检验授权凭证是否有效
+ * @param string $access_token
+ * @param string $openid
+ * @return bool 是否有效
+ */
+ public function getOauthAuth($access_token, $openid)
+ {
+ $result = Tools::httpGet(self::API_BASE_URL_PREFIX . self::OAUTH_AUTH_URL . "access_token={$access_token}&openid={$openid}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ Tools::log("WechatOauth::getOauthAuth Fail.{$this->errMsg} [{$this->errCode}]", "ERR - {$this->appid}");
+ return false;
+ } elseif (intval($json['errcode']) === 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPay.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPay.php
new file mode 100644
index 0000000..0ca602d
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPay.php
@@ -0,0 +1,620 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Tools;
+
+/**
+ * 微信支付SDK
+ * @author zoujingli <zoujingli@qq.com>
+ * @date 2015/05/13 12:12:00
+ */
+class WechatPay
+{
+
+ /** 支付接口基础地址 */
+ const MCH_BASE_URL = 'https://api.mch.weixin.qq.com';
+
+ /** 公众号appid */
+ public $appid;
+
+ /** 公众号配置 */
+ public $config;
+
+ /** 商户身份ID */
+ public $mch_id;
+
+ /** 商户支付密钥Key */
+ public $partnerKey;
+
+ /** 证书路径 */
+ public $ssl_cer;
+ public $ssl_key;
+
+ /** 执行错误消息及代码 */
+ public $errMsg;
+ public $errCode;
+
+ /**
+ * WechatPay constructor.
+ * @param array $options
+ */
+ public function __construct($options = array())
+ {
+ $this->config = Loader::config($options);
+ $this->appid = isset($this->config['appid']) ? $this->config['appid'] : '';
+ $this->mch_id = isset($this->config['mch_id']) ? $this->config['mch_id'] : '';
+ $this->partnerKey = isset($this->config['partnerkey']) ? $this->config['partnerkey'] : '';
+ $this->ssl_cer = isset($this->config['ssl_cer']) ? $this->config['ssl_cer'] : '';
+ $this->ssl_key = isset($this->config['ssl_key']) ? $this->config['ssl_key'] : '';
+ }
+
+ /**
+ * 获取当前错误内容
+ * @return string
+ */
+ public function getError()
+ {
+ return $this->errMsg;
+ }
+
+ /**
+ * 当前当前错误代码
+ * @return int
+ */
+ public function getErrorCode()
+ {
+ return $this->errCode;
+ }
+
+ /**
+ * 获取当前操作公众号APPID
+ * @return string
+ */
+ public function getAppid()
+ {
+ return $this->appid;
+ }
+
+ /**
+ * 获取SDK配置参数
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ /**
+ * 设置标配的请求参数,生成签名,生成接口参数xml
+ * @param array $data
+ * @return string
+ */
+ protected function createXml($data)
+ {
+ if (!isset($data['wxappid']) && !isset($data['mch_appid']) && !isset($data['appid'])) {
+ $data['appid'] = $this->appid;
+ }
+ if (!isset($data['mchid']) && !isset($data['mch_id'])) {
+ $data['mch_id'] = $this->mch_id;
+ }
+ isset($data['nonce_str']) || $data['nonce_str'] = Tools::createNoncestr();
+ $data["sign"] = Tools::getPaySign($data, $this->partnerKey);
+ return Tools::arr2xml($data);
+ }
+
+ /**
+ * POST提交XML
+ * @param array $data
+ * @param string $url
+ * @return mixed
+ */
+ public function postXml($data, $url)
+ {
+ return Tools::httpPost($url, $this->createXml($data));
+ }
+
+ /**
+ * 使用证书post请求XML
+ * @param array $data
+ * @param string $url
+ * @return mixed
+ */
+ function postXmlSSL($data, $url)
+ {
+ return Tools::httpsPost($url, $this->createXml($data), $this->ssl_cer, $this->ssl_key);
+ }
+
+ /**
+ * POST提交获取Array结果
+ * @param array $data 需要提交的数据
+ * @param string $url
+ * @param string $method
+ * @return array
+ */
+ public function getArrayResult($data, $url, $method = 'postXml')
+ {
+ return Tools::xml2arr($this->$method($data, $url));
+ }
+
+ /**
+ * 解析返回的结果
+ * @param array $result
+ * @return bool|array
+ */
+ protected function _parseResult($result)
+ {
+ if (empty($result)) {
+ $this->errCode = 'result error';
+ $this->errMsg = '解析返回结果失败';
+ return false;
+ }
+ if ($result['return_code'] !== 'SUCCESS') {
+ $this->errCode = $result['return_code'];
+ $this->errMsg = $result['return_msg'];
+ return false;
+ }
+ if (isset($result['err_code']) && $result['err_code'] !== 'SUCCESS') {
+ $this->errMsg = $result['err_code_des'];
+ $this->errCode = $result['err_code'];
+ return false;
+ }
+ return $result;
+ }
+
+ /**
+ * 创建刷卡支付参数包
+ * @param string $auth_code 授权Code号
+ * @param string $out_trade_no 商户订单号
+ * @param int $total_fee 支付费用
+ * @param string $body 订单标识
+ * @param null $goods_tag 商品标签
+ * @return array|bool
+ */
+ public function createMicroPay($auth_code, $out_trade_no, $total_fee, $body, $goods_tag = null)
+ {
+ $data = array(
+ "appid" => $this->appid,
+ "mch_id" => $this->mch_id,
+ "body" => $body,
+ "out_trade_no" => $out_trade_no,
+ "total_fee" => $total_fee,
+ "auth_code" => $auth_code,
+ "spbill_create_ip" => Tools::getAddress(),
+ );
+ empty($goods_tag) || $data['goods_tag'] = $goods_tag;
+ $json = Tools::xml2arr($this->postXml($data, self::MCH_BASE_URL . '/pay/micropay'));
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+
+ /**
+ * 支付通知验证处理
+ * @return bool|array
+ */
+ public function getNotify()
+ {
+ $disableEntities = libxml_disable_entity_loader(true);
+ $notifyInfo = (array)simplexml_load_string(file_get_contents("php://input"), 'SimpleXMLElement', LIBXML_NOCDATA);
+ libxml_disable_entity_loader($disableEntities);
+ if (empty($notifyInfo)) {
+ Tools::log('Payment notification forbidden access.', "ERR - {$this->appid}");
+ $this->errCode = '404';
+ $this->errMsg = 'Payment notification forbidden access.';
+ return false;
+ }
+ if (empty($notifyInfo['sign'])) {
+ Tools::log('Payment notification signature is missing.' . var_export($notifyInfo, true), "ERR - {$this->appid}");
+ $this->errCode = '403';
+ $this->errMsg = 'Payment notification signature is missing.';
+ return false;
+ }
+ $data = $notifyInfo;
+ unset($data['sign']);
+ if ($notifyInfo['sign'] !== Tools::getPaySign($data, $this->partnerKey)) {
+ Tools::log('Payment notification signature verification failed.' . var_export($notifyInfo, true), "ERR - {$this->appid}");
+ $this->errCode = '403';
+ $this->errMsg = 'Payment signature verification failed.';
+ return false;
+ }
+ Tools::log('Payment notification signature verification success.' . var_export($notifyInfo, true), "MSG - {$this->appid}");
+ $this->errCode = '0';
+ $this->errMsg = '';
+ return $notifyInfo;
+ }
+
+
+ /**
+ * 支付XML统一回复
+ * @param array $data 需要回复的XML内容数组
+ * @param bool $isReturn 是否返回XML内容,默认不返回
+ * @return string
+ */
+ public function replyXml(array $data, $isReturn = false)
+ {
+ $xml = Tools::arr2xml($data);
+ if ($isReturn) {
+ return $xml;
+ }
+ ob_clean();
+ exit($xml);
+ }
+
+ /**
+ * 获取预支付ID
+ * @param string $openid 用户openid,JSAPI必填
+ * @param string $body 商品标题
+ * @param string $out_trade_no 第三方订单号
+ * @param int $total_fee 订单总价
+ * @param string $notify_url 支付成功回调地址
+ * @param string $trade_type 支付类型JSAPI|NATIVE|APP
+ * @param string $goods_tag 商品标记,代金券或立减优惠功能的参数
+ * @param string $fee_type 交易币种
+ * @param null $no_credit 是否禁止信用
+ * @return bool|string
+ */
+ public function getPrepayId($openid, $body, $out_trade_no, $total_fee, $notify_url, $trade_type = "JSAPI", $goods_tag = null, $fee_type = 'CNY', $no_credit = null)
+ {
+ $postdata = array(
+ "body" => $body,
+ "out_trade_no" => $out_trade_no,
+ "fee_type" => $fee_type,
+ "total_fee" => $total_fee,
+ "notify_url" => $notify_url,
+ "trade_type" => $trade_type,
+ "spbill_create_ip" => Tools::getAddress(),
+ );
+ empty($openid) || $postdata['openid'] = $openid;
+ empty($goods_tag) || $postdata['goods_tag'] = $goods_tag;
+ is_null($no_credit) || $postdata['no_credit'] = $no_credit;
+ $result = $this->getArrayResult($postdata, self::MCH_BASE_URL . '/pay/unifiedorder');
+ if (false === $this->_parseResult($result)) {
+ return false;
+ }
+ return in_array($trade_type, array('JSAPI', 'APP')) ? $result['prepay_id'] : ($trade_type === 'MWEB' ? $result['mweb_url'] : $result['code_url']);
+ }
+
+ /**
+ * 获取二维码预支付ID
+ * @param string $openid 用户openid,JSAPI必填
+ * @param string $body 商品标题
+ * @param string $out_trade_no 第三方订单号
+ * @param int $total_fee 订单总价
+ * @param string $notify_url 支付成功回调地址
+ * @param string $goods_tag 商品标记,代金券或立减优惠功能的参数
+ * @param string $fee_type 交易币种
+ * @return bool|string
+ */
+ public function getQrcPrepayId($openid, $body, $out_trade_no, $total_fee, $notify_url, $goods_tag = null, $fee_type = 'CNY')
+ {
+ $postdata = array(
+ "body" => $body,
+ "out_trade_no" => $out_trade_no,
+ "fee_type" => $fee_type,
+ "total_fee" => $total_fee,
+ "notify_url" => $notify_url,
+ "trade_type" => 'NATIVE',
+ "spbill_create_ip" => Tools::getAddress(),
+ );
+ empty($goods_tag) || $postdata['goods_tag'] = $goods_tag;
+ empty($openid) || $postdata['openid'] = $openid;
+ $result = $this->getArrayResult($postdata, self::MCH_BASE_URL . '/pay/unifiedorder');
+ if (false === $this->_parseResult($result) || empty($result['prepay_id'])) {
+ return false;
+ }
+ return $result['prepay_id'];
+ }
+
+ /**
+ * 获取支付规二维码
+ * @param string $product_id 商户定义的商品id 或者订单号
+ * @return string
+ */
+ public function getQrcPayUrl($product_id)
+ {
+ $data = array(
+ 'appid' => $this->appid,
+ 'mch_id' => $this->mch_id,
+ 'time_stamp' => (string)time(),
+ 'nonce_str' => Tools::createNoncestr(),
+ 'product_id' => (string)$product_id,
+ );
+ $data['sign'] = Tools::getPaySign($data, $this->partnerKey);
+ return "weixin://wxpay/bizpayurl?" . http_build_query($data);
+ }
+
+
+ /**
+ * 创建JSAPI支付参数包
+ * @param string $prepay_id
+ * @return array
+ */
+ public function createMchPay($prepay_id)
+ {
+ $option = array();
+ $option["appId"] = $this->appid;
+ $option["timeStamp"] = (string)time();
+ $option["nonceStr"] = Tools::createNoncestr();
+ $option["package"] = "prepay_id={$prepay_id}";
+ $option["signType"] = "MD5";
+ $option["paySign"] = Tools::getPaySign($option, $this->partnerKey);
+ $option['timestamp'] = $option['timeStamp'];
+ return $option;
+ }
+
+ /**
+ * 关闭订单
+ * @param string $out_trade_no
+ * @return bool
+ */
+ public function closeOrder($out_trade_no)
+ {
+ $data = array('out_trade_no' => $out_trade_no);
+ $result = $this->getArrayResult($data, self::MCH_BASE_URL . '/pay/closeorder');
+ if (false === $this->_parseResult($result)) {
+ return false;
+ }
+ return ($result['return_code'] === 'SUCCESS');
+ }
+
+ /**
+ * 查询订单详情
+ * @param $out_trade_no
+ * @return bool|array
+ */
+ public function queryOrder($out_trade_no)
+ {
+ $data = array('out_trade_no' => $out_trade_no);
+ $result = $this->getArrayResult($data, self::MCH_BASE_URL . '/pay/orderquery');
+ if (false === $this->_parseResult($result)) {
+ return false;
+ }
+ return $result;
+ }
+
+ /**
+ * 订单退款接口
+ * @param string $out_trade_no 商户订单号
+ * @param string $transaction_id 微信订单号,与 out_refund_no 二选一(不选时传0或false)
+ * @param string $out_refund_no 商户退款订单号,与 transaction_id 二选一(不选时传0或false)
+ * @param int $total_fee 商户订单总金额
+ * @param int $refund_fee 退款金额,不可大于订单总金额
+ * @param int|null $op_user_id 操作员ID,默认商户ID
+ * @param string $refund_account 退款资金来源
+ * 仅针对老资金流商户使用
+ * REFUND_SOURCE_UNSETTLED_FUNDS --- 未结算资金退款(默认使用未结算资金退款)
+ * REFUND_SOURCE_RECHARGE_FUNDS --- 可用余额退款
+ * @param string $refund_desc 退款原因
+ * @param string $refund_fee_type 退款货币种类
+ * @return bool
+ */
+ public function refund($out_trade_no, $transaction_id, $out_refund_no, $total_fee, $refund_fee, $op_user_id = null, $refund_account = '', $refund_desc = '', $refund_fee_type = 'CNY')
+ {
+ $data = array();
+ $data['out_trade_no'] = $out_trade_no;
+ $data['total_fee'] = $total_fee;
+ $data['refund_fee'] = $refund_fee;
+ $data['refund_fee_type'] = $refund_fee_type;
+ $data['op_user_id'] = empty($op_user_id) ? $this->mch_id : $op_user_id;
+ !empty($out_refund_no) && $data['out_refund_no'] = $out_refund_no;
+ !empty($transaction_id) && $data['transaction_id'] = $transaction_id;
+ !empty($refund_account) && $data['refund_account'] = $refund_account;
+ !empty($refund_desc) && $data['refund_desc'] = $refund_desc;
+ $result = $this->getArrayResult($data, self::MCH_BASE_URL . '/secapi/pay/refund', 'postXmlSSL');
+ if (false === $this->_parseResult($result)) {
+ return false;
+ }
+ return ($result['return_code'] === 'SUCCESS');
+ }
+
+ /**
+ * 退款查询接口
+ * @param string $out_trade_no
+ * @return bool|array
+ */
+ public function refundQuery($out_trade_no)
+ {
+ $data = array();
+ $data['out_trade_no'] = $out_trade_no;
+ $result = $this->getArrayResult($data, self::MCH_BASE_URL . '/pay/refundquery');
+ if (false === $this->_parseResult($result)) {
+ return false;
+ }
+ return $result;
+ }
+
+ /**
+ * 获取对账单
+ * @param string $bill_date 账单日期,如 20141110
+ * @param string $bill_type ALL|SUCCESS|REFUND|REVOKED
+ * @return bool|array
+ */
+ public function getBill($bill_date, $bill_type = 'ALL')
+ {
+ $data = array();
+ $data['bill_date'] = $bill_date;
+ $data['bill_type'] = $bill_type;
+ $result = $this->postXml($data, self::MCH_BASE_URL . '/pay/downloadbill');
+ $json = Tools::xml2arr($result);
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+
+ /**
+ * 发送现金红包
+ * @param string $openid 红包接收者OPENID
+ * @param int $total_amount 红包总金额
+ * @param string $mch_billno 商户订单号
+ * @param string $sendname 商户名称
+ * @param string $wishing 红包祝福语
+ * @param string $act_name 活动名称
+ * @param string $remark 备注信息
+ * @param null|int $total_num 红包发放总人数(大于1为裂变红包)
+ * @param null|string $scene_id 场景id
+ * @param string $risk_info 活动信息
+ * @param null|string $consume_mch_id 资金授权商户号
+ * @return array|bool
+ * @link https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5
+ */
+ public function sendRedPack($openid, $total_amount, $mch_billno, $sendname, $wishing, $act_name, $remark, $total_num = 1, $scene_id = null, $risk_info = '', $consume_mch_id = null)
+ {
+ $data = array();
+ $data['mch_billno'] = $mch_billno; // 商户订单号 mch_id+yyyymmdd+10位一天内不能重复的数字
+ $data['wxappid'] = $this->appid;
+ $data['send_name'] = $sendname; //商户名称
+ $data['re_openid'] = $openid; //红包接收者
+ $data['total_amount'] = $total_amount; //红包总金额
+ $data['total_num'] = '1'; //发放人数据
+ $data['wishing'] = $wishing; //红包祝福语
+ $data['client_ip'] = Tools::getAddress(); //调用接口的机器Ip地址
+ $data['act_name'] = $act_name; //活动名称
+ $data['remark'] = $remark; //备注信息
+ $data['total_num'] = $total_num;
+ !empty($scene_id) && $data['scene_id'] = $scene_id;
+ !empty($risk_info) && $data['risk_info'] = $risk_info;
+ !empty($consume_mch_id) && $data['consume_mch_id'] = $consume_mch_id;
+ if ($total_num > 1) {
+ $data['amt_type'] = 'ALL_RAND';
+ $api = self::MCH_BASE_URL . '/mmpaymkttransfers/sendgroupredpack';
+ } else {
+ $api = self::MCH_BASE_URL . '/mmpaymkttransfers/sendredpack';
+ }
+ $result = $this->postXmlSSL($data, $api);
+ $json = Tools::xml2arr($result);
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+
+
+ /**
+ * 现金红包状态查询
+ * @param string $billno
+ * @return bool|array
+ * @link https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_7&index=6
+ */
+ public function queryRedPack($billno)
+ {
+ $data['mch_billno'] = $billno;
+ $data['bill_type'] = 'MCHT';
+ $result = $this->postXmlSSL($data, self::MCH_BASE_URL . '/mmpaymkttransfers/gethbinfo');
+ $json = Tools::xml2arr($result);
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+
+ /**
+ * 企业付款
+ * @param string $openid 红包接收者OPENID
+ * @param int $amount 红包总金额
+ * @param string $billno 商户订单号
+ * @param string $desc 备注信息
+ * @return bool|array
+ * @link https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
+ */
+ public function transfers($openid, $amount, $billno, $desc)
+ {
+ $data = array();
+ $data['mchid'] = $this->mch_id;
+ $data['mch_appid'] = $this->appid;
+ $data['partner_trade_no'] = $billno;
+ $data['openid'] = $openid;
+ $data['amount'] = $amount;
+ $data['check_name'] = 'NO_CHECK'; #不验证姓名
+ $data['spbill_create_ip'] = Tools::getAddress(); //调用接口的机器Ip地址
+ $data['desc'] = $desc; //备注信息
+ $result = $this->postXmlSSL($data, self::MCH_BASE_URL . '/mmpaymkttransfers/promotion/transfers');
+ $json = Tools::xml2arr($result);
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+
+ /**
+ * 企业付款查询
+ * @param string $billno
+ * @return bool|array
+ * @link https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
+ */
+ public function queryTransfers($billno)
+ {
+ $data['appid'] = $this->appid;
+ $data['mch_id'] = $this->mch_id;
+ $data['partner_trade_no'] = $billno;
+ $result = $this->postXmlSSL($data, self::MCH_BASE_URL . '/mmpaymkttransfers/gettransferinfo');
+ $json = Tools::xml2arr($result);
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+
+ /**
+ * 二维码链接转成短链接
+ * @param string $url 需要处理的长链接
+ * @return bool|string
+ */
+ public function shortUrl($url)
+ {
+ $data = array();
+ $data['long_url'] = $url;
+ $result = $this->getArrayResult($data, self::MCH_BASE_URL . '/tools/shorturl');
+ if (!$result || $result['return_code'] !== 'SUCCESS') {
+ $this->errCode = $result['return_code'];
+ $this->errMsg = $result['return_msg'];
+ return false;
+ }
+ if (isset($result['err_code']) && $result['err_code'] !== 'SUCCESS') {
+ $this->errMsg = $result['err_code_des'];
+ $this->errCode = $result['err_code'];
+ return false;
+ }
+ return $result['short_url'];
+ }
+
+ /**
+ * 发放代金券
+ * @param int $coupon_stock_id 代金券批次id
+ * @param string $partner_trade_no 商户此次发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性
+ * @param string $openid Openid信息
+ * @param string $op_user_id 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限
+ * @return bool|array
+ * @link https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_3
+ */
+ public function sendCoupon($coupon_stock_id, $partner_trade_no, $openid, $op_user_id = null)
+ {
+ $data = array();
+ $data['appid'] = $this->appid;
+ $data['coupon_stock_id'] = $coupon_stock_id;
+ $data['openid_count'] = 1;
+ $data['partner_trade_no'] = $partner_trade_no;
+ $data['openid'] = $openid;
+ $data['op_user_id'] = empty($op_user_id) ? $this->mch_id : $op_user_id;
+ $result = $this->postXmlSSL($data, self::MCH_BASE_URL . '/mmpaymkttransfers/send_coupon');
+ $json = Tools::xml2arr($result);
+ if (!empty($json) && false === $this->_parseResult($json)) {
+ return false;
+ }
+ return $json;
+ }
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPoi.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPoi.php
new file mode 100644
index 0000000..7073c90
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatPoi.php
@@ -0,0 +1,193 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信门店接口
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/10/26 15:43
+ */
+class WechatPoi extends Common
+{
+
+ /** 创建门店 */
+ const POI_ADD = '/cgi-bin/poi/addpoi?';
+
+ /** 查询门店信息 */
+ const POI_GET = '/cgi-bin/poi/getpoi?';
+
+ /** 获取门店列表 */
+ const POI_GET_LIST = '/cgi-bin/poi/getpoilist?';
+
+ /** 修改门店信息 */
+ const POI_UPDATE = '/cgi-bin/poi/updatepoi?';
+
+ /** 删除门店 */
+ const POI_DELETE = '/cgi-bin/poi/delpoi?';
+
+ /** 获取门店类目表 */
+ const POI_CATEGORY = '/cgi-bin/poi/getwxcategory?';
+
+ /**
+ * 创建门店
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444378120&token=&lang=zh_CN
+ * @param array $data
+ * @return bool
+ */
+ public function addPoi($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::POI_ADD . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除门店
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444378120&token=&lang=zh_CN
+ * @param string $poi_id JSON数据格式
+ * @return bool|array
+ */
+ public function delPoi($poi_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('poi_id' => $poi_id);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::POI_DELETE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 修改门店服务信息
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444378120&token=&lang=zh_CN
+ * @param array $data
+ * @return bool
+ */
+ public function updatePoi($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::POI_UPDATE . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 查询门店信息
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444378120&token=&lang=zh_CN
+ * @param string $poi_id
+ * @return bool
+ */
+ public function getPoi($poi_id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('poi_id' => $poi_id);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::POI_GET . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 查询门店列表
+ * @link https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444378120&token=&lang=zh_CN
+ * @param int $begin 开始位置,0 即为从第一条开始查询
+ * @param int $limit 返回数据条数,最大允许50,默认为20
+ * @return bool|array
+ */
+ public function getPoiList($begin = 0, $limit = 50)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $limit > 50 && $limit = 50;
+ $data = array('begin' => $begin, 'limit' => $limit);
+ $result = Tools::httpPost(self::API_BASE_URL_PREFIX . self::POI_GET_LIST . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取商家门店类目表
+ * @return bool|string
+ */
+ public function getCategory()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::POI_CATEGORY . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatReceive.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatReceive.php
new file mode 100644
index 0000000..87fab46
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatReceive.php
@@ -0,0 +1,771 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Prpcrypt;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信消息对象解析SDK
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/06/28 11:29
+ */
+class WechatReceive extends WechatMessage
+{
+
+ /** 消息回复类型 */
+ const MSGTYPE_TEXT = 'text';
+ const MSGTYPE_LINK = 'link';
+ const MSGTYPE_NEWS = 'news';
+ const MSGTYPE_IMAGE = 'image';
+ const MSGTYPE_VOICE = 'voice';
+ const MSGTYPE_EVENT = 'event';
+ const MSGTYPE_MUSIC = 'music';
+ const MSGTYPE_VIDEO = 'video';
+ const MSGTYPE_LOCATION = 'location';
+
+ /** 文本过滤 */
+ protected $_text_filter = true;
+
+ /** 消息对象 */
+ private $_receive;
+
+ /**
+ * 获取微信服务器发来的内容
+ * @return $this
+ */
+ public function getRev()
+ {
+ if ($this->_receive) {
+ return $this;
+ }
+ $postStr = !empty($this->postxml) ? $this->postxml : file_get_contents("php://input");
+ if (!empty($postStr)) {
+ $disableEntities = libxml_disable_entity_loader(true);
+ $this->_receive = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
+ libxml_disable_entity_loader($disableEntities);
+ }
+ return $this;
+ }
+
+ /**
+ * 获取微信服务器发来的信息数据
+ * @return array
+ */
+ public function getRevData()
+ {
+ return $this->_receive;
+ }
+
+ /**
+ * 获取消息发送者
+ * @return bool|string
+ */
+ public function getRevFrom()
+ {
+ if (isset($this->_receive['FromUserName'])) {
+ return $this->_receive['FromUserName'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取消息接受者
+ * @return bool|string
+ */
+ public function getRevTo()
+ {
+ if (isset($this->_receive['ToUserName'])) {
+ return $this->_receive['ToUserName'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收消息的类型
+ * @return bool|string
+ */
+ public function getRevType()
+ {
+ if (isset($this->_receive['MsgType'])) {
+ return $this->_receive['MsgType'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取消息ID
+ * @return bool|string
+ */
+ public function getRevID()
+ {
+ if (isset($this->_receive['MsgId'])) {
+ return $this->_receive['MsgId'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取消息发送时间
+ * @return bool|string
+ */
+ public function getRevCtime()
+ {
+ if (isset($this->_receive['CreateTime'])) {
+ return $this->_receive['CreateTime'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取卡券事件推送 - 卡卷审核是否通过
+ * 当Event为 card_pass_check(审核通过) 或 card_not_pass_check(未通过)
+ * @return bool|string 返回卡券ID
+ */
+ public function getRevCardPass()
+ {
+ if (isset($this->_receive['CardId'])) {
+ return $this->_receive['CardId'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取卡券事件推送 - 领取卡券
+ * 当Event为 user_get_card(用户领取卡券)
+ * @return bool|array
+ */
+ public function getRevCardGet()
+ {
+ $array = array();
+ if (isset($this->_receive['CardId'])) {
+ $array['CardId'] = $this->_receive['CardId'];
+ }
+ if (isset($this->_receive['IsGiveByFriend'])) {
+ $array['IsGiveByFriend'] = $this->_receive['IsGiveByFriend'];
+ }
+ $array['OldUserCardCode'] = $this->_receive['OldUserCardCode'];
+ if (isset($this->_receive['UserCardCode']) && !empty($this->_receive['UserCardCode'])) {
+ $array['UserCardCode'] = $this->_receive['UserCardCode'];
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 获取卡券事件推送 - 删除卡券
+ * 当Event为 user_del_card (用户删除卡券)
+ * @return bool|array
+ */
+ public function getRevCardDel()
+ {
+ if (isset($this->_receive['CardId'])) { //卡券 ID
+ $array['CardId'] = $this->_receive['CardId'];
+ }
+ if (isset($this->_receive['UserCardCode']) && !empty($this->_receive['UserCardCode'])) {
+ $array['UserCardCode'] = $this->_receive['UserCardCode'];
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 获取接收消息内容正文
+ * @return bool
+ */
+ public function getRevContent()
+ {
+ if (isset($this->_receive['Content'])) {
+ return $this->_receive['Content'];
+ } elseif (isset($this->_receive['Recognition'])) {
+ return $this->_receive['Recognition'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收消息图片
+ * @return array|bool
+ */
+ public function getRevPic()
+ {
+ if (isset($this->_receive['PicUrl'])) {
+ return array(
+ 'mediaid' => $this->_receive['MediaId'],
+ 'picurl' => (string)$this->_receive['PicUrl'],
+ );
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收消息链接
+ * @return bool|array
+ */
+ public function getRevLink()
+ {
+ if (isset($this->_receive['Url'])) {
+ return array(
+ 'url' => $this->_receive['Url'],
+ 'title' => $this->_receive['Title'],
+ 'description' => $this->_receive['Description'],
+ );
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收地理位置
+ * @return bool|array
+ */
+ public function getRevGeo()
+ {
+ if (isset($this->_receive['Location_X'])) {
+ return array(
+ 'x' => $this->_receive['Location_X'],
+ 'y' => $this->_receive['Location_Y'],
+ 'scale' => $this->_receive['Scale'],
+ 'label' => $this->_receive['Label'],
+ );
+ }
+ return false;
+ }
+
+ /**
+ * 获取上报地理位置事件
+ * @return bool|array
+ */
+ public function getRevEventGeo()
+ {
+ if (isset($this->_receive['Latitude'])) {
+ return array(
+ 'x' => $this->_receive['Latitude'],
+ 'y' => $this->_receive['Longitude'],
+ 'precision' => $this->_receive['Precision'],
+ );
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收事件推送
+ * @return bool|array
+ */
+ public function getRevEvent()
+ {
+ if (isset($this->_receive['Event'])) {
+ $array['event'] = $this->_receive['Event'];
+ }
+ if (isset($this->_receive['EventKey'])) {
+ $array['key'] = $this->_receive['EventKey'];
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 获取自定义菜单的扫码推事件信息
+ *
+ * 事件类型为以下两种时则调用此方法有效
+ * Event 事件类型, scancode_push
+ * Event 事件类型, scancode_waitmsg
+ * @return bool|array
+ */
+ public function getRevScanInfo()
+ {
+ if (isset($this->_receive['ScanCodeInfo'])) {
+ if (!is_array($this->_receive['ScanCodeInfo'])) {
+ $array = (array)$this->_receive['ScanCodeInfo'];
+ $this->_receive['ScanCodeInfo'] = $array;
+ } else {
+ $array = $this->_receive['ScanCodeInfo'];
+ }
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 获取自定义菜单的图片发送事件信息
+ *
+ * 事件类型为以下三种时则调用此方法有效
+ * Event 事件类型,pic_sysphoto 弹出系统拍照发图的事件推送
+ * Event 事件类型,pic_photo_or_album 弹出拍照或者相册发图的事件推送
+ * Event 事件类型,pic_weixin 弹出微信相册发图器的事件推送
+ *
+ * @return bool|array
+ * array (
+ * 'Count' => '2',
+ * 'PicList' =>array (
+ * 'item' =>array (
+ * 0 =>array ('PicMd5Sum' => 'aaae42617cf2a14342d96005af53624c'),
+ * 1 =>array ('PicMd5Sum' => '149bd39e296860a2adc2f1bb81616ff8'),
+ * ),
+ * ),
+ * )
+ *
+ */
+ public function getRevSendPicsInfo()
+ {
+ if (isset($this->_receive['SendPicsInfo'])) {
+ if (!is_array($this->_receive['SendPicsInfo'])) {
+ $array = (array)$this->_receive['SendPicsInfo'];
+ if (isset($array['PicList'])) {
+ $array['PicList'] = (array)$array['PicList'];
+ $item = $array['PicList']['item'];
+ $array['PicList']['item'] = array();
+ foreach ($item as $key => $value) {
+ $array['PicList']['item'][$key] = (array)$value;
+ }
+ }
+ $this->_receive['SendPicsInfo'] = $array;
+ } else {
+ $array = $this->_receive['SendPicsInfo'];
+ }
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 获取自定义菜单的地理位置选择器事件推送
+ *
+ * 事件类型为以下时则可以调用此方法有效
+ * Event 事件类型,location_select 弹出地理位置选择器的事件推送
+ *
+ * @return bool|array
+ * array (
+ * 'Location_X' => '33.731655000061',
+ * 'Location_Y' => '113.29955200008047',
+ * 'Scale' => '16',
+ * 'Label' => '某某市某某区某某路',
+ * 'Poiname' => '',
+ * )
+ *
+ */
+ public function getRevSendGeoInfo()
+ {
+ if (isset($this->_receive['SendLocationInfo'])) {
+ if (!is_array($this->_receive['SendLocationInfo'])) {
+ $array = (array)$this->_receive['SendLocationInfo'];
+ if (empty($array['Poiname'])) {
+ $array['Poiname'] = "";
+ }
+ if (empty($array['Label'])) {
+ $array['Label'] = "";
+ }
+ $this->_receive['SendLocationInfo'] = $array;
+ } else {
+ $array = $this->_receive['SendLocationInfo'];
+ }
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 获取接收语音推送
+ * @return bool|array
+ */
+ public function getRevVoice()
+ {
+ if (isset($this->_receive['MediaId'])) {
+ return array(
+ 'mediaid' => $this->_receive['MediaId'],
+ 'format' => $this->_receive['Format'],
+ );
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收视频推送
+ * @return array|bool
+ */
+ public function getRevVideo()
+ {
+ if (isset($this->_receive['MediaId'])) {
+ return array(
+ 'mediaid' => $this->_receive['MediaId'],
+ 'thumbmediaid' => $this->_receive['ThumbMediaId'],
+ );
+ }
+ return false;
+ }
+
+ /**
+ * 获取接收TICKET
+ * @return bool|string
+ */
+ public function getRevTicket()
+ {
+ if (isset($this->_receive['Ticket'])) {
+ return $this->_receive['Ticket'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取二维码的场景值
+ * @return bool|string
+ */
+ public function getRevSceneId()
+ {
+ if (isset($this->_receive['EventKey'])) {
+ return str_replace('qrscene_', '', $this->_receive['EventKey']);
+ }
+ return false;
+ }
+
+ /**
+ * 获取主动推送的消息ID
+ * 经过验证,这个和普通的消息MsgId不一样
+ * 当Event为 MASSSENDJOBFINISH 或 TEMPLATESENDJOBFINISH
+ * @return bool|string
+ */
+ public function getRevTplMsgID()
+ {
+ if (isset($this->_receive['MsgID'])) {
+ return $this->_receive['MsgID'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取模板消息发送状态
+ * @return bool|string
+ */
+ public function getRevStatus()
+ {
+ if (isset($this->_receive['Status'])) {
+ return $this->_receive['Status'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取群发或模板消息发送结果
+ * 当Event为 MASSSENDJOBFINISH 或 TEMPLATESENDJOBFINISH,即高级群发/模板消息
+ * @return bool|array
+ */
+ public function getRevResult()
+ {
+ if (isset($this->_receive['Status'])) { //发送是否成功,具体的返回值请参考 高级群发/模板消息 的事件推送说明
+ $array['Status'] = $this->_receive['Status'];
+ }
+ if (isset($this->_receive['MsgID'])) { //发送的消息id
+ $array['MsgID'] = $this->_receive['MsgID'];
+ }
+ //以下仅当群发消息时才会有的事件内容
+ if (isset($this->_receive['TotalCount'])) { //分组或openid列表内粉丝数量
+ $array['TotalCount'] = $this->_receive['TotalCount'];
+ }
+ if (isset($this->_receive['FilterCount'])) { //过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,用户接收已超4条的过滤)后,准备发送的粉丝数
+ $array['FilterCount'] = $this->_receive['FilterCount'];
+ }
+ if (isset($this->_receive['SentCount'])) { //发送成功的粉丝数
+ $array['SentCount'] = $this->_receive['SentCount'];
+ }
+ if (isset($this->_receive['ErrorCount'])) { //发送失败的粉丝数
+ $array['ErrorCount'] = $this->_receive['ErrorCount'];
+ }
+ if (isset($array) && count($array) > 0) {
+ return $array;
+ }
+ return false;
+ }
+
+ /**
+ * 获取多客服会话状态推送事件 - 接入会话
+ * 当Event为 kfcreatesession 即接入会话
+ * @return bool|string
+ */
+ public function getRevKFCreate()
+ {
+ if (isset($this->_receive['KfAccount'])) {
+ return $this->_receive['KfAccount'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取多客服会话状态推送事件 - 关闭会话
+ * 当Event为 kfclosesession 即关闭会话
+ * @return bool|string
+ */
+ public function getRevKFClose()
+ {
+ if (isset($this->_receive['KfAccount'])) {
+ return $this->_receive['KfAccount'];
+ }
+ return false;
+ }
+
+ /**
+ * 获取多客服会话状态推送事件 - 转接会话
+ * 当Event为 kfswitchsession 即转接会话
+ * @return bool|array
+ */
+ public function getRevKFSwitch()
+ {
+ if (isset($this->_receive['FromKfAccount'])) { //原接入客服
+ $array['FromKfAccount'] = $this->_receive['FromKfAccount'];
+ }
+ if (isset($this->_receive['ToKfAccount'])) { //转接到客服
+ $array['ToKfAccount'] = $this->_receive['ToKfAccount'];
+ }
+ return (isset($array) && count($array) > 0) ? $array : false;
+ }
+
+ /**
+ * 发送客服消息
+ * @param array $data 消息结构{"touser":"OPENID","msgtype":"news","news":{...}}
+ * @return bool|array
+ */
+ public function sendCustomMessage($data)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . "/message/custom/send?access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 转发多客服消息
+ * @param string $customer_account
+ * @return $this
+ */
+ public function transfer_customer_service($customer_account = '')
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'CreateTime' => time(),
+ 'MsgType' => 'transfer_customer_service',
+ );
+ if ($customer_account) {
+ $msg['TransInfo'] = array('KfAccount' => $customer_account);
+ }
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 设置发送消息
+ * @param string|array $msg 消息数组
+ * @param bool $append 是否在原消息数组追加
+ * @return array
+ */
+ public function Message($msg = '', $append = false)
+ {
+ if (is_null($msg)) {
+ $this->_msg = array();
+ } elseif (is_array($msg)) {
+ if ($append) {
+ $this->_msg = array_merge($this->_msg, $msg);
+ } else {
+ $this->_msg = $msg;
+ }
+ return $this->_msg;
+ }
+ return $this->_msg;
+ }
+
+ /**
+ * 设置文本消息
+ * @param string $text 文本内容
+ * @return $this
+ */
+ public function text($text = '')
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'MsgType' => self::MSGTYPE_TEXT,
+ 'Content' => $this->_auto_text_filter($text),
+ 'CreateTime' => time(),
+ );
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 设置图片消息
+ * @param string $mediaid 图片媒体ID
+ * @return $this
+ */
+ public function image($mediaid = '')
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'MsgType' => self::MSGTYPE_IMAGE,
+ 'Image' => array('MediaId' => $mediaid),
+ 'CreateTime' => time(),
+ );
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 设置语音回复消息
+ * @param string $mediaid 语音媒体ID
+ * @return $this
+ */
+ public function voice($mediaid = '')
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'MsgType' => self::MSGTYPE_VOICE,
+ 'Voice' => array('MediaId' => $mediaid),
+ 'CreateTime' => time(),
+ );
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 设置视频回复消息
+ * @param string $mediaid 视频媒体ID
+ * @param string $title 视频标题
+ * @param string $description 视频描述
+ * @return $this
+ */
+ public function video($mediaid = '', $title = '', $description = '')
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'MsgType' => self::MSGTYPE_VIDEO,
+ 'Video' => array(
+ 'MediaId' => $mediaid,
+ 'Title' => $title,
+ 'Description' => $description,
+ ),
+ 'CreateTime' => time(),
+ );
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 设置音乐回复消息
+ * @param string $title 音乐标题
+ * @param string $desc 音乐描述
+ * @param string $musicurl 音乐地址
+ * @param string $hgmusicurl 高清音乐地址
+ * @param string $thumbmediaid 音乐图片缩略图的媒体id(可选)
+ * @return $this
+ */
+ public function music($title, $desc, $musicurl, $hgmusicurl = '', $thumbmediaid = '')
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'CreateTime' => time(),
+ 'MsgType' => self::MSGTYPE_MUSIC,
+ 'Music' => array(
+ 'Title' => $title,
+ 'Description' => $desc,
+ 'MusicUrl' => $musicurl,
+ 'HQMusicUrl' => $hgmusicurl,
+ ),
+ );
+ if ($thumbmediaid) {
+ $msg['Music']['ThumbMediaId'] = $thumbmediaid;
+ }
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 设置回复图文
+ * @param array $newsData
+ * @return $this
+ */
+ public function news($newsData = array())
+ {
+ $msg = array(
+ 'ToUserName' => $this->getRevFrom(),
+ 'FromUserName' => $this->getRevTo(),
+ 'CreateTime' => time(),
+ 'MsgType' => self::MSGTYPE_NEWS,
+ 'ArticleCount' => count($newsData),
+ 'Articles' => $newsData,
+ );
+ $this->Message($msg);
+ return $this;
+ }
+
+ /**
+ * 回复微信服务器
+ * @param array $msg 要发送的信息(默认取$this->_msg)
+ * @param bool $return 是否返回信息而不抛出到浏览器(默认:否)
+ * @return bool|string
+ */
+ public function reply($msg = array(), $return = false)
+ {
+ if (empty($msg)) {
+ if (empty($this->_msg)) { //防止不先设置回复内容,直接调用reply方法导致异常
+ return false;
+ }
+ $msg = $this->_msg;
+ }
+ $xmldata = Tools::arr2xml($msg);
+ if ($this->encrypt_type == 'aes') { //如果来源消息为加密方式
+ !class_exists('Prpcrypt', false) && require __DIR__ . '/Lib/Prpcrypt.php';
+ $pc = new Prpcrypt($this->encodingAesKey);
+ // 如果是第三方平台,加密得使用 component_appid
+ $array = $pc->encrypt($xmldata, empty($this->config['component_appid']) ? $this->appid : $this->config['component_appid']);
+ $ret = $array[0];
+ if ($ret != 0) {
+ Tools::log('Encrypt Error!', "ERR - {$this->appid}");
+ return false;
+ }
+ $timestamp = time();
+ $nonce = rand(77, 999) * rand(605, 888) * rand(11, 99);
+ $encrypt = $array[1];
+ $tmpArr = array($this->token, $timestamp, $nonce, $encrypt);
+ sort($tmpArr, SORT_STRING);
+ $signature = sha1(implode($tmpArr));
+ $format = "<xml><Encrypt><![CDATA[%s]]></Encrypt><MsgSignature><![CDATA[%s]]></MsgSignature><TimeStamp>%s</TimeStamp><Nonce><![CDATA[%s]]></Nonce></xml>";
+ $xmldata = sprintf($format, $encrypt, $signature, $timestamp, $nonce);
+ }
+ if ($return) {
+ return $xmldata;
+ }
+ echo $xmldata;
+ }
+
+ /**
+ * 过滤文字回复\r\n换行符
+ * @param string $text
+ * @return string
+ */
+ private function _auto_text_filter($text)
+ {
+ if (!$this->_text_filter) {
+ return $text;
+ }
+ return str_replace("\r\n", "\n", $text);
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatScript.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatScript.php
new file mode 100644
index 0000000..b26dd1f
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatScript.php
@@ -0,0 +1,138 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信前端 JavaScript 签名SDK
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/06/28 11:24
+ */
+class WechatScript extends Common
+{
+
+ /**
+ * JSAPI授权TICKET
+ * @var string
+ */
+ public $jsapi_ticket;
+
+ /**
+ * 删除JSAPI授权TICKET
+ * @param string $appid
+ * @return bool
+ */
+ public function resetJsTicket($appid = '')
+ {
+ $this->jsapi_ticket = '';
+ $authname = 'wechat_jsapi_ticket_' . empty($appid) ? $this->appid : $appid;
+ Tools::removeCache($authname);
+ return true;
+ }
+
+ /**
+ * 获取JSAPI授权TICKET
+ * @param string $appid 用于多个appid时使用,可空
+ * @param string $jsapi_ticket 手动指定jsapi_ticket,非必要情况不建议用
+ * @param string $access_token 获取 jsapi_ticket 指定 access_token
+ * @return bool|string
+ */
+ public function getJsTicket($appid = '', $jsapi_ticket = '', $access_token = '')
+ {
+ if (empty($access_token)) {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $access_token = $this->access_token;
+ }
+ if (empty($appid)) {
+ $appid = $this->appid;
+ }
+ # 手动指定token,优先使用
+ if ($jsapi_ticket) {
+ $this->jsapi_ticket = $jsapi_ticket;
+ return $this->jsapi_ticket;
+ }
+ # 尝试从缓存中读取
+ $cache = 'wechat_jsapi_ticket_' . $appid;
+ $jt = Tools::getCache($cache);
+ if ($jt) {
+ return $this->jsapi_ticket = $jt;
+ }
+ # 检测事件注册
+ if (isset(Loader::$callback[__FUNCTION__])) {
+ return $this->jsapi_ticket = call_user_func_array(Loader::$callback[__FUNCTION__], array(&$this, &$cache));
+ }
+ # 调接口获取
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::GET_TICKET_URL . "access_token={$access_token}" . '&type=jsapi');
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ $this->jsapi_ticket = $json['ticket'];
+ Tools::setCache($cache, $this->jsapi_ticket, $json['expires_in'] ? intval($json['expires_in']) - 100 : 3600);
+ return $this->jsapi_ticket;
+ }
+ return false;
+ }
+
+ /**
+ * 获取JsApi使用签名
+ * @param string $url 网页的URL,自动处理#及其后面部分
+ * @param int $timestamp 当前时间戳 (为空则自动生成)
+ * @param string $noncestr 随机串 (为空则自动生成)
+ * @param string $appid 用于多个appid时使用,可空
+ * @param string $access_token 获取 jsapi_ticket 指定 access_token
+ * @return array|bool 返回签名字串
+ */
+ public function getJsSign($url, $timestamp = 0, $noncestr = '', $appid = '', $access_token = '')
+ {
+ if (!$this->jsapi_ticket && !$this->getJsTicket($appid, '', $access_token) || empty($url)) {
+ return false;
+ }
+ $data = array(
+ "jsapi_ticket" => $this->jsapi_ticket,
+ "timestamp" => empty($timestamp) ? time() : $timestamp,
+ "noncestr" => '' . empty($noncestr) ? Tools::createNoncestr(16) : $noncestr,
+ "url" => trim($url),
+ );
+ return array(
+ "url" => $url,
+ 'debug' => false,
+ "appId" => empty($appid) ? $this->appid : $appid,
+ "nonceStr" => $data['noncestr'],
+ "timestamp" => $data['timestamp'],
+ "signature" => Tools::getSignature($data, 'sha1'),
+ 'jsApiList' => array(
+ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone',
+ 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem',
+ 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'closeWindow', 'scanQRCode', 'chooseWXPay',
+ 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation',
+ 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard',
+ 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice',
+ 'openWXDeviceLib', 'closeWXDeviceLib', 'getWXDeviceInfos', 'sendDataToWXDevice', 'disconnectWXDevice', 'getWXDeviceTicket', 'connectWXDevice',
+ 'startScanWXDevice', 'stopScanWXDevice', 'onWXDeviceBindStateChange', 'onScanWXDeviceResult', 'onReceiveDataFromWXDevice',
+ 'onWXDeviceBluetoothStateChange', 'onWXDeviceStateChange'
+ )
+ );
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatService.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatService.php
new file mode 100644
index 0000000..56aa4c1
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatService.php
@@ -0,0 +1,408 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Cache;
+use Wechat\Lib\Tools;
+
+/**
+ * 公众号第三方平台SDK
+ *
+ * @version 1.0
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/10/18 00:35:55
+ */
+class WechatService
+{
+
+ const URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin/component';
+ // 获取服务access_token
+ const COMPONENT_TOKEN_URL = '/api_component_token';
+ // 获取(刷新)授权公众号的令牌
+ const REFRESH_ACCESS_TOKEN = '/api_authorizer_token';
+ // 获取预授权码
+ const PREAUTH_CODE_URL = '/api_create_preauthcode';
+ // 获取公众号的授权信息
+ const QUERY_AUTH_URL = '/api_query_auth';
+ // 获取授权方的账户信息
+ const GET_AUTHORIZER_INFO_URL = '/api_get_authorizer_info';
+ // 获取授权方的选项设置信息
+ const GET_AUTHORIZER_OPTION_URL = '/api_get_authorizer_option';
+ // 设置授权方的选项信息
+ const SET_AUTHORIZER_OPTION_URL = '/api_set_authorizer_option';
+
+ // 微信后台推送的ticket 每十分钟更新一次
+ public $errCode;
+ // 服务appid
+ public $errMsg;
+ // 服务appsecret
+ protected $component_verify_ticket;
+ // 公众号消息校验Token
+ protected $component_appid;
+ // 公众号消息加解密Key
+ protected $component_appsecret;
+ // 服务令牌
+ protected $component_token;
+ // 授权方appid
+ protected $component_encodingaeskey;
+ // 授权方令牌
+ protected $component_access_token;
+ // 刷新令牌
+ protected $authorizer_appid;
+ // JSON数据
+ protected $pre_auth_code;
+ // 错误消息
+ protected $data;
+
+ /**
+ * WechatService constructor.
+ * @param array $options
+ */
+ public function __construct($options = array())
+ {
+ $options = Loader::config($options);
+ $this->component_encodingaeskey = !empty($options['component_encodingaeskey']) ? $options['component_encodingaeskey'] : '';
+ $this->component_verify_ticket = !empty($options['component_verify_ticket']) ? $options['component_verify_ticket'] : '';
+ $this->component_appsecret = !empty($options['component_appsecret']) ? $options['component_appsecret'] : '';
+ $this->component_token = !empty($options['component_token']) ? $options['component_token'] : '';
+ $this->component_appid = !empty($options['component_appid']) ? $options['component_appid'] : '';
+ }
+
+ /**
+ * 接收公众平台推送的 Ticket
+ * @return bool|array
+ */
+ public function getComonentTicket()
+ {
+ $receive = new WechatReceive(array(
+ 'appid' => $this->component_appid,
+ 'appsecret' => $this->component_appsecret,
+ 'encodingaeskey' => $this->component_encodingaeskey,
+ 'token' => $this->component_token,
+ 'cachepath' => Cache::$cachepath
+ ));
+ # 会话内容解密状态判断
+ if (false === $receive->valid()) {
+ $this->errCode = $receive->errCode;
+ $this->errMsg = $receive->errMsg;
+ Tools::log("Get Wechat Push ComponentVerifyTicket Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ return false;
+ }
+ $data = $receive->getRev()->getRevData();
+ if ($data['InfoType'] === 'component_verify_ticket' && !empty($data['ComponentVerifyTicket'])) {
+ # 记录推送日志到微信SDK
+ Tools::log("Wechat Push ComponentVerifyTicket Success. ");
+ Tools::setCache('component_verify_ticket', $data['ComponentVerifyTicket']);
+ }
+ return $data;
+ }
+
+ /**
+ * 获取(刷新)授权公众号的令牌
+ * @注意1. 授权公众号访问access token2小时有效
+ * @注意2. 一定保存好新的刷新令牌
+ * @param string $authorizer_appid 授权方APPID
+ * @param string $authorizer_refresh_token 授权方刷新令牌
+ * @return bool|string
+ */
+ public function refreshAccessToken($authorizer_appid, $authorizer_refresh_token)
+ {
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ if (empty($this->component_access_token)) {
+ return false;
+ }
+ $data = array();
+ $data['component_appid'] = $this->component_appid;
+ $data['authorizer_appid'] = $authorizer_appid;
+ $data['authorizer_refresh_token'] = $authorizer_refresh_token;
+ $url = self::URL_PREFIX . self::REFRESH_ACCESS_TOKEN . "?component_access_token={$this->component_access_token}";
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ if (($result = $this->_decode($result)) === false) {
+ Tools::log("Get getAuthorizerOption Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ }
+ return $result;
+ }
+
+ /**
+ * 获取或刷新服务 AccessToken
+ * @return bool|string
+ */
+ public function getComponentAccessToken()
+ {
+ $cacheKey = 'wechat_component_access_token';
+ $this->component_access_token = Tools::getCache($cacheKey);
+ if (empty($this->component_access_token)) {
+ $data = array();
+ $data['component_appid'] = $this->component_appid;
+ $data['component_appsecret'] = $this->component_appsecret;
+ $data['component_verify_ticket'] = $this->component_verify_ticket;
+ $url = self::URL_PREFIX . self::COMPONENT_TOKEN_URL;
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ if (($this->component_access_token = $this->_decode($result, 'component_access_token')) === false) {
+ Tools::log("Get getComponentAccessToken Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ return false;
+ }
+ Tools::setCache($cacheKey, $this->component_access_token, 7200);
+ }
+ return $this->component_access_token;
+ }
+
+ /**
+ * 解析JSON数据
+ * @param string $result
+ * @param string|null $field
+ * @return bool|array
+ */
+ private function _decode($result, $field = null)
+ {
+ $this->data = json_decode($result, true);
+ if (!empty($this->data['errcode'])) {
+ $this->errCode = $this->data['errcode'];
+ $this->errMsg = $this->data['errmsg'];
+ return false;
+ }
+ if ($this->data && !is_null($field)) {
+ if (isset($this->data[$field])) {
+ return $this->data[$field];
+ } else {
+ return false;
+ }
+ }
+ return $this->data;
+ }
+
+ /**
+ * 获取公众号的授权信息
+ *
+ * @param string $authorization_code
+ * @return bool|array
+ */
+ public function getAuthorizationInfo($authorization_code)
+ {
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ if (empty($this->component_access_token)) {
+ return false;
+ }
+ $data = array();
+ $data['component_appid'] = $this->component_appid;
+ $data['authorization_code'] = $authorization_code;
+ $url = self::URL_PREFIX . self::QUERY_AUTH_URL . "?component_access_token={$this->component_access_token}";
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ $authorization_info = $this->_decode($result, 'authorization_info');
+ if (empty($authorization_info)) {
+ Tools::log("Get getAuthorizationInfo Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ return false;
+ }
+ $authorization_info['func_info'] = $this->_parseFuncInfo($authorization_info['func_info']);
+ return $authorization_info;
+ }
+
+ /**
+ * 解析授权信息,返回以逗号分割的数据
+ * @param array $func_info
+ * @return string
+ */
+ private function _parseFuncInfo($func_info)
+ {
+ $authorization_list = array();
+ foreach ($func_info as $func) {
+ foreach ($func as $f) {
+ isset($f['id']) && $authorization_list[] = $f['id'];
+ }
+ }
+ return join($authorization_list, ',');
+ }
+
+ /**
+ * 获取授权方的账户信息
+ * @param string $authorizer_appid
+ * @return bool
+ */
+ public function getWechatInfo($authorizer_appid)
+ {
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ $data = array();
+ $data['component_access_token'] = $this->component_access_token;
+ $data['component_appid'] = $this->component_appid;
+ $data['authorizer_appid'] = $authorizer_appid;
+ $url = self::URL_PREFIX . self::GET_AUTHORIZER_INFO_URL . "?component_access_token={$this->component_access_token}";
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ $authorizer_info = $this->_decode($result, 'authorizer_info');
+ if (empty($authorizer_info)) {
+ Tools::log("Get WechatInfo Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ return false;
+ }
+ $author_data = array_merge($authorizer_info, $this->data['authorization_info']);
+ $author_data['service_type_info'] = $author_data['service_type_info']['id'];
+ $author_data['verify_type_info'] = $author_data['verify_type_info']['id'];
+ $author_data['func_info'] = $this->_parseFuncInfo($author_data['func_info']);
+ $author_data['business_info'] = json_encode($author_data['business_info']);
+ return $author_data;
+ }
+
+ /**
+ * 获取授权方的选项设置信息
+ * @param string $authorizer_appid
+ * @param string $option_name
+ * @return bool
+ */
+ public function getAuthorizerOption($authorizer_appid, $option_name)
+ {
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ if (empty($this->authorizer_appid)) {
+ return false;
+ }
+ $data = array();
+ $data['component_appid'] = $this->component_appid;
+ $data['authorizer_appid'] = $authorizer_appid;
+ $data['option_name'] = $option_name;
+ $url = self::URL_PREFIX . self::GET_AUTHORIZER_OPTION_URL . "?component_access_token={$this->component_access_token}";
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ if (($result = $this->_decode($result)) === false) {
+ Tools::log("Get getAuthorizerOption Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ }
+ return $result;
+ }
+
+ /**
+ * 设置授权方的选项信息
+ * @param string $authorizer_appid
+ * @param string $option_name
+ * @param string $option_value
+ * @return bool
+ */
+ public function setAuthorizerOption($authorizer_appid, $option_name, $option_value)
+ {
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ if (empty($this->authorizer_appid)) {
+ return false;
+ }
+ $data = array();
+ $data['component_appid'] = $this->component_appid;
+ $data['authorizer_appid'] = $authorizer_appid;
+ $data['option_name'] = $option_name;
+ $data['option_value'] = $option_value;
+ $url = self::URL_PREFIX . self::SET_AUTHORIZER_OPTION_URL . "?component_access_token={$this->component_access_token}";
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ if (($result = $this->_decode($result)) === false) {
+ Tools::log("Get setAuthorizerOption Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ }
+ return $result;
+ }
+
+ /**
+ * 获取授权回跳地址
+ * @param string $redirect_uri
+ * @return bool
+ */
+ public function getAuthRedirect($redirect_uri)
+ {
+ empty($this->pre_auth_code) && $this->getPreauthCode();
+ if (empty($this->pre_auth_code)) {
+ return false;
+ }
+ return "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid={$this->component_appid}&pre_auth_code={$this->pre_auth_code}&redirect_uri={$redirect_uri}";
+ }
+
+ /**
+ * 获取预授权码
+ *
+ * @return bool|string
+ */
+ public function getPreauthCode()
+ {
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ if (empty($this->component_access_token)) {
+ return false;
+ }
+ $data = array();
+ $data['component_appid'] = $this->component_appid;
+ $url = self::URL_PREFIX . self::PREAUTH_CODE_URL . "?component_access_token={$this->component_access_token}";
+ $result = Tools::httpPost($url, Tools::json_encode($data));
+ $this->pre_auth_code = $this->_decode($result, 'pre_auth_code');
+ if (empty($this->pre_auth_code)) {
+ Tools::log("Get getPreauthCode Faild. {$this->errMsg} [$this->errCode]", "ERR - {$this->authorizer_appid}");
+ }
+ return $this->pre_auth_code;
+ }
+
+ /**
+ * oauth 授权跳转接口
+ * @param string $appid
+ * @param string $redirect_uri
+ * @param string $scope snsapi_userinfo|snsapi_base
+ * @return string
+ */
+ public function getOauthRedirect($appid, $redirect_uri, $scope = 'snsapi_userinfo')
+ {
+ return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri=" . urlencode($redirect_uri)
+ . "&response_type=code&scope={$scope}&state={$appid}&component_appid={$this->component_appid}#wechat_redirect";
+ }
+
+ /**
+ * 通过code获取Access Token
+ * @param string $appid
+ * @return bool|array
+ */
+ public function getOauthAccessToken($appid)
+ {
+ $code = isset($_GET['code']) ? $_GET['code'] : '';
+ if (empty($code)) {
+ return false;
+ }
+ empty($this->component_access_token) && $this->getComponentAccessToken();
+ if (empty($this->component_access_token)) {
+ return false;
+ }
+ $url = "https://api.weixin.qq.com/sns/oauth2/component/access_token?appid={$appid}&code={$code}&grant_type=authorization_code&"
+ . "component_appid={$this->component_appid}&component_access_token={$this->component_access_token}";
+ $json = $this->parseJson(Tools::httpGet($url));
+ if ($json !== false) {
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 解析JSON数据
+ * @param string $result
+ * @return bool
+ */
+ private function parseJson($result)
+ {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return false;
+ }
+ return $json;
+ }
+
+ /**
+ * 获取关注者详细信息
+ * @param string $openid
+ * @param string $oauthAccessToken
+ * @return bool|array {subscribe,openid,nickname,sex,city,province,country,language,headimgurl,subscribe_time,[unionid]}
+ * 注意:unionid字段 只有在用户将公众号绑定到公众号第三方平台账号后,才会出现。建议调用前用isset()检测一下
+ */
+ public function getOauthUserInfo($openid, $oauthAccessToken)
+ {
+ $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$oauthAccessToken}&openid={$openid}&lang=zh_CN";
+ return $this->parseJson(Tools::httpGet($url));
+ }
+
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatUser.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatUser.php
new file mode 100644
index 0000000..0798951
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/Wechat/WechatUser.php
@@ -0,0 +1,612 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+namespace Wechat;
+
+use Wechat\Lib\Common;
+use Wechat\Lib\Tools;
+
+/**
+ * 微信粉丝操作SDK
+ *
+ * @author Anyon <zoujingli@qq.com>
+ * @date 2016/06/28 11:20
+ */
+class WechatUser extends Common
+{
+
+ /** 获取粉丝列表 */
+ const USER_GET_URL = '/user/get?';
+ /* 获取粉丝信息 */
+ const USER_INFO_URL = '/user/info?';
+ /* 批量获取粉丝信息 */
+ const USER_BATCH_INFO_URL = '/user/info/batchget?';
+ /* 更新粉丝标注 */
+ const USER_UPDATEREMARK_URL = '/user/info/updateremark?';
+
+ /** 创建标签 */
+ const TAGS_CREATE_URL = '/tags/create?';
+ /* 获取标签列表 */
+ const TAGS_GET_URL = '/tags/get?';
+ /* 更新标签 */
+ const TAGS_UPDATE_URL = '/tags/update?';
+ /* 删除标签 */
+ const TAGS_DELETE_URL = '/tags/delete?';
+ /* 获取标签下的粉丝列表 */
+ const TAGS_GET_USER_URL = '/user/tag/get?';
+ /* 批量为粉丝打标签 */
+ const TAGS_MEMBER_BATCHTAGGING = '/tags/members/batchtagging?';
+ /* 批量为粉丝取消标签 */
+ const TAGS_MEMBER_BATCHUNTAGGING = '/tags/members/batchuntagging?';
+ /* 获取粉丝的标签列表 */
+ const TAGS_LIST = '/tags/getidlist?';
+
+ /** 获取分组列表 */
+ const GROUP_GET_URL = '/groups/get?';
+ /* 获取粉丝所在的分组 */
+ const USER_GROUP_URL = '/groups/getid?';
+ /* 创建分组 */
+ const GROUP_CREATE_URL = '/groups/create?';
+ /* 更新分组 */
+ const GROUP_UPDATE_URL = '/groups/update?';
+ /* 删除分组 */
+ const GROUP_DELETE_URL = '/groups/delete?';
+ /* 修改粉丝所在分组 */
+ const GROUP_MEMBER_UPDATE_URL = '/groups/members/update?';
+ /* 批量修改粉丝所在分组 */
+ const GROUP_MEMBER_BATCHUPDATE_URL = '/groups/members/batchupdate?';
+
+ /** 获取黑名单列表 */
+ const BACKLIST_GET_URL = '/tags/members/getblacklist?';
+ /* 批量拉黑粉丝 */
+ const BACKLIST_ADD_URL = '/tags/members/batchblacklist?';
+ /* 批量取消拉黑粉丝 */
+ const BACKLIST_DEL_URL = '/tags/members/batchunblacklist?';
+
+ /**
+ * 批量获取关注粉丝列表
+ * @param string $next_openid
+ * @return bool|array
+ */
+ public function getUserList($next_openid = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::USER_GET_URL . "access_token={$this->access_token}&next_openid={$next_openid}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取关注者详细信息
+ * @param string $openid
+ * @return bool|array {subscribe,openid,nickname,sex,city,province,country,language,headimgurl,subscribe_time,[unionid]}
+ * @注意:unionid字段 只有在粉丝将公众号绑定到微信开放平台账号后,才会出现。建议调用前用isset()检测一下
+ */
+ public function getUserInfo($openid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::USER_INFO_URL . "access_token={$this->access_token}&openid={$openid}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量获取用户基本信息
+ * @param array $openids 用户oepnid列表(最多支持100个openid)
+ * @param string $lang 指定返回语言
+ * @return bool|mixed
+ */
+ public function getUserBatchInfo(array $openids, $lang = 'zh_CN')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('user_list' => array());
+ foreach (array_unique($openids) as $openid) {
+ $data['user_list'][] = array('openid' => $openid, 'lang' => $lang);
+ }
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::USER_BATCH_INFO_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode']) || !isset($json['user_info_list'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json['user_info_list'];
+ }
+ return false;
+ }
+
+ /**
+ * 设置粉丝备注名
+ * @param string $openid
+ * @param string $remark 备注名
+ * @return bool|array
+ */
+ public function updateUserRemark($openid, $remark)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid' => $openid, 'remark' => $remark);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::USER_UPDATEREMARK_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取粉丝分组列表
+ * @return bool|array
+ */
+ public function getGroup()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::GROUP_GET_URL . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除粉丝分组
+ * @param type $id
+ * @return bool
+ */
+ public function delGroup($id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('group' => array('id' => $id));
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::GROUP_DELETE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取粉丝所在分组
+ * @param string $openid
+ * @return bool|int 成功则返回粉丝分组id
+ */
+ public function getUserGroup($openid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid' => $openid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::USER_GROUP_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode']) || !isset($json['groupid'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json['groupid'];
+ }
+ return false;
+ }
+
+ /**
+ * 新增自定分组
+ * @param string $name 分组名称
+ * @return bool|array
+ */
+ public function createGroup($name)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('group' => array('name' => $name));
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::GROUP_CREATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 更改分组名称
+ * @param int $groupid 分组id
+ * @param string $name 分组名称
+ * @return bool|array
+ */
+ public function updateGroup($groupid, $name)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('group' => array('id' => $groupid, 'name' => $name));
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::GROUP_UPDATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 移动粉丝分组
+ * @param int $groupid 分组id
+ * @param string $openid 粉丝openid
+ * @return bool|array
+ */
+ public function updateGroupMembers($groupid, $openid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid' => $openid, 'to_groupid' => $groupid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::GROUP_MEMBER_UPDATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量移动粉丝分组
+ * @param string $groupid 分组ID
+ * @param string $openid_list 粉丝openid数组(一次不能超过50个)
+ * @return bool|array
+ */
+ public function batchUpdateGroupMembers($groupid, $openid_list)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid_list' => $openid_list, 'to_groupid' => $groupid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::GROUP_MEMBER_BATCHUPDATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 新增自定标签
+ * @param string $name 标签名称
+ * @return bool|array
+ */
+ public function createTags($name)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('tag' => array('name' => $name));
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_CREATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 更新标签
+ * @param string $id 标签id
+ * @param string $name 标签名称
+ * @return bool|array
+ */
+ public function updateTag($id, $name)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('tag' => array('id' => $id, 'name' => $name));
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_UPDATE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取粉丝标签列表
+ * @return bool|array
+ */
+ public function getTags()
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $result = Tools::httpGet(self::API_URL_PREFIX . self::TAGS_GET_URL . "access_token={$this->access_token}");
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 删除粉丝标签
+ * @param string $id
+ * @return bool
+ */
+ public function delTag($id)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('tag' => array('id' => $id));
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_DELETE_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取标签下的粉丝列表
+ * @param string $tagid
+ * @param string $next_openid
+ * @return bool
+ */
+ public function getTagUsers($tagid, $next_openid = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('tagid' => $tagid, 'next_openid' => $next_openid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_GET_USER_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量为粉丝打标签
+ * @param string $tagid 标签ID
+ * @param array $openid_list 粉丝openid数组,一次不能超过50个
+ * @return bool|array
+ */
+ public function batchAddUserTag($tagid, $openid_list)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid_list' => $openid_list, 'tagid' => $tagid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_MEMBER_BATCHTAGGING . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量为粉丝取消标签
+ * @param string $tagid 标签ID
+ * @param array $openid_list 粉丝openid数组,一次不能超过50个
+ * @return bool|array
+ */
+ public function batchDeleteUserTag($tagid, $openid_list)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid_list' => $openid_list, 'tagid' => $tagid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_MEMBER_BATCHUNTAGGING . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 获取粉丝的标签列表
+ * @param string $openid 粉丝openid
+ * @return bool|array
+ */
+ public function getUserTags($openid)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid' => $openid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::TAGS_LIST . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode']) || !isset($json['tagid_list'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json['tagid_list'];
+ }
+ return false;
+ }
+
+ /**
+ * 批量获取黑名单粉丝
+ * @param string $begin_openid
+ * @return bool|array
+ */
+ public function getBacklist($begin_openid = '')
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = empty($begin_openid) ? array() : array('begin_openid' => $begin_openid);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::BACKLIST_GET_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量拉黑粉丝
+ * @param string $openids
+ * @return bool|array
+ */
+ public function addBacklist($openids)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid_list' => $openids);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::BACKLIST_ADD_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+ /**
+ * 批量取消拉黑粉丝
+ * @param string $openids
+ * @return bool|array
+ */
+ public function delBacklist($openids)
+ {
+ if (!$this->access_token && !$this->getAccessToken()) {
+ return false;
+ }
+ $data = array('openid_list' => $openids);
+ $result = Tools::httpPost(self::API_URL_PREFIX . self::BACKLIST_DEL_URL . "access_token={$this->access_token}", Tools::json_encode($data));
+ if ($result) {
+ $json = json_decode($result, true);
+ if (empty($json) || !empty($json['errcode'])) {
+ $this->errCode = isset($json['errcode']) ? $json['errcode'] : '505';
+ $this->errMsg = isset($json['errmsg']) ? $json['errmsg'] : '无法解析接口返回内容!';
+ return $this->checkRetry(__FUNCTION__, func_get_args());
+ }
+ return $json;
+ }
+ return false;
+ }
+
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/composer.json b/public/system/storage/vendor/zoujingli/wechat-php-sdk/composer.json
new file mode 100644
index 0000000..b3f9dfd
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/composer.json
@@ -0,0 +1,18 @@
+{
+ "type": "project",
+ "name": "zoujingli/wechat-php-sdk",
+ "homepage": "http://www.kancloud.cn/zoujingli/wechat-php-sdk",
+ "description": "WeChat development of SDK",
+ "license": "MIT",
+ "keywords": [
+ "wechat-php-sdk"
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "autoload": {
+ "psr-4": {
+ "Wechat\\": "./Wechat"
+ }
+ }
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/include.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/include.php
new file mode 100644
index 0000000..c2aa13f
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/include.php
@@ -0,0 +1,17 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+if (!class_exists('\Wechat\Loader')) {
+ require __DIR__ . DIRECTORY_SEPARATOR . 'Wechat' . DIRECTORY_SEPARATOR . 'Loader.php';
+}
diff --git a/public/system/storage/vendor/zoujingli/wechat-php-sdk/test.php b/public/system/storage/vendor/zoujingli/wechat-php-sdk/test.php
new file mode 100644
index 0000000..ed4ee38
--- /dev/null
+++ b/public/system/storage/vendor/zoujingli/wechat-php-sdk/test.php
@@ -0,0 +1,68 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/wechat-php-sdk
+// +----------------------------------------------------------------------
+
+# 引入文件
+require 'include.php';
+
+# 配置参数
+$config = array(
+ 'token' => '',
+ 'appid' => '',
+ 'appsecret' => '',
+ 'encodingaeskey' => '',
+);
+
+# 加载对应操作接口
+$wechat = &\Wechat\Loader::get('User', $config);
+$userlist = $wechat->getUserList();
+
+var_dump($userlist);
+var_dump($wechat->errMsg);
+var_dump($wechat->errCode);
+
+exit;
+
+// 第三方平台 JSSDK 签名包
+
+$wechat = Db::name('WechatConfig')->where('authorizer_appid', 'wx60a43dd8161666d4')->find();
+// 第三方授权获取到的 Access_token
+$access_token = $wechat['authorizer_access_token'];
+// 参与授权的公众号 APPID
+$authorizer_appid = $wechat['authorizer_appid'];
+// 当前微信页面URL地址(完整)
+$current_url = url('', '', true, true);
+// 实例SDK脚本
+$script = load_wechat('Script', $authorizer_appid);
+// 获取JS签名包
+$result = $script->getJsSign($current_url, 0, '', $authorizer_appid, $access_token);
+dump($result);
+dump([$script->errMsg, $script->errCode]);
+
+$json = json_encode($result, JSON_PRETTY_PRINT);
+echo '<script src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>';
+echo "
+<script>
+ // JSSDK 错误处理
+ wx.error(function(){
+ //alert(JSON.stringify(arguments));
+ });
+ // JSSDK 配置参数
+ wx.config({$json});
+ // JSSDK 初始化成功
+ wx.ready(function(){
+ alert('初始化成功!');
+ wx.hideOptionMenu();
+ });
+</script>
+"; \ No newline at end of file