├── .gitignore ├── composer.json ├── tests └── MWSClientTest.php ├── src ├── MWSEndPoint.php ├── AmazonMarketPlaceProduct.php └── MWSClient.php ├── README.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | test.php 3 | xml.xml 4 | xsd/ 5 | documentor.php 6 | test.csv 7 | .idea/ -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcs/amazon-mws", 3 | "description": "Library to interface with Amazon MWS", 4 | "license": "MIT", 5 | "keywords": [ 6 | "amazon", 7 | "mws" 8 | ], 9 | "minimum-stability": "dev", 10 | "authors": [ 11 | { 12 | "name": "Michiel Meertens", 13 | "email": "meertensmichiel28@gmail.com" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=7.0", 18 | "ext-mbstring": "*", 19 | "ext-json": "*", 20 | "ext-simplexml": "*", 21 | "guzzlehttp/guzzle": "*", 22 | "spatie/array-to-xml": "^2.1", 23 | "league/csv": "^9", 24 | "ext-curl": "*" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "^7" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "MCS\\": "src" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/MWSClientTest.php: -------------------------------------------------------------------------------- 1 | 'A1PA6795UKMFR9', 9 | 'Seller_Id' => 'SOME_SELLER_ID', 10 | 'Access_Key_ID' => 'SOME_ACCESS_KEY', 11 | 'Secret_Access_Key' => 'SOME_SECRET_ACCESS_KEY', 12 | 'MWSAuthToken' => '' 13 | ]; 14 | 15 | public function testValidateCredentialsOnWrongCredentials(): void { 16 | $stub = $this->getMockBuilder(\MCS\MWSClient::class) 17 | ->disableOriginalConstructor() 18 | ->setMethods(['ListOrderItems']) 19 | ->getMock(); 20 | 21 | $stub->method('ListOrderItems') 22 | ->will($this->throwException(new Exception('Some Exception'))); 23 | 24 | $this->assertFalse($stub->validateCredentials()); 25 | } 26 | 27 | public function testValidateCredentialsOnRightCredentials(): void { 28 | $stub = $this->getMockBuilder(\MCS\MWSClient::class) 29 | ->disableOriginalConstructor() 30 | ->setMethods(['ListOrderItems']) 31 | ->getMock(); 32 | 33 | $stub->method('ListOrderItems') 34 | ->will($this->throwException(new Exception('Invalid AmazonOrderId: validate'))); 35 | 36 | $this->assertTrue($stub->validateCredentials()); 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/MWSEndPoint.php: -------------------------------------------------------------------------------- 1 | [ 13 | 'method' => 'POST', 14 | 'action' => 'ListRecommendations', 15 | 'path' => '/Recommendations/2013-04-01', 16 | 'date' => '2013-04-01' 17 | ], 18 | 'ListMarketplaceParticipations' => [ 19 | 'method' => 'POST', 20 | 'action' => 'ListMarketplaceParticipations', 21 | 'path' => '/Sellers/2011-07-01', 22 | 'date' => '2011-07-01' 23 | ], 24 | 'GetMyPriceForSKU' => [ 25 | 'method' => 'POST', 26 | 'action' => 'GetMyPriceForSKU', 27 | 'path' => '/Products/2011-10-01', 28 | 'date' => '2011-10-01' 29 | ], 30 | 'GetMyPriceForASIN' => [ 31 | 'method' => 'POST', 32 | 'action' => 'GetMyPriceForASIN', 33 | 'path' => '/Products/2011-10-01', 34 | 'date' => '2011-10-01' 35 | ], 36 | 'GetProductCategoriesForSKU' => [ 37 | 'method' => 'POST', 38 | 'action' => 'GetProductCategoriesForSKU', 39 | 'path' => '/Products/2011-10-01', 40 | 'date' => '2011-10-01' 41 | ], 42 | 'GetProductCategoriesForASIN' => [ 43 | 'method' => 'POST', 44 | 'action' => 'GetProductCategoriesForASIN', 45 | 'path' => '/Products/2011-10-01', 46 | 'date' => '2011-10-01' 47 | ], 48 | 'GetCompetitivePricingForSKU' => [ 49 | 'method' => 'POST', 50 | 'action' => 'GetCompetitivePricingForSKU', 51 | 'path' => '/Products/2011-10-01', 52 | 'date' => '2011-10-01' 53 | ], 54 | 'GetFeedSubmissionResult' => [ 55 | 'method' => 'POST', 56 | 'action' => 'GetFeedSubmissionResult', 57 | 'path' => '/', 58 | 'date' => '2009-01-01' 59 | ], 60 | 'GetFeedSubmissionList' => [ 61 | 'method' => 'POST', 62 | 'action' => 'GetFeedSubmissionList', 63 | 'path' => '/', 64 | 'date' => '2009-01-01' 65 | ], 66 | 'GetReportList' => [ 67 | 'method' => 'POST', 68 | 'action' => 'GetReportList', 69 | 'path' => '/', 70 | 'date' => '2009-01-01' 71 | ], 72 | 'GetReportListByNextToken' => [ 73 | 'method' => 'POST', 74 | 'action' => 'GetReportListByNextToken', 75 | 'path' => '/', 76 | 'date' => '2009-01-01' 77 | ], 78 | 'GetReportRequestList' => [ 79 | 'method' => 'POST', 80 | 'action' => 'GetReportRequestList', 81 | 'path' => '/', 82 | 'date' => '2009-01-01' 83 | ], 84 | 'GetReport' => [ 85 | 'method' => 'POST', 86 | 'action' => 'GetReport', 87 | 'path' => '/', 88 | 'date' => '2009-01-01' 89 | ], 90 | 'RequestReport' => [ 91 | 'method' => 'POST', 92 | 'action' => 'RequestReport', 93 | 'path' => '/', 94 | 'date' => '2009-01-01' 95 | ], 96 | 'ListInventorySupply' => [ 97 | 'method' => 'POST', 98 | 'action' => 'ListInventorySupply', 99 | 'path' => '/FulfillmentInventory', 100 | 'date' => '2010-10-01' 101 | ], 102 | 'ListOrders' => [ 103 | 'method' => 'POST', 104 | 'action' => 'ListOrders', 105 | 'path' => '/Orders/2013-09-01', 106 | 'date' => '2013-09-01' 107 | ], 108 | 'ListOrdersByNextToken' => [ 109 | 'method' => 'POST', 110 | 'action' => 'ListOrdersByNextToken', 111 | 'path' => '/Orders/2013-09-01', 112 | 'date' => '2013-09-01' 113 | ], 114 | 'ListOrderItems' => [ 115 | 'method' => 'POST', 116 | 'action' => 'ListOrderItems', 117 | 'path' => '/Orders/2013-09-01', 118 | 'date' => '2013-09-01' 119 | ], 120 | 'GetOrder' => [ 121 | 'method' => 'POST', 122 | 'action' => 'GetOrder', 123 | 'path' => '/Orders/2013-09-01', 124 | 'date' => '2013-09-01' 125 | ], 126 | 'SubmitFeed' => [ 127 | 'method' => 'POST', 128 | 'action' => 'SubmitFeed', 129 | 'path' => '/', 130 | 'date' => '2009-01-01' 131 | ], 132 | 'GetMatchingProductForId' => [ 133 | 'method' => 'POST', 134 | 'action' => 'GetMatchingProductForId', 135 | 'path' => '/Products/2011-10-01', 136 | 'date' => '2011-10-01' 137 | ], 138 | 'ListMatchingProducts' => [ 139 | 'method' => 'POST', 140 | 'action' => 'ListMatchingProducts', 141 | 'path' => '/Products/2011-10-01', 142 | 'date' => '2011-10-01' 143 | ], 144 | 'GetCompetitivePricingForASIN' => [ 145 | 'method' => 'POST', 146 | 'action' => 'GetCompetitivePricingForASIN', 147 | 'path' => '/Products/2011-10-01', 148 | 'date' => '2011-10-01' 149 | ], 150 | 'GetLowestOfferListingsForASIN' => [ 151 | 'method' => 'POST', 152 | 'action' => 'GetLowestOfferListingsForASIN', 153 | 'path' => '/Products/2011-10-01', 154 | 'date' => '2011-10-01' 155 | ], 156 | 'GetLowestPricedOffersForASIN' => [ 157 | 'method' => 'POST', 158 | 'action' => 'GetLowestPricedOffersForASIN', 159 | 'path' => '/Products/2011-10-01', 160 | 'date' => '2011-10-01' 161 | ], 162 | /** Finances API section **/ 163 | 'ListFinancialEvents' => [ 164 | 'method' => 'POST', 165 | 'action' => 'ListFinancialEvents', 166 | 'path' => self::FINANCES_API_PATH, 167 | 'date' => '2015-05-01' 168 | ], 169 | 'ListFinancialEventsByNextToken' => [ 170 | 'method' => 'POST', 171 | 'action' => 'ListFinancialEventsByNextToken', 172 | 'path' => self::FINANCES_API_PATH, 173 | 'date' => '2015-05-01' 174 | ] 175 | ]; 176 | 177 | public static function get($key) 178 | { 179 | if (isset(self::$endpoints[$key])) { 180 | return self::$endpoints[$key]; 181 | } else { 182 | throw new Exception('Call to undefined endpoint ' . $key); 183 | } 184 | } 185 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amazon Marketplace Webservices 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/mcs/amazon-mws/v/stable)](https://packagist.org/packages/mcs/amazon-mws) 4 | [![Latest Unstable Version](https://poser.pugx.org/mcs/amazon-mws/v/unstable)](https://packagist.org/packages/mcs/amazon-mws) 5 | [![License](https://poser.pugx.org/mcs/amazon-mws/license)](https://packagist.org/packages/mcs/amazon-mws) 6 | [![Total Downloads](https://poser.pugx.org/mcs/amazon-mws/downloads)](https://packagist.org/packages/mcs/amazon-mws) 7 | 8 | Interaction with the Amazon Api for vendors called MWS 9 | 10 | ### Change your composer.json file 11 | 12 | ``` 13 | "require": { 14 | // ... 15 | "mcs/amazon-mws": "*", 16 | // ... 17 | }, 18 | "repositories": [ 19 | { 20 | "name": "mcs/amazon-mws", 21 | "type": "git", 22 | "url": "git@github.com:forecho/amazon-mws.git" 23 | } 24 | ] 25 | ``` 26 | 27 | ### Installation: 28 | ```bash 29 | $ composer require mcs/amazon-mws 30 | ``` 31 | 32 | ### Initiate the client 33 | 34 | ```php 35 | require_once 'vendor/autoload.php'; 36 | 37 | $client = new MCS\MWSClient([ 38 | 'Marketplace_Id' => '', 39 | 'Seller_Id' => '', 40 | 'Access_Key_ID' => '', 41 | 'Secret_Access_Key' => '', 42 | 'MWSAuthToken' => '' // Optional. Only use this key if you are a third party user/developer 43 | ]); 44 | 45 | // Optionally check if the supplied credentials are valid 46 | if ($client->validateCredentials()) { 47 | // Credentials are valid 48 | } else { 49 | // Credentials are not valid 50 | } 51 | ``` 52 | 53 | ### Get orders 54 | 55 | ```php 56 | $fromDate = new DateTime('2016-01-01'); 57 | $orders = $client->ListOrders($fromDate); 58 | foreach ($orders as $order) { 59 | $items = $client->ListOrderItems($order['AmazonOrderId']); 60 | print_r($order); 61 | print_r($items); 62 | } 63 | ``` 64 | 65 | ### Get product attributes 66 | 67 | ```php 68 | $searchField = 'ASIN'; // Can be GCID, SellerSKU, UPC, EAN, ISBN, or JAN 69 | 70 | $result = $client->GetMatchingProductForId([ 71 | '', '', '' 72 | ], $searchField); 73 | 74 | print_r($result); 75 | ``` 76 | 77 | ### Create or update a marketplace product 78 | 79 | ```php 80 | public function uploadAmazon(string $productType, Product $product, int $productNode, $otherAttributes = []) 81 | { 82 | $client = new MCS\MWSClient([ 83 | 'Marketplace_Id' => '', 84 | 'Seller_Id' => '', 85 | 'Access_Key_ID' => '', 86 | 'Secret_Access_Key' => '', 87 | 'MWSAuthToken' => '' // Optional. Only use this key if you are a third party user/developer 88 | ]); 89 | $amazonProducts = []; 90 | $postItems = []; 91 | $amazonProduct = new AmazonMarketPlaceProduct(); 92 | if ($product->productSku) { 93 | $amazonProduct->setSku($product->parent_sku) 94 | ->setFeedProductType($productType) 95 | ->setBrand($product->brand) 96 | ->setTitle($product->title) 97 | ->setManufacturer($product->manufacturer) 98 | ->setRecommendedBrowseNodes($productNode) 99 | ->setParentChild('Parent') 100 | ->setOtherAttributes(\app\core\helpers\ArrayHelper::clearValue($otherAttributes)) 101 | ->setVariationTheme($product->variation_theme); 102 | array_push($amazonProducts, $amazonProduct); 103 | array_push($postItems, $amazonProduct->toArray(false)); 104 | 105 | foreach ($product->productSku as $productSku) { 106 | $retailPrice = $productSku->retail_price ?: 0; 107 | $salePrice = $productSku->sale_price ?: 0; 108 | $saleDate = $salePrice ? explode('~', $productSku->sale_date) : []; 109 | 110 | $_amazonProduct = clone $amazonProduct; 111 | $_amazonProduct->setSku($productSku->product_sku) 112 | ->setFeedProductType($productType) 113 | ->setBrand($product->brand) 114 | ->setTitle($product->title) 115 | ->setManufacturer($product->manufacturer) 116 | ->setPrice($retailPrice > 0 ? CurrencyConverter::CNYConverter($currency, $retailPrice) : '') 117 | ->setSalePrice($salePrice > 0 ? CurrencyConverter::CNYConverter($currency, $salePrice) : '') 118 | ->setProductId($amazonProductId) 119 | ->setSizeName($productSku->size ?: '') 120 | ->setColorName($productSku->color ?: '') 121 | ->setProductIdType('EAN') 122 | ->setCurrency($currency) 123 | ->setConditionType('New') 124 | ->setWeight($product->weight) 125 | ->setQuantity($product->quantity) 126 | ->setParentChild('Child') 127 | ->setParentSku($parentSku) 128 | ->setSaleFromDate(count($saleDate) == 2 ? $saleDate[0] : '') 129 | ->setSaleEndDate(count($saleDate) == 2 ? $saleDate[1] : '') 130 | ->setVariationTheme($product->variation_theme) 131 | ->setKeywords($product->search_keyword) 132 | ->setRecommendedBrowseNodes($productNode) 133 | ->setBulletPoint($features) 134 | ->setDescription($product->description) 135 | ->setOtherAttributes($otherAttributes) 136 | ->setImage($productSku->images); 137 | array_push($amazonProducts, $_amazonProduct); 138 | array_push($postItems, $_amazonProduct->toArray(false)); 139 | } 140 | } else { 141 | $retailPrice = $product->price ?: 0; 142 | $salePrice = $product->sale_price ?: 0; 143 | $saleDate = $salePrice ? explode('~', $product->sale_date) : []; 144 | 145 | $amazonProduct->setSku($parentSku) 146 | ->setFeedProductType($productType) 147 | ->setBrand($product->brand) 148 | ->setTitle($product->{$titleAttribute}) 149 | ->setManufacturer($product->manufacturer) 150 | ->setPrice($retailPrice > 0 ? CurrencyConverter::CNYConverter($currency, $retailPrice) : '') 151 | ->setSalePrice($salePrice > 0 ? CurrencyConverter::CNYConverter($currency, $salePrice) : '') 152 | ->setProductId($amazonProductId) 153 | ->setProductIdType('EAN') 154 | ->setCurrency($currency) 155 | ->setConditionType('New') 156 | ->setWeight($product->weight) 157 | ->setQuantity($product->quantity) 158 | ->setSaleFromDate(count($saleDate) == 2 ? $saleDate[0] : '') 159 | ->setSaleEndDate(count($saleDate) == 2 ? $saleDate[1] : '') 160 | ->setKeywords($product->search_keyword) 161 | ->setRecommendedBrowseNodes($productNode) 162 | ->setBulletPoint($features) 163 | ->setDescription($product->description) 164 | ->setOtherAttributes($otherAttributes) 165 | ->setImage($product->images); 166 | array_push($amazonProducts, $amazonProduct); 167 | array_push($postItems, $amazonProduct->toArray(false)); 168 | } 169 | 170 | // You can also submit an array of MWSProduct objects 171 | $feed = $client->postProduct( 172 | $amazonProducts, 173 | 'fptcustomcustom', 174 | '2019.0501', 175 | 'SE9NRV9MSUdIVElOR19BTkRfTEFNUFM=' 176 | ); 177 | return $feed; 178 | } 179 | ``` 180 | 181 | 182 | ### Update product stock 183 | 184 | ```php 185 | $result = $client->updateStock([ 186 | 'sku1' => 20, 187 | 'sku2' => 9, 188 | ]); 189 | print_r($result); 190 | 191 | $info = $client->GetFeedSubmissionResult($result['FeedSubmissionId']); 192 | print_r($info); 193 | ``` 194 | 195 | ### Update product stock with fulfillment latency specified 196 | 197 | ```php 198 | $result = $client->updateStockWithFulfillmentLatency([ 199 | ['sku' => 'sku1', 'quantity' => 20, 'latency' => 1], 200 | ['sku' => 'sku2', 'quantity' => 20, 'latency' => 1], 201 | ]); 202 | print_r($result); 203 | 204 | $info = $client->GetFeedSubmissionResult($result['FeedSubmissionId']); 205 | print_r($info); 206 | ``` 207 | 208 | ### Update product pricing 209 | 210 | ```php 211 | $result = $client->updatePrice([ 212 | 'sku1' => '20.99', 213 | 'sku2' => '100.00', 214 | ]); 215 | print_r($result); 216 | 217 | $info = $client->GetFeedSubmissionResult($result['FeedSubmissionId']); 218 | print_r($info); 219 | ``` 220 | 221 | ### Reports 222 | 223 | For all report types, visit: [http://docs.developer.amazonservices.com](http://docs.developer.amazonservices.com/en_US/reports/Reports_ReportType.html#ReportTypeCategories__ListingsReports) 224 | 225 | ```php 226 | $reportId = $client->RequestReport('_GET_MERCHANT_LISTINGS_DATA_'); 227 | // Wait a couple of minutes and get it's content 228 | $report_content = $client->GetReport($reportId); 229 | print_r($report_content); 230 | ``` 231 | ### Available methods 232 | 233 | View source for detailed argument description. 234 | All methods starting with an uppercase character are also documented in the [Amazon MWS documentation](http://docs.developer.amazonservices.com/en_US/dev_guide/index.html) 235 | 236 | ```php 237 | // Returns the current competitive price of a product, based on ASIN. 238 | $client->GetCompetitivePricingForASIN($asin_array = []); 239 | 240 | // Returns the feed processing report and the Content-MD5 header. 241 | $client->GetFeedSubmissionResult($FeedSubmissionId); 242 | 243 | // Returns pricing information for the lowest-price active offer listings for up to 20 products, based on ASIN. 244 | $client->GetLowestOfferListingsForASIN($asin_array = [], $ItemCondition = null); 245 | 246 | // Returns lowest priced offers for a single product, based on ASIN. 247 | $client->GetLowestPricedOffersForASIN($asin, $ItemCondition = 'New'); 248 | 249 | // Returns a list of products and their attributes, based on a list of ASIN, GCID, SellerSKU, UPC, EAN, ISBN, and JAN values. 250 | $client->GetMatchingProductForId($asin_array, $type = 'ASIN'); 251 | 252 | // Returns a list of products and their attributes, based on an open text based query 253 | $client->ListMatchingProducts($query, $query_context_id = null); 254 | 255 | // Returns pricing information for your own offer listings, based on ASIN. 256 | $client->GetMyPriceForASIN($asin_array = [], $ItemCondition = null); 257 | 258 | // Returns pricing information for your own offer listings, based on SKU. 259 | $client->GetMyPriceForSKU($sku_array = [], $ItemCondition = null); 260 | 261 | // Returns an order based on the AmazonOrderId values that you specify. 262 | $client->GetOrder($AmazonOrderId); 263 | 264 | // Returns the parent product categories that a product belongs to, based on ASIN. 265 | $client->GetProductCategoriesForASIN($ASIN); 266 | 267 | // Returns the parent product categories that a product belongs to, based on SellerSKU. 268 | $client->GetProductCategoriesForSKU($SellerSKU); 269 | 270 | // Get a report's content 271 | $client->GetReport($ReportId); 272 | 273 | // Returns a list of reports that were created in the previous 90 days. 274 | $client->GetReportList($ReportTypeList = []); 275 | 276 | // Get a report's processing status 277 | $client->GetReportRequestStatus($ReportId); 278 | 279 | // Get a list's inventory for Amazon's fulfillment 280 | $client->ListInventorySupply($sku_array = []); 281 | 282 | // Returns a list of marketplaces that the seller submitting the request can sell in, and a list of participations that include seller-specific information in that marketplace 283 | $client->ListMarketplaceParticipations(); 284 | 285 | // Returns order items based on the AmazonOrderId that you specify. 286 | $client->ListOrderItems($AmazonOrderId); 287 | 288 | // Returns orders created or updated during a time frame that you specify. 289 | $client->ListOrders($from, $allMarketplaces = false, $states = ['Unshipped', 'PartiallyShipped'], $FulfillmentChannel = 'MFN'); 290 | 291 | // Returns your active recommendations for a specific category or for all categories for a specific marketplace. 292 | $client->ListRecommendations($RecommendationCategory = null); 293 | 294 | // Creates a report request and submits the request to Amazon MWS. 295 | $client->RequestReport($report, $StartDate = null, $EndDate = null); 296 | 297 | // Uploads a feed for processing by Amazon MWS. 298 | $client->SubmitFeed($FeedType, $feedContent, $debug = false); 299 | 300 | // Call this method to get the raw feed instead of sending it 301 | $client->debugNextFeed(); 302 | 303 | // Post to create or update a product (_POST_FLAT_FILE_LISTINGS_DATA_) 304 | $client->postProduct($MWSProduct); 305 | 306 | // Update a product's price 307 | $client->updatePrice($array); 308 | 309 | // Update a product's stock quantity 310 | $client->updateStock($array); 311 | 312 | // A method to quickly check if the supplied credentials are valid 313 | $client->validateCredentials(); 314 | ``` 315 | -------------------------------------------------------------------------------- /src/AmazonMarketPlaceProduct.php: -------------------------------------------------------------------------------- 1 | sku = $sku; 47 | return $this; 48 | } 49 | 50 | /** 51 | * @param mixed $price 52 | * @return AmazonMarketPlaceProduct 53 | */ 54 | public function setPrice($price) 55 | { 56 | $this->price = $price; 57 | return $this; 58 | } 59 | 60 | /** 61 | * @param int $quantity 62 | * @return AmazonMarketPlaceProduct 63 | */ 64 | public function setQuantity(int $quantity): AmazonMarketPlaceProduct 65 | { 66 | $this->quantity = $quantity; 67 | return $this; 68 | } 69 | 70 | /** 71 | * @param mixed $product_id 72 | * @return AmazonMarketPlaceProduct 73 | */ 74 | public function setProductId($product_id) 75 | { 76 | $this->product_id = $product_id; 77 | return $this; 78 | } 79 | 80 | /** 81 | * @param mixed $product_id_type 82 | * @return AmazonMarketPlaceProduct 83 | */ 84 | public function setProductIdType($product_id_type) 85 | { 86 | $this->product_id_type = $product_id_type; 87 | return $this; 88 | } 89 | 90 | /** 91 | * @param string $condition_type 92 | * @return AmazonMarketPlaceProduct 93 | */ 94 | public function setConditionType(string $condition_type): AmazonMarketPlaceProduct 95 | { 96 | $this->condition_type = $condition_type; 97 | return $this; 98 | } 99 | 100 | /** 101 | * @param mixed $condition_note 102 | * @return AmazonMarketPlaceProduct 103 | */ 104 | public function setConditionNote($condition_note) 105 | { 106 | $this->condition_note = $condition_note; 107 | return $this; 108 | } 109 | 110 | /** 111 | * @param mixed $title 112 | * @return AmazonMarketPlaceProduct 113 | */ 114 | public function setTitle($title) 115 | { 116 | $this->title = $title; 117 | return $this; 118 | } 119 | 120 | /** 121 | * @param mixed $brand 122 | * @return AmazonMarketPlaceProduct 123 | */ 124 | public function setBrand($brand) 125 | { 126 | $this->brand = $brand; 127 | return $this; 128 | } 129 | 130 | /** 131 | * @param mixed $shipping 132 | * @return AmazonMarketPlaceProduct 133 | */ 134 | public function setShipping($shipping) 135 | { 136 | $this->shipping = $shipping; 137 | return $this; 138 | } 139 | 140 | /** 141 | * @param array $image 142 | * @return AmazonMarketPlaceProduct 143 | */ 144 | public function setImage(array $image): AmazonMarketPlaceProduct 145 | { 146 | $this->image = $image; 147 | return $this; 148 | } 149 | 150 | /** 151 | * @param array $validation_errors 152 | * @return AmazonMarketPlaceProduct 153 | */ 154 | public function setValidationErrors(array $validation_errors): AmazonMarketPlaceProduct 155 | { 156 | $this->validation_errors = $validation_errors; 157 | return $this; 158 | } 159 | 160 | /** 161 | * @param array $conditions 162 | * @return AmazonMarketPlaceProduct 163 | */ 164 | public function setConditions(array $conditions): AmazonMarketPlaceProduct 165 | { 166 | $this->conditions = $conditions; 167 | return $this; 168 | } 169 | 170 | /** 171 | * @return float 172 | */ 173 | public function getWeight() 174 | { 175 | return $this->weight; 176 | } 177 | 178 | /** 179 | * @param float $weight 180 | * @return AmazonMarketPlaceProduct 181 | */ 182 | public function setWeight($weight) 183 | { 184 | $this->weight = $weight; 185 | return $this; 186 | } 187 | 188 | /** 189 | * @return string 190 | */ 191 | public function getRecommendedBrowseNodes() 192 | { 193 | return $this->recommended_browse_nodes; 194 | } 195 | 196 | /** 197 | * @param string $recommended_browse_nodes 198 | * @return AmazonMarketPlaceProduct 199 | */ 200 | public function setRecommendedBrowseNodes($recommended_browse_nodes) 201 | { 202 | $this->recommended_browse_nodes = $recommended_browse_nodes; 203 | return $this; 204 | } 205 | 206 | /** 207 | * @return string 208 | */ 209 | public function getFeedProductType() 210 | { 211 | return $this->feed_product_type; 212 | } 213 | 214 | /** 215 | * @param string $feed_product_type 216 | * @return AmazonMarketPlaceProduct 217 | */ 218 | public function setFeedProductType($feed_product_type) 219 | { 220 | $this->feed_product_type = $feed_product_type; 221 | return $this; 222 | } 223 | 224 | /** 225 | * @param string $description 226 | * @return AmazonMarketPlaceProduct 227 | */ 228 | public function setDescription(string $description) 229 | { 230 | $this->description = $description; 231 | return $this; 232 | } 233 | 234 | private $validation_errors = []; 235 | 236 | private $conditions = [ 237 | 'New', 238 | 'Refurbished', 239 | 'UsedLikeNew', 240 | 'UsedVeryGood', 241 | 'UsedGood', 242 | 'UsedAcceptable' 243 | ]; 244 | 245 | public function __construct(array $array = []) 246 | { 247 | foreach ($array as $property => $value) { 248 | $this->{$property} = $value; 249 | } 250 | } 251 | 252 | public function getValidationErrors() 253 | { 254 | return $this->validation_errors; 255 | } 256 | 257 | 258 | public function toArray($toEncoding = true) 259 | { 260 | /*'feed_product_type' => 'television',*/ 261 | return array_merge( 262 | $this->other_attributes, 263 | [ 264 | 'feed_product_type' => $this->feed_product_type, 265 | 'item_sku' => $this->sku, 266 | 'external_product_id' => $this->product_id, 267 | 'external_product_id_type' => $this->product_id_type, 268 | 'brand_name' => $this->brand, 269 | 'item_name' => $this->title, 270 | 'product_description' => $this->description, 271 | "manufacturer" => $this->manufacturer, 272 | 'standard_price' => $this->price, 273 | 'sale_price' => $this->sale_price, 274 | 'currency' => $this->currency, 275 | 'quantity' => $this->quantity, 276 | 'parent_child' => $this->parent_child, 277 | 'relationship_type' => $this->parent_child == 'Child' ? 'Variation' : '', 278 | 'parent_sku' => $this->parent_sku, 279 | 'variation_theme' => $this->variation_theme, 280 | 'generic_keywords' => $this->keywords, 281 | 'color_name' => $this->color_name, 282 | 'size_name' => $this->size_name, 283 | 'merchant_shipping_group_name' => $this->shipping, 284 | 'website_shipping_weight_unit_of_measure' => $this->weight, 285 | 'recommended_browse_nodes' => $this->recommended_browse_nodes, 286 | 'sale_from_date' => $this->sale_from_date, 287 | 'sale_end_date' => $this->sale_end_date, 288 | 'main_image_url' => array_key_exists(0, $this->image) ? $this->image[0] : '', 289 | 'other_image_url1' => array_key_exists(1, $this->image) ? $this->image[1] : '', 290 | 'other_image_url2' => array_key_exists(2, $this->image) ? $this->image[2] : '', 291 | 'other_image_url3' => array_key_exists(3, $this->image) ? $this->image[3] : '', 292 | 'other_image_url4' => array_key_exists(4, $this->image) ? $this->image[4] : '', 293 | 'other_image_url5' => array_key_exists(5, $this->image) ? $this->image[5] : '', 294 | 'other_image_url6' => array_key_exists(6, $this->image) ? $this->image[6] : '', 295 | 'other_image_url7' => array_key_exists(7, $this->image) ? $this->image[7] : '', 296 | 'other_image_url8' => array_key_exists(8, $this->image) ? $this->image[8] : '', 297 | 'bullet_point1' => array_key_exists(0, $this->bullet_point) ? $this->bullet_point[0] : '', 298 | 'bullet_point2' => array_key_exists(1, $this->bullet_point) ? $this->bullet_point[1] : '', 299 | 'bullet_point3' => array_key_exists(2, $this->bullet_point) ? $this->bullet_point[2] : '', 300 | 'bullet_point4' => array_key_exists(3, $this->bullet_point) ? $this->bullet_point[3] : '', 301 | 'bullet_point5' => array_key_exists(4, $this->bullet_point) ? $this->bullet_point[4] : '', 302 | ] 303 | ); 304 | } 305 | 306 | public function validate() 307 | { 308 | if (mb_strlen($this->sku) < 1 or strlen($this->sku) > 40) { 309 | $this->validation_errors['sku'] = 'Should be longer then 1 character and shorter then 40 characters'; 310 | } 311 | 312 | $this->price = str_replace(',', '.', $this->price); 313 | 314 | $exploded_price = explode('.', $this->price); 315 | 316 | if (count($exploded_price) == 2) { 317 | if (mb_strlen($exploded_price[0]) > 18) { 318 | $this->validation_errors['price'] = 'Too high'; 319 | } else { 320 | if (mb_strlen($exploded_price[1]) > 2) { 321 | $this->validation_errors['price'] = 'Too many decimals'; 322 | } 323 | } 324 | } else { 325 | $this->validation_errors['price'] = 'Looks wrong'; 326 | } 327 | 328 | $this->quantity = (int)$this->quantity; 329 | $this->product_id = (string)$this->product_id; 330 | 331 | $product_id_length = mb_strlen($this->product_id); 332 | 333 | switch ($this->product_id_type) { 334 | case 'ASIN': 335 | if ($product_id_length != 10) { 336 | $this->validation_errors['product_id'] = 'ASIN should be 10 characters long'; 337 | } 338 | break; 339 | case 'UPC': 340 | if ($product_id_length != 12) { 341 | $this->validation_errors['product_id'] = 'UPC should be 12 characters long'; 342 | } 343 | break; 344 | case 'EAN': 345 | if ($product_id_length != 13) { 346 | $this->validation_errors['product_id'] = 'EAN should be 13 characters long'; 347 | } 348 | break; 349 | default: 350 | $this->validation_errors['product_id_type'] = 'Not one of: ASIN,UPC,EAN'; 351 | } 352 | 353 | if (!in_array($this->condition_type, $this->conditions)) { 354 | $this->validation_errors['condition_type'] = 'Not one of: ' . implode($this->conditions, ','); 355 | } 356 | 357 | if ($this->condition_type != 'New') { 358 | $length = mb_strlen($this->condition_note); 359 | if ($length < 1) { 360 | $this->validation_errors['condition_note'] = 'Required if condition_type not is New'; 361 | } else { 362 | if ($length > 1000) { 363 | $this->validation_errors['condition_note'] = 'Should not exceed 1000 characters'; 364 | } 365 | } 366 | } 367 | 368 | if (count($this->validation_errors) > 0) { 369 | return false; 370 | } else { 371 | return true; 372 | } 373 | } 374 | 375 | public function __set($property, $value) 376 | { 377 | if (property_exists($this, $property)) { 378 | return $this->$property; 379 | } 380 | } 381 | 382 | /** 383 | * @param string $parent_sku 384 | * @return AmazonMarketPlaceProduct 385 | */ 386 | public function setParentSku(string $parent_sku) 387 | { 388 | $this->parent_sku = $parent_sku; 389 | return $this; 390 | } 391 | 392 | /** 393 | * @param string $variation_theme 394 | * @return AmazonMarketPlaceProduct 395 | */ 396 | public function setVariationTheme(string $variation_theme) 397 | { 398 | $this->variation_theme = $variation_theme; 399 | return $this; 400 | } 401 | 402 | /** 403 | * @param string $keywords 404 | * @return AmazonMarketPlaceProduct 405 | */ 406 | public function setKeywords(string $keywords) 407 | { 408 | $this->keywords = $keywords; 409 | return $this; 410 | } 411 | 412 | /** 413 | * @param array $bullet_point 414 | * @return AmazonMarketPlaceProduct 415 | */ 416 | public function setBulletPoint(array $bullet_point) 417 | { 418 | $this->bullet_point = $bullet_point; 419 | return $this; 420 | } 421 | 422 | /** 423 | * @param mixed $sale_price 424 | * @return AmazonMarketPlaceProduct 425 | */ 426 | public function setSalePrice($sale_price) 427 | { 428 | $this->sale_price = $sale_price; 429 | return $this; 430 | } 431 | 432 | /** 433 | * @param string $currency 434 | * @return AmazonMarketPlaceProduct 435 | */ 436 | public function setCurrency(string $currency) 437 | { 438 | $this->currency = $currency; 439 | return $this; 440 | } 441 | 442 | /** 443 | * @param string $color_name 444 | * @return AmazonMarketPlaceProduct 445 | */ 446 | public function setColorName(string $color_name) 447 | { 448 | $this->color_name = $color_name; 449 | return $this; 450 | } 451 | 452 | /** 453 | * @param string $size_name 454 | * @return AmazonMarketPlaceProduct 455 | */ 456 | public function setSizeName(string $size_name) 457 | { 458 | $this->size_name = $size_name; 459 | return $this; 460 | } 461 | 462 | /** 463 | * @param string $manufacturer 464 | * @return AmazonMarketPlaceProduct 465 | */ 466 | public function setManufacturer(string $manufacturer) 467 | { 468 | $this->manufacturer = $manufacturer; 469 | return $this; 470 | } 471 | 472 | /** 473 | * @param string $sale_from_date 474 | * @return AmazonMarketPlaceProduct 475 | */ 476 | public function setSaleFromDate($sale_from_date) 477 | { 478 | $this->sale_from_date = $sale_from_date; 479 | return $this; 480 | } 481 | 482 | /** 483 | * @param string $sale_end_date 484 | * @return AmazonMarketPlaceProduct 485 | */ 486 | public function setSaleEndDate($sale_end_date) 487 | { 488 | $this->sale_end_date = $sale_end_date; 489 | return $this; 490 | } 491 | 492 | /** 493 | * @param array $other_attributes 494 | * @return AmazonMarketPlaceProduct 495 | */ 496 | public function setOtherAttributes(array $other_attributes) 497 | { 498 | $this->other_attributes = $other_attributes; 499 | return $this; 500 | } 501 | 502 | /** 503 | * @param string $parent_child 504 | * @return AmazonMarketPlaceProduct 505 | */ 506 | public function setParentChild($parent_child) 507 | { 508 | $this->parent_child = $parent_child; 509 | return $this; 510 | } 511 | } 512 | -------------------------------------------------------------------------------- /src/MWSClient.php: -------------------------------------------------------------------------------- 1 | null, 22 | 'Marketplace_Id' => null, 23 | 'Access_Key_ID' => null, 24 | 'Secret_Access_Key' => null, 25 | 'MWSAuthToken' => null, 26 | 'Application_Version' => '0.0.*' 27 | ]; 28 | protected $MarketplaceIds = [ 29 | 'A2EUQ1WTGCTBG2' => 'mws.amazonservices.ca', 30 | 'ATVPDKIKX0DER' => 'mws.amazonservices.com', 31 | 'A1AM78C64UM0Y8' => 'mws.amazonservices.com.mx', 32 | 'A1PA6795UKMFR9' => 'mws-eu.amazonservices.com', 33 | 'A1RKKUPIHCS9HS' => 'mws-eu.amazonservices.com', 34 | 'A13V1IB3VIYZZH' => 'mws-eu.amazonservices.com', 35 | 'A21TJRUUN4KGV' => 'mws.amazonservices.in', 36 | 'APJ6JRA9NG5V4' => 'mws-eu.amazonservices.com', 37 | 'A1F83G8C2ARO7P' => 'mws-eu.amazonservices.com', 38 | 'A1VC38T7YXB528' => 'mws.amazonservices.jp', 39 | 'AAHKV2X7AFYLW' => 'mws.amazonservices.com.cn', 40 | 'A39IBJ37TRP1C6' => 'mws.amazonservices.com.au', 41 | 'A2Q3Y263D00KWC' => 'mws.amazonservices.com', 42 | 'A1805IZSGTT6HS' => 'mws-eu.amazonservices.com', 43 | 'ARBP9OOSHTCHU' => 'mws-eu.amazonservices.com', 44 | 'A17E79C6D8DWNP' => 'mws.amazonservices.com', 45 | 'A33AVAJ2PDY3EV' => 'mws.amazonservices.com', 46 | 'A19VAU5U5O7RUS' => 'mws-fe.amazonservices.com', 47 | 'A2VIGQ35RCS4UG' => 'mws.amazonservices.ae', 48 | 'A2NODRKZP88ZB9' => 'mws-eu.amazonservices.com' 49 | ]; 50 | protected $debugNextFeed = false; 51 | protected $client = null; 52 | 53 | public function __construct(array $config) 54 | { 55 | foreach ($config as $key => $value) { 56 | if (array_key_exists($key, $this->config)) { 57 | $this->config[$key] = $value; 58 | } 59 | } 60 | $required_keys = [ 61 | 'Marketplace_Id', 62 | 'Seller_Id', 63 | 'Access_Key_ID', 64 | 'Secret_Access_Key' 65 | ]; 66 | foreach ($required_keys as $key) { 67 | if (is_null($this->config[$key])) { 68 | throw new Exception('Required field ' . $key . ' is not set'); 69 | } 70 | } 71 | if (!isset($this->MarketplaceIds[$this->config['Marketplace_Id']])) { 72 | throw new Exception('Invalid Marketplace Id'); 73 | } 74 | $this->config['Application_Name'] = self::APPLICATION_NAME; 75 | $this->config['Region_Host'] = $this->MarketplaceIds[$this->config['Marketplace_Id']]; 76 | $this->config['Region_Url'] = 'https://' . $this->config['Region_Host']; 77 | } 78 | 79 | /** 80 | * Call this method to get the raw feed instead of sending it 81 | */ 82 | public function debugNextFeed() 83 | { 84 | $this->debugNextFeed = true; 85 | } 86 | 87 | /** 88 | * A method to quickly check if the supplied credentials are valid 89 | * @return boolean 90 | * @throws \GuzzleHttp\Exception\GuzzleException 91 | */ 92 | public function validateCredentials() 93 | { 94 | try { 95 | $this->ListOrderItems('validate'); 96 | } catch(Exception $e) { 97 | $validResponseSearchs = [ 98 | 'invalid', 99 | 'not valid', 100 | ]; 101 | foreach ($validResponseSearchs as $responseSearch) { 102 | if (strpos(strtolower($e->getMessage()), $responseSearch) !== false) { 103 | return true; 104 | } 105 | } 106 | return false; 107 | } 108 | } 109 | 110 | /** 111 | * Returns the current competitive price of a product, based on ASIN. 112 | * @param array [$asin_array = []] 113 | * @return array 114 | * @throws Exception 115 | * @throws \GuzzleHttp\Exception\GuzzleException 116 | */ 117 | public function GetCompetitivePricingForASIN($asin_array = []) 118 | { 119 | if (count($asin_array) > 20) { 120 | throw new Exception('Maximum amount of ASIN\'s for this call is 20'); 121 | } 122 | $counter = 1; 123 | $query = [ 124 | 'MarketplaceId' => $this->config['Marketplace_Id'] 125 | ]; 126 | foreach ($asin_array as $key) { 127 | $query['ASINList.ASIN.' . $counter] = $key; 128 | $counter++; 129 | } 130 | $response = $this->request( 131 | 'GetCompetitivePricingForASIN', 132 | $query 133 | ); 134 | if (isset($response['GetCompetitivePricingForASINResult'])) { 135 | $response = $response['GetCompetitivePricingForASINResult']; 136 | if (array_keys($response) !== range(0, count($response) - 1)) { 137 | $response = [$response]; 138 | } 139 | } else { 140 | return []; 141 | } 142 | $array = []; 143 | foreach ($response as $product) { 144 | if (isset($product['Product']['CompetitivePricing']['CompetitivePrices']['CompetitivePrice']['Price'])) { 145 | $array[$product['Product']['Identifiers']['MarketplaceASIN']['ASIN']] = $product['Product']['CompetitivePricing']['CompetitivePrices']['CompetitivePrice']['Price']; 146 | } 147 | } 148 | return $array; 149 | } 150 | 151 | /** 152 | * Returns the current competitive price of a product, based on SKU. 153 | * @param array [$sku_array = []] 154 | * @return array 155 | * @throws Exception 156 | * @throws \GuzzleHttp\Exception\GuzzleException 157 | */ 158 | public function GetCompetitivePricingForSKU($sku_array = []) 159 | { 160 | if (count($sku_array) > 20) { 161 | throw new Exception('Maximum amount of SKU\'s for this call is 20'); 162 | } 163 | $counter = 1; 164 | $query = [ 165 | 'MarketplaceId' => $this->config['Marketplace_Id'] 166 | ]; 167 | foreach ($sku_array as $key) { 168 | $query['SellerSKUList.SellerSKU.' . $counter] = $key; 169 | $counter++; 170 | } 171 | $response = $this->request( 172 | 'GetCompetitivePricingForSKU', 173 | $query 174 | ); 175 | if (isset($response['GetCompetitivePricingForSKUResult'])) { 176 | $response = $response['GetCompetitivePricingForSKUResult']; 177 | if (array_keys($response) !== range(0, count($response) - 1)) { 178 | $response = [$response]; 179 | } 180 | } else { 181 | return []; 182 | } 183 | $array = []; 184 | foreach ($response as $product) { 185 | if (isset($product['Product']['CompetitivePricing']['CompetitivePrices']['CompetitivePrice']['Price'])) { 186 | $array[$product['Product']['Identifiers']['SKUIdentifier']['SellerSKU']]['Price'] = $product['Product']['CompetitivePricing']['CompetitivePrices']['CompetitivePrice']['Price']; 187 | $array[$product['Product']['Identifiers']['SKUIdentifier']['SellerSKU']]['Rank'] = $product['Product']['SalesRankings']['SalesRank'][1]; 188 | } 189 | } 190 | return $array; 191 | } 192 | 193 | /** 194 | * Returns lowest priced offers for a single product, based on ASIN. 195 | * @param string $asin 196 | * @param string [$ItemCondition = 'New'] Should be one in: New, Used, Collectible, Refurbished, Club 197 | * @return array 198 | * @throws Exception 199 | * @throws \GuzzleHttp\Exception\GuzzleException 200 | */ 201 | public function GetLowestPricedOffersForASIN($asin, $ItemCondition = 'New') 202 | { 203 | $query = [ 204 | 'ASIN' => $asin, 205 | 'MarketplaceId' => $this->config['Marketplace_Id'], 206 | 'ItemCondition' => $ItemCondition 207 | ]; 208 | return $this->request('GetLowestPricedOffersForASIN', $query); 209 | } 210 | 211 | /** 212 | * Returns pricing information for your own offer listings, based on SKU. 213 | * @param array [$sku_array = []] 214 | * @param string [$ItemCondition = null] 215 | * @return array 216 | * @throws Exception 217 | * @throws \GuzzleHttp\Exception\GuzzleException 218 | */ 219 | public function GetMyPriceForSKU($sku_array = [], $ItemCondition = null) 220 | { 221 | if (count($sku_array) > 20) { 222 | throw new Exception('Maximum amount of SKU\'s for this call is 20'); 223 | } 224 | $counter = 1; 225 | $query = [ 226 | 'MarketplaceId' => $this->config['Marketplace_Id'] 227 | ]; 228 | if (!is_null($ItemCondition)) { 229 | $query['ItemCondition'] = $ItemCondition; 230 | } 231 | foreach ($sku_array as $key) { 232 | $query['SellerSKUList.SellerSKU.' . $counter] = $key; 233 | $counter++; 234 | } 235 | $response = $this->request( 236 | 'GetMyPriceForSKU', 237 | $query 238 | ); 239 | if (isset($response['GetMyPriceForSKUResult'])) { 240 | $response = $response['GetMyPriceForSKUResult']; 241 | if (array_keys($response) !== range(0, count($response) - 1)) { 242 | $response = [$response]; 243 | } 244 | } else { 245 | return []; 246 | } 247 | $array = []; 248 | foreach ($response as $product) { 249 | if (isset($product['@attributes']['status']) && $product['@attributes']['status'] == 'Success') { 250 | if (isset($product['Product']['Offers']['Offer'])) { 251 | $array[$product['@attributes']['SellerSKU']] = $product['Product']['Offers']['Offer']; 252 | } else { 253 | $array[$product['@attributes']['SellerSKU']] = []; 254 | } 255 | } else { 256 | $array[$product['@attributes']['SellerSKU']] = false; 257 | } 258 | } 259 | return $array; 260 | } 261 | 262 | /** 263 | * Returns pricing information for your own offer listings, based on ASIN. 264 | * @param array [$asin_array = []] 265 | * @param string [$ItemCondition = null] 266 | * @return array 267 | * @throws Exception 268 | * @throws \GuzzleHttp\Exception\GuzzleException 269 | */ 270 | public function GetMyPriceForASIN($asin_array = [], $ItemCondition = null) 271 | { 272 | if (count($asin_array) > 20) { 273 | throw new Exception('Maximum amount of SKU\'s for this call is 20'); 274 | } 275 | $counter = 1; 276 | $query = [ 277 | 'MarketplaceId' => $this->config['Marketplace_Id'] 278 | ]; 279 | if (!is_null($ItemCondition)) { 280 | $query['ItemCondition'] = $ItemCondition; 281 | } 282 | foreach ($asin_array as $key) { 283 | $query['ASINList.ASIN.' . $counter] = $key; 284 | $counter++; 285 | } 286 | $response = $this->request( 287 | 'GetMyPriceForASIN', 288 | $query 289 | ); 290 | if (isset($response['GetMyPriceForASINResult'])) { 291 | $response = $response['GetMyPriceForASINResult']; 292 | if (array_keys($response) !== range(0, count($response) - 1)) { 293 | $response = [$response]; 294 | } 295 | } else { 296 | return []; 297 | } 298 | $array = []; 299 | foreach ($response as $product) { 300 | if (isset($product['@attributes']['status']) && $product['@attributes']['status'] == 'Success' && isset($product['Product']['Offers']['Offer'])) { 301 | $array[$product['@attributes']['ASIN']] = $product['Product']['Offers']['Offer']; 302 | } else { 303 | $array[$product['@attributes']['ASIN']] = false; 304 | } 305 | } 306 | return $array; 307 | } 308 | 309 | /** 310 | * Returns pricing information for the lowest-price active offer listings for up to 20 products, based on ASIN. 311 | * @param array [$asin_array = []] array of ASIN values 312 | * @param array [$ItemCondition = null] Should be one in: New, Used, Collectible, Refurbished, Club. Default: All 313 | * @return array 314 | * @throws Exception 315 | * @throws \GuzzleHttp\Exception\GuzzleException 316 | */ 317 | public function GetLowestOfferListingsForASIN($asin_array = [], $ItemCondition = null) 318 | { 319 | if (count($asin_array) > 20) { 320 | throw new Exception('Maximum amount of ASIN\'s for this call is 20'); 321 | } 322 | $counter = 1; 323 | $query = [ 324 | 'MarketplaceId' => $this->config['Marketplace_Id'] 325 | ]; 326 | if (!is_null($ItemCondition)) { 327 | $query['ItemCondition'] = $ItemCondition; 328 | } 329 | foreach ($asin_array as $key) { 330 | $query['ASINList.ASIN.' . $counter] = $key; 331 | $counter++; 332 | } 333 | $response = $this->request( 334 | 'GetLowestOfferListingsForASIN', 335 | $query 336 | ); 337 | if (isset($response['GetLowestOfferListingsForASINResult'])) { 338 | $response = $response['GetLowestOfferListingsForASINResult']; 339 | if (array_keys($response) !== range(0, count($response) - 1)) { 340 | $response = [$response]; 341 | } 342 | } else { 343 | return []; 344 | } 345 | $array = []; 346 | foreach ($response as $product) { 347 | if (isset($product['Product']['LowestOfferListings']['LowestOfferListing'])) { 348 | $array[$product['Product']['Identifiers']['MarketplaceASIN']['ASIN']] = $product['Product']['LowestOfferListings']['LowestOfferListing']; 349 | } else { 350 | $array[$product['Product']['Identifiers']['MarketplaceASIN']['ASIN']] = false; 351 | } 352 | } 353 | return $array; 354 | } 355 | 356 | /** 357 | * Returns orders created or updated during a time frame that you specify. 358 | * @param object DateTime $from, beginning of time frame 359 | * @param boolean $allMarketplaces, list orders from all marketplaces 360 | * @param array $states, an array containing orders states you want to filter on 361 | * @param string $FulfillmentChannel 362 | * @param object DateTime $till, end of time frame 363 | * @param $updatedFrom, Use from date is CreatedAfter or LastUpdatedAfter 364 | * @return array 365 | * @throws Exception 366 | * @throws \GuzzleHttp\Exception\GuzzleException 367 | */ 368 | public function ListOrders(DateTime $from, $allMarketplaces = false, $states = [ 369 | 'Unshipped', 'PartiallyShipped' 370 | ], $FulfillmentChannels = 'MFN', DateTime $till = null, $fromUpdated = false) 371 | { 372 | if ($fromUpdated) { 373 | $query = [ 374 | 'LastUpdatedAfter' => gmdate(self::DATE_FORMAT, $from->getTimestamp()) 375 | ]; 376 | } else { 377 | $query = [ 378 | 'CreatedAfter' => gmdate(self::DATE_FORMAT, $from->getTimestamp()) 379 | ]; 380 | } 381 | if ($till !== null) { 382 | $query['CreatedBefore'] = gmdate(self::DATE_FORMAT, $till->getTimestamp()); 383 | } 384 | $counter = 1; 385 | foreach ($states as $status) { 386 | $query['OrderStatus.Status.' . $counter] = $status; 387 | $counter = $counter + 1; 388 | } 389 | if ($allMarketplaces == true) { 390 | $counter = 1; 391 | foreach ($this->MarketplaceIds as $key => $value) { 392 | $query['MarketplaceId.Id.' . $counter] = $key; 393 | $counter = $counter + 1; 394 | } 395 | } 396 | if (is_array($FulfillmentChannels)) { 397 | $counter = 1; 398 | foreach ($FulfillmentChannels as $fulfillmentChannel) { 399 | $query['FulfillmentChannel.Channel.' . $counter] = $fulfillmentChannel; 400 | $counter = $counter + 1; 401 | } 402 | } else { 403 | $query['FulfillmentChannel.Channel.1'] = $FulfillmentChannels; 404 | } 405 | $response = $this->request('ListOrders', $query); 406 | if (isset($response['ListOrdersResult']['Orders']['Order'])) { 407 | if (isset($response['ListOrdersResult']['NextToken'])) { 408 | $data['ListOrders'] = $response['ListOrdersResult']['Orders']['Order']; 409 | $data['NextToken'] = $response['ListOrdersResult']['NextToken']; 410 | return $data; 411 | } 412 | 413 | $response = $response['ListOrdersResult']['Orders']['Order']; 414 | 415 | if (array_keys($response) !== range(0, count($response) - 1)) { 416 | return [$response]; 417 | } 418 | 419 | return $response; 420 | 421 | } else { 422 | return []; 423 | } 424 | } 425 | 426 | /** 427 | * Returns orders created or updated during a time frame that you specify. 428 | * @param string $nextToken 429 | * @return array 430 | * @throws Exception 431 | * @throws \GuzzleHttp\Exception\GuzzleException 432 | */ 433 | public function ListOrdersByNextToken($nextToken) 434 | { 435 | $query = [ 436 | 'NextToken' => $nextToken, 437 | ]; 438 | $response = $this->request( 439 | 'ListOrdersByNextToken', 440 | $query 441 | ); 442 | if (isset($response['ListOrdersByNextTokenResult']['Orders']['Order'])) { 443 | if (isset($response['ListOrdersByNextTokenResult']['NextToken'])) { 444 | $data['ListOrders'] = $response['ListOrdersByNextTokenResult']['Orders']['Order']; 445 | $data['NextToken'] = $response['ListOrdersByNextTokenResult']['NextToken']; 446 | return $data; 447 | } 448 | $response = $response['ListOrdersByNextTokenResult']['Orders']['Order']; 449 | if (array_keys($response) !== range(0, count($response) - 1)) { 450 | return [$response]; 451 | } 452 | return $response; 453 | } else { 454 | return []; 455 | } 456 | } 457 | 458 | /** 459 | * Returns an order based on the AmazonOrderId values that you specify. 460 | * @param string $AmazonOrderId 461 | * @return bool if the order is found, false if not 462 | * @throws Exception 463 | * @throws \GuzzleHttp\Exception\GuzzleException 464 | */ 465 | public function GetOrder($AmazonOrderId) 466 | { 467 | $response = $this->request('GetOrder', [ 468 | 'AmazonOrderId.Id.1' => $AmazonOrderId 469 | ]); 470 | if (isset($response['GetOrderResult']['Orders']['Order'])) { 471 | return $response['GetOrderResult']['Orders']['Order']; 472 | } else { 473 | return false; 474 | } 475 | } 476 | 477 | /** 478 | * Returns order items based on the AmazonOrderId that you specify. 479 | * @param string $AmazonOrderId 480 | * @return array 481 | * @throws Exception 482 | * @throws \GuzzleHttp\Exception\GuzzleException 483 | */ 484 | public function ListOrderItems($AmazonOrderId) 485 | { 486 | $response = $this->request('ListOrderItems', [ 487 | 'AmazonOrderId' => $AmazonOrderId 488 | ]); 489 | $result = array_values($response['ListOrderItemsResult']['OrderItems']); 490 | if (isset($result[0]['QuantityOrdered'])) { 491 | return $result; 492 | } else { 493 | return $result[0]; 494 | } 495 | } 496 | 497 | /** 498 | * Returns the parent product categories that a product belongs to, based on SellerSKU. 499 | * @param string $SellerSKU 500 | * @return bool if found, false if not found 501 | * @throws Exception 502 | * @throws \GuzzleHttp\Exception\GuzzleException 503 | */ 504 | public function GetProductCategoriesForSKU($SellerSKU) 505 | { 506 | $result = $this->request('GetProductCategoriesForSKU', [ 507 | 'MarketplaceId' => $this->config['Marketplace_Id'], 508 | 'SellerSKU' => $SellerSKU 509 | ]); 510 | if (isset($result['GetProductCategoriesForSKUResult']['Self'])) { 511 | return $result['GetProductCategoriesForSKUResult']['Self']; 512 | } else { 513 | return false; 514 | } 515 | } 516 | 517 | /** 518 | * Returns the parent product categories that a product belongs to, based on ASIN. 519 | * @param string $ASIN 520 | * @return bool if found, false if not found 521 | * @throws Exception 522 | * @throws \GuzzleHttp\Exception\GuzzleException 523 | */ 524 | public function GetProductCategoriesForASIN($ASIN) 525 | { 526 | $result = $this->request('GetProductCategoriesForASIN', [ 527 | 'MarketplaceId' => $this->config['Marketplace_Id'], 528 | 'ASIN' => $ASIN 529 | ]); 530 | if (isset($result['GetProductCategoriesForASINResult']['Self'])) { 531 | return $result['GetProductCategoriesForASINResult']['Self']; 532 | } else { 533 | return false; 534 | } 535 | } 536 | 537 | /** 538 | * Returns a list of products and their attributes, based on a list of ASIN, GCID, SellerSKU, UPC, EAN, ISBN, and JAN values. 539 | * @param array $asin_array A list of id's 540 | * @param string [$type = 'ASIN'] the identifier name 541 | * @return array 542 | * @throws Exception 543 | * @throws \GuzzleHttp\Exception\GuzzleException 544 | */ 545 | public function GetMatchingProductForId(array $asin_array, $type = 'ASIN') 546 | { 547 | $asin_array = array_unique($asin_array); 548 | if (count($asin_array) > 5) { 549 | throw new Exception('Maximum number of id\'s = 5'); 550 | } 551 | $counter = 1; 552 | $array = [ 553 | 'MarketplaceId' => $this->config['Marketplace_Id'], 554 | 'IdType' => $type 555 | ]; 556 | foreach ($asin_array as $asin) { 557 | $array['IdList.Id.' . $counter] = $asin; 558 | $counter++; 559 | } 560 | $response = $this->request( 561 | 'GetMatchingProductForId', 562 | $array, 563 | null, 564 | true 565 | ); 566 | $languages = [ 567 | 'de-DE', 568 | 'en-EN', 569 | 'es-ES', 570 | 'fr-FR', 571 | 'it-IT', 572 | 'en-US' 573 | ]; 574 | $replace = [ 575 | '' => '' 576 | ]; 577 | foreach ($languages as $language) { 578 | $replace[''] = '' . $language . ''; 579 | } 580 | $replace['ns2:'] = ''; 581 | $response = $this->xmlToArray(strtr($response, $replace)); 582 | if (isset($response['GetMatchingProductForIdResult']['@attributes'])) { 583 | $response['GetMatchingProductForIdResult'] = [ 584 | 0 => $response['GetMatchingProductForIdResult'] 585 | ]; 586 | } 587 | $found = []; 588 | $not_found = []; 589 | if (isset($response['GetMatchingProductForIdResult']) && is_array($response['GetMatchingProductForIdResult'])) { 590 | foreach ($response['GetMatchingProductForIdResult'] as $result) { 591 | //print_r($product);exit; 592 | $asin = $result['@attributes']['Id']; 593 | if ($result['@attributes']['status'] != 'Success') { 594 | $not_found[] = $asin; 595 | } else { 596 | if (isset($result['Products']['Product']['AttributeSets'])) { 597 | $products[0] = $result['Products']['Product']; 598 | } else { 599 | $products = $result['Products']['Product']; 600 | } 601 | foreach ($products as $product) { 602 | $array = []; 603 | if (isset($product['Identifiers']['MarketplaceASIN']['ASIN'])) { 604 | $array["ASIN"] = $product['Identifiers']['MarketplaceASIN']['ASIN']; 605 | } 606 | foreach ($product['AttributeSets']['ItemAttributes'] as $key => $value) { 607 | if (is_string($key) && is_string($value)) { 608 | $array[$key] = $value; 609 | } 610 | } 611 | if (isset($product['AttributeSets']['ItemAttributes']['Feature'])) { 612 | $array['Feature'] = $product['AttributeSets']['ItemAttributes']['Feature']; 613 | } 614 | if (isset($product['AttributeSets']['ItemAttributes']['PackageDimensions'])) { 615 | $array['PackageDimensions'] = array_map( 616 | 'floatval', 617 | $product['AttributeSets']['ItemAttributes']['PackageDimensions'] 618 | ); 619 | } 620 | if (isset($product['AttributeSets']['ItemAttributes']['ListPrice'])) { 621 | $array['ListPrice'] = $product['AttributeSets']['ItemAttributes']['ListPrice']; 622 | } 623 | if (isset($product['AttributeSets']['ItemAttributes']['SmallImage'])) { 624 | $image = $product['AttributeSets']['ItemAttributes']['SmallImage']['URL']; 625 | $array['medium_image'] = $image; 626 | $array['small_image'] = str_replace('._SL75_', '._SL50_', $image); 627 | $array['large_image'] = str_replace('._SL75_', '', $image);; 628 | } 629 | if (isset($product['Relationships']['VariationParent']['Identifiers']['MarketplaceASIN']['ASIN'])) { 630 | $array['Parentage'] = 'child'; 631 | $array['Relationships'] = $product['Relationships']['VariationParent']['Identifiers']['MarketplaceASIN']['ASIN']; 632 | } 633 | if (isset($product['Relationships']['VariationChild'])) { 634 | $array['Parentage'] = 'parent'; 635 | } 636 | if (isset($product['SalesRankings']['SalesRank'])) { 637 | $array['SalesRank'] = $product['SalesRankings']['SalesRank']; 638 | } 639 | $found[$asin][] = $array; 640 | } 641 | } 642 | } 643 | } 644 | return [ 645 | 'found' => $found, 646 | 'not_found' => $not_found 647 | ]; 648 | } 649 | 650 | /** 651 | * Returns a list of products and their attributes, ordered by relevancy, based on a search query that you specify. 652 | * @param string $query the open text query 653 | * @param string [$query_context_id = null] the identifier for the context within which the given search will be performed. see: http://docs.developer.amazonservices.com/en_US/products/Products_QueryContextIDs.html 654 | * @return array 655 | * @throws Exception 656 | * @throws \GuzzleHttp\Exception\GuzzleException 657 | */ 658 | public function ListMatchingProducts($query, $query_context_id = null) 659 | { 660 | if (trim($query) == "") { 661 | throw new Exception('Missing query'); 662 | } 663 | $array = [ 664 | 'MarketplaceId' => $this->config['Marketplace_Id'], 665 | 'Query' => urlencode($query), 666 | 'QueryContextId' => $query_context_id 667 | ]; 668 | $response = $this->request( 669 | 'ListMatchingProducts', 670 | $array, 671 | null, 672 | true 673 | ); 674 | $languages = [ 675 | 'de-DE', 676 | 'en-EN', 677 | 'es-ES', 678 | 'fr-FR', 679 | 'it-IT', 680 | 'en-US' 681 | ]; 682 | $replace = [ 683 | '' => '' 684 | ]; 685 | foreach ($languages as $language) { 686 | $replace[''] = '' . $language . ''; 687 | } 688 | $replace['ns2:'] = ''; 689 | $response = $this->xmlToArray(strtr($response, $replace)); 690 | if (isset($response['ListMatchingProductsResult'])) { 691 | return $response['ListMatchingProductsResult']; 692 | } else { 693 | return ['ListMatchingProductsResult' => []]; 694 | } 695 | } 696 | 697 | /** 698 | * Returns a list of reports that were created in the previous 90 days. 699 | * @param array [$ReportTypeList = []] 700 | * @return array 701 | * @throws Exception 702 | * @throws \GuzzleHttp\Exception\GuzzleException 703 | */ 704 | public function GetReportList($ReportTypeList = []) 705 | { 706 | $array = []; 707 | $counter = 1; 708 | if (count($ReportTypeList)) { 709 | foreach ($ReportTypeList as $ReportType) { 710 | $array['ReportTypeList.Type.' . $counter] = $ReportType; 711 | $counter++; 712 | } 713 | } 714 | return $this->request('GetReportList', $array); 715 | } 716 | 717 | /** 718 | * Returns your active recommendations for a specific category or for all categories for a specific marketplace. 719 | * @param string [$RecommendationCategory = null] One of: Inventory, Selection, Pricing, Fulfillment, ListingQuality, GlobalSelling, Advertising 720 | * @return array/false if no result 721 | * @throws Exception 722 | * @throws \GuzzleHttp\Exception\GuzzleException 723 | */ 724 | public function ListRecommendations($RecommendationCategory = null) 725 | { 726 | $query = [ 727 | 'MarketplaceId' => $this->config['Marketplace_Id'] 728 | ]; 729 | if (!is_null($RecommendationCategory)) { 730 | $query['RecommendationCategory'] = $RecommendationCategory; 731 | } 732 | $result = $this->request('ListRecommendations', $query); 733 | if (isset($result['ListRecommendationsResult'])) { 734 | return $result['ListRecommendationsResult']; 735 | } else { 736 | return false; 737 | } 738 | } 739 | 740 | /** 741 | * Returns a list of marketplaces that the seller submitting the request can sell in, and a list of participations that include seller-specific information in that marketplace 742 | * @return array 743 | * @throws Exception 744 | * @throws \GuzzleHttp\Exception\GuzzleException 745 | */ 746 | public function ListMarketplaceParticipations() 747 | { 748 | $result = $this->request('ListMarketplaceParticipations'); 749 | if (isset($result['ListMarketplaceParticipationsResult'])) { 750 | return $result['ListMarketplaceParticipationsResult']; 751 | } else { 752 | return $result; 753 | } 754 | } 755 | 756 | /** 757 | * Delete product's based on SKU 758 | * @param array $array array containing sku's 759 | * @return array feed submission result 760 | * @throws Exception 761 | * @throws \GuzzleHttp\Exception\GuzzleException 762 | */ 763 | public function deleteProductBySKU(array $array) 764 | { 765 | $feed = [ 766 | 'MessageType' => 'Product', 767 | 'Message' => [] 768 | ]; 769 | foreach ($array as $sku) { 770 | $feed['Message'][] = [ 771 | 'MessageID' => rand(), 772 | 'OperationType' => 'Delete', 773 | 'Product' => [ 774 | 'SKU' => $sku 775 | ] 776 | ]; 777 | } 778 | return $this->SubmitFeed('_POST_PRODUCT_DATA_', $feed); 779 | } 780 | 781 | /** 782 | * Update a product's stock quantity 783 | * @param array $array array containing sku as key and quantity as value 784 | * @return array feed submission result 785 | * @throws Exception 786 | * @throws \GuzzleHttp\Exception\GuzzleException 787 | */ 788 | public function updateStock(array $array) 789 | { 790 | $feed = [ 791 | 'MessageType' => 'Inventory', 792 | 'Message' => [] 793 | ]; 794 | foreach ($array as $sku => $quantity) { 795 | $feed['Message'][] = [ 796 | 'MessageID' => rand(), 797 | 'OperationType' => 'Update', 798 | 'Inventory' => [ 799 | 'SKU' => $sku, 800 | 'Quantity' => (int)$quantity 801 | ] 802 | ]; 803 | } 804 | return $this->SubmitFeed('_POST_INVENTORY_AVAILABILITY_DATA_', $feed); 805 | } 806 | 807 | /** 808 | * Update a product's stock quantity 809 | * 810 | * @param array $array array containing arrays with next keys: [sku, quantity, latency] 811 | * @return array feed submission result 812 | * @throws Exception 813 | * @throws \GuzzleHttp\Exception\GuzzleException 814 | */ 815 | public function updateStockWithFulfillmentLatency(array $array) 816 | { 817 | $feed = [ 818 | 'MessageType' => 'Inventory', 819 | 'Message' => [] 820 | ]; 821 | foreach ($array as $item) { 822 | $feed['Message'][] = [ 823 | 'MessageID' => rand(), 824 | 'OperationType' => 'Update', 825 | 'Inventory' => [ 826 | 'SKU' => $item['sku'], 827 | 'Quantity' => (int)$item['quantity'], 828 | 'FulfillmentLatency' => $item['latency'] 829 | ] 830 | ]; 831 | } 832 | return $this->SubmitFeed('_POST_INVENTORY_AVAILABILITY_DATA_', $feed); 833 | } 834 | 835 | /** 836 | * Update a product's price 837 | * @param array $standardprice an array containing sku as key and price as value 838 | * @param array|null $saleprice 839 | * @return array feed submission result 840 | * @throws Exception 841 | * @throws \GuzzleHttp\Exception\GuzzleException 842 | */ 843 | public function updatePrice(array $standardprice, array $saleprice = null) 844 | { 845 | $feed = [ 846 | 'MessageType' => 'Price', 847 | 'Message' => [] 848 | ]; 849 | foreach ($standardprice as $sku => $price) { 850 | $feed['Message'][] = [ 851 | 'MessageID' => rand(), 852 | 'Price' => [ 853 | 'SKU' => $sku, 854 | 'StandardPrice' => [ 855 | '_value' => strval($price), 856 | '_attributes' => [ 857 | 'currency' => 'DEFAULT' 858 | ] 859 | ] 860 | ] 861 | ]; 862 | if (isset($saleprice[$sku]) && is_array($saleprice[$sku])) { 863 | $feed['Message'][count($feed['Message']) - 1]['Price']['Sale'] = [ 864 | 'StartDate' => $saleprice[$sku]['StartDate']->format(self::DATE_FORMAT), 865 | 'EndDate' => $saleprice[$sku]['EndDate']->format(self::DATE_FORMAT), 866 | 'SalePrice' => [ 867 | '_value' => strval($saleprice[$sku]['SalePrice']), 868 | '_attributes' => [ 869 | 'currency' => 'DEFAULT' 870 | ] 871 | ] 872 | ]; 873 | } 874 | } 875 | return $this->SubmitFeed('_POST_PRODUCT_PRICING_DATA_', $feed); 876 | } 877 | 878 | 879 | /** 880 | * Returns the feed processing report and the Content-MD5 header. 881 | * @param string $FeedSubmissionId 882 | * @return array 883 | * @throws Exception 884 | * @throws \GuzzleHttp\Exception\GuzzleException 885 | */ 886 | public function GetFeedSubmissionResult($FeedSubmissionId) 887 | { 888 | $result = $this->request('GetFeedSubmissionResult', [ 889 | 'FeedSubmissionId' => $FeedSubmissionId 890 | ]); 891 | 892 | if (isset($result['Message']['ProcessingReport'])) { 893 | return $result['Message']['ProcessingReport']; 894 | } else { 895 | return $result; 896 | } 897 | } 898 | /** 899 | * Returns a list of all feed submissions submitted in the previous 90 days. 900 | * @return array 901 | */ 902 | public function GetFeedSubmissionList() 903 | { 904 | $result = $this->request('GetFeedSubmissionList'); 905 | 906 | if (isset($result['Message']['ProcessingReport'])) { 907 | return $result['Message']['ProcessingReport']; 908 | } else { 909 | return $result; 910 | } 911 | } 912 | 913 | /** 914 | * Uploads a feed for processing by Amazon MWS. 915 | * @param string $FeedType (http://docs.developer.amazonservices.com/en_US/feeds/Feeds_FeedType.html) 916 | * @param mixed $feedContent Array will be converted to xml using https://github.com/spatie/array-to-xml. Strings will not be modified. 917 | * @param boolean $debug Return the generated xml and don't send it to amazon 918 | * @param array $options 919 | * @return array 920 | * @throws \GuzzleHttp\Exception\GuzzleException 921 | */ 922 | public function SubmitFeed($FeedType, $feedContent, $debug = false, $options = []) 923 | { 924 | if (is_array($feedContent)) { 925 | $feedContent = $this->arrayToXml( 926 | array_merge([ 927 | 'Header' => [ 928 | 'DocumentVersion' => 1.01, 929 | 'MerchantIdentifier' => $this->config['Seller_Id'] 930 | ] 931 | ], $feedContent) 932 | ); 933 | } 934 | 935 | if ($debug === true) { 936 | return $feedContent; 937 | } else { 938 | if ($this->debugNextFeed == true) { 939 | $this->debugNextFeed = false; 940 | return $feedContent; 941 | } 942 | } 943 | $purgeAndReplace = isset($options['PurgeAndReplace']) ? $options['PurgeAndReplace'] : false; 944 | 945 | $query = [ 946 | 'FeedType' => $FeedType, 947 | 'PurgeAndReplace' => ($purgeAndReplace ? 'true' : 'false'), 948 | 'Merchant' => $this->config['Seller_Id'], 949 | 'MarketplaceId.Id.1' => false, 950 | 'SellerId' => false, 951 | ]; 952 | //if ($FeedType === '_POST_PRODUCT_PRICING_DATA_') { 953 | $query['MarketplaceIdList.Id.1'] = $this->config['Marketplace_Id']; 954 | //} 955 | $response = $this->request( 956 | 'SubmitFeed', 957 | $query, 958 | $feedContent 959 | ); 960 | return $response['SubmitFeedResult']['FeedSubmissionInfo']; 961 | } 962 | 963 | /** 964 | * Convert an array to xml 965 | * @param $array array to convert 966 | * @param string $customRoot [$customRoot = 'AmazonEnvelope'] 967 | * @return string 968 | */ 969 | protected function arrayToXml(array $array, $customRoot = 'AmazonEnvelope') 970 | { 971 | return ArrayToXml::convert($array, $customRoot, true, 'UTF-8'); 972 | } 973 | 974 | /** 975 | * Convert an xml string to an array 976 | * @param string $xmlstring 977 | * @return array 978 | */ 979 | protected function xmlToArray($xmlstring) 980 | { 981 | return json_decode(json_encode(simplexml_load_string($xmlstring)), true); 982 | } 983 | 984 | /** 985 | * Creates a report request and submits the request to Amazon MWS. 986 | * @param string $report (http://docs.developer.amazonservices.com/en_US/reports/Reports_ReportType.html) 987 | * @param DateTime [$StartDate = null] 988 | * @param DateTime [$EndDate = null] 989 | * @return string ReportRequestId 990 | * @throws Exception 991 | * @throws \GuzzleHttp\Exception\GuzzleException 992 | */ 993 | public function RequestReport($report, $StartDate = null, $EndDate = null) 994 | { 995 | $query = [ 996 | 'MarketplaceIdList.Id.1' => $this->config['Marketplace_Id'], 997 | 'ReportType' => $report 998 | ]; 999 | if (!is_null($StartDate)) { 1000 | if (!is_a($StartDate, 'DateTime')) { 1001 | throw new Exception('StartDate should be a DateTime object'); 1002 | } else { 1003 | $query['StartDate'] = gmdate(self::DATE_FORMAT, $StartDate->getTimestamp()); 1004 | } 1005 | } 1006 | if (!is_null($EndDate)) { 1007 | if (!is_a($EndDate, 'DateTime')) { 1008 | throw new Exception('EndDate should be a DateTime object'); 1009 | } else { 1010 | $query['EndDate'] = gmdate(self::DATE_FORMAT, $EndDate->getTimestamp()); 1011 | } 1012 | } 1013 | $result = $this->request( 1014 | 'RequestReport', 1015 | $query 1016 | ); 1017 | if (isset($result['RequestReportResult']['ReportRequestInfo']['ReportRequestId'])) { 1018 | return $result['RequestReportResult']['ReportRequestInfo']['ReportRequestId']; 1019 | } else { 1020 | throw new Exception('Error trying to request report'); 1021 | } 1022 | } 1023 | 1024 | /** 1025 | * Get a report's content 1026 | * @param string $ReportId 1027 | * @return array|bool on succes 1028 | * @throws Exception 1029 | * @throws \GuzzleHttp\Exception\GuzzleException 1030 | */ 1031 | public function GetReport($ReportId) 1032 | { 1033 | $status = $this->GetReportRequestStatus($ReportId); 1034 | if ($status !== false && $status['ReportProcessingStatus'] === '_DONE_NO_DATA_') { 1035 | return []; 1036 | } else { 1037 | if ($status !== false && $status['ReportProcessingStatus'] === '_DONE_') { 1038 | $result = $this->request('GetReport', [ 1039 | 'ReportId' => $status['GeneratedReportId'] 1040 | ]); 1041 | if (is_string($result)) { 1042 | $reader = Reader::createFromString($result); 1043 | $reader->setDelimiter("\t"); 1044 | $reader->setHeaderOffset(0); 1045 | $headers = $reader->getHeader(); 1046 | $statement = new \League\Csv\Statement; 1047 | $result = []; 1048 | foreach ($statement->process($reader) as $row) { 1049 | $result[] = array_combine($headers, $row); 1050 | } 1051 | } 1052 | return $result; 1053 | } else { 1054 | return false; 1055 | } 1056 | } 1057 | } 1058 | 1059 | /** 1060 | * Get a report's processing status 1061 | * @param string $ReportId 1062 | * @return bool if the report is found 1063 | * @throws Exception 1064 | * @throws \GuzzleHttp\Exception\GuzzleException 1065 | */ 1066 | public function GetReportRequestStatus($ReportId) 1067 | { 1068 | $result = $this->request('GetReportRequestList', [ 1069 | 'ReportRequestIdList.Id.1' => $ReportId 1070 | ]); 1071 | if (isset($result['GetReportRequestListResult']['ReportRequestInfo'])) { 1072 | return $result['GetReportRequestListResult']['ReportRequestInfo']; 1073 | } 1074 | return false; 1075 | } 1076 | 1077 | /** 1078 | * Get a list's inventory for Amazon's fulfillment 1079 | * 1080 | * @param array $sku_array 1081 | * 1082 | * @return array 1083 | * @throws Exception 1084 | * @throws \GuzzleHttp\Exception\GuzzleException 1085 | */ 1086 | public function ListInventorySupply($sku_array = []) 1087 | { 1088 | 1089 | if (count($sku_array) > 50) { 1090 | throw new Exception('Maximum amount of SKU\'s for this call is 50'); 1091 | } 1092 | 1093 | $counter = 1; 1094 | $query = [ 1095 | 'MarketplaceId' => $this->config['Marketplace_Id'] 1096 | ]; 1097 | 1098 | foreach ($sku_array as $key) { 1099 | $query['SellerSkus.member.' . $counter] = $key; 1100 | $counter++; 1101 | } 1102 | 1103 | $response = $this->request( 1104 | 'ListInventorySupply', 1105 | $query 1106 | ); 1107 | 1108 | $result = []; 1109 | if (isset($response['ListInventorySupplyResult']['InventorySupplyList']['member'])) { 1110 | foreach ($response['ListInventorySupplyResult']['InventorySupplyList']['member'] as $index => $ListInventorySupplyResult) { 1111 | $result[$index] = $ListInventorySupplyResult; 1112 | } 1113 | } 1114 | 1115 | return $result; 1116 | } 1117 | 1118 | /** 1119 | * Sets the shipping status of an order 1120 | * @param array $data required data 1121 | * @return array feed submission result 1122 | * @throws Exception 1123 | * @throws \GuzzleHttp\Exception\GuzzleException 1124 | */ 1125 | public function setDeliveryState(array $data) 1126 | { 1127 | if (!isset($data["shippingDate"])) { 1128 | $data["shippingDate"] = date("c"); 1129 | } 1130 | 1131 | if (!isset($data["carrierCode"]) && !isset($data["carrierName"])) { 1132 | throw new Exception('Missing required carrier data'); 1133 | } 1134 | 1135 | $feed = [ 1136 | 'MessageType' => 'OrderFulfillment', 1137 | 'Message' => [ 1138 | 'MessageID' => rand(), 1139 | "OrderFulfillment" => [ 1140 | "AmazonOrderID" => $data["orderId"], 1141 | "FulfillmentDate" => $data["shippingDate"] 1142 | ] 1143 | ] 1144 | ]; 1145 | $fulfillmentData = []; 1146 | 1147 | 1148 | if (isset($data["carrierCode"])) { 1149 | $fulfillmentData["CarrierCode"] = $data["carrierCode"]; 1150 | } elseif (isset($data["carrierName"])) { 1151 | $fulfillmentData["CarrierName"] = $data["carrierName"]; 1152 | } 1153 | 1154 | if (isset($data["shippingMethod"])) { 1155 | $fulfillmentData["ShippingMethod"] = $data["shippingMethod"]; 1156 | } 1157 | 1158 | 1159 | if (isset($data["trackingCode"])) { 1160 | $fulfillmentData["ShipperTrackingNumber"] = $data["trackingCode"]; 1161 | } 1162 | 1163 | if (sizeof($fulfillmentData) > 0) { 1164 | $feed["Message"]["OrderFulfillment"]["FulfillmentData"] = $fulfillmentData; 1165 | } 1166 | $feed = $this->SubmitFeed('_POST_ORDER_FULFILLMENT_DATA_', $feed); 1167 | 1168 | return $feed; 1169 | } 1170 | 1171 | /** 1172 | * Post to create or update a product (_POST_FLAT_FILE_LISTINGS_DATA_) 1173 | * @param object|array $MWSProduct or array of Custom objects 1174 | * @param string $template 1175 | * @param null $version 1176 | * @param null $signature 1177 | * @return array 1178 | * @throws Exception 1179 | * @throws \GuzzleHttp\Exception\GuzzleException 1180 | */ 1181 | public function postProduct($MWSProduct, $template = 'Custom', $version = null, $signature = null) 1182 | { 1183 | if (!is_array($MWSProduct)) { 1184 | $MWSProduct = [$MWSProduct]; 1185 | } 1186 | $csv = Writer::createFromFileObject(new SplTempFileObject()); 1187 | $csv->setDelimiter("\t"); 1188 | 1189 | $csv->insertOne(['TemplateType=' . $template, 'Version=' . $version, 'TemplateSignature=' . $signature]); 1190 | 1191 | $header = array_keys($MWSProduct[0]->toArray()); 1192 | 1193 | $csv->insertOne($header); 1194 | foreach ($MWSProduct as $product) { 1195 | $csv->insertOne(array_values($product->toArray())); 1196 | } 1197 | // $csv->output(date('Y-m-d') . '.csv'); 1198 | // die; 1199 | 1200 | return $this->SubmitFeed('_POST_FLAT_FILE_LISTINGS_DATA_', $csv); 1201 | } 1202 | 1203 | /** 1204 | * Returns financial events for a given order by it's id 1205 | * 1206 | * @param string $AmazonOrderId 1207 | * @return array 1208 | * 1209 | * @throws Exception 1210 | * @throws \GuzzleHttp\Exception\GuzzleException 1211 | */ 1212 | public function ListFinancialEventsByOrderId($AmazonOrderId) 1213 | { 1214 | $query = ['AmazonOrderId' => $AmazonOrderId]; 1215 | $response = $this->request('ListFinancialEvents', $query); 1216 | return $this->processListFinancialEventsResponse($response); 1217 | } 1218 | 1219 | /** 1220 | * Returns financial events for a given financial event group id 1221 | * 1222 | * @param $groupId 1223 | * @return array 1224 | * 1225 | * @throws Exception 1226 | * @throws \GuzzleHttp\Exception\GuzzleException 1227 | */ 1228 | public function ListFinancialEventsByEventGroupId($groupId) 1229 | { 1230 | $query = ['FinancialEventGroupId' => $groupId]; 1231 | $response = $this->request('ListFinancialEvents', $query); 1232 | return $this->processListFinancialEventsResponse($response); 1233 | } 1234 | 1235 | /** 1236 | * Returns financial events for a given financial events date range 1237 | * 1238 | * @param DateTime $from 1239 | * @param DateTime|null $till 1240 | * 1241 | * @return array 1242 | * 1243 | * @throws Exception 1244 | * @throws \GuzzleHttp\Exception\GuzzleException 1245 | */ 1246 | public function ListFinancialEventsByDateRange(DateTime $from, DateTime $till = null) 1247 | { 1248 | $query = [ 1249 | 'PostedAfter' => gmdate(self::DATE_FORMAT, $from->getTimestamp()) 1250 | ]; 1251 | if (!is_null($till)) { 1252 | $query['PostedBefore'] = gmdate(self::DATE_FORMAT, $till->getTimestamp()); 1253 | } 1254 | $response = $this->request('ListFinancialEvents', $query); 1255 | return $this->processListFinancialEventsResponse($response); 1256 | } 1257 | 1258 | /** 1259 | * Processes list financial events response 1260 | * 1261 | * @param array $response 1262 | * @param string $fieldName 1263 | * 1264 | * @return array 1265 | */ 1266 | protected function processListFinancialEventsResponse($response, $fieldName = 'ListFinancialEventsResult') 1267 | { 1268 | if (!isset($response[$fieldName]['FinancialEvents'])) { 1269 | return []; 1270 | } 1271 | $data = $response[$fieldName]['FinancialEvents']; 1272 | // We remove empty lists 1273 | $data = array_filter($data, function ($item) { 1274 | return count($item) > 0; 1275 | }); 1276 | if (isset($response[$fieldName]['NextToken'])) { 1277 | // Remove ==, I've seen cases when Amazon servers fails otherwise 1278 | $data['ListFinancialEvents'] = $data; 1279 | $data['NextToken'] = rtrim($response[$fieldName]['NextToken'], '='); 1280 | return $data; 1281 | } 1282 | return ['ListFinancialEvents' => $data]; 1283 | } 1284 | 1285 | /** 1286 | * Returns the next page of financial events using the NextToken parameter 1287 | * 1288 | * @param string $nextToken 1289 | * @return array 1290 | * 1291 | * @throws Exception 1292 | * @throws \GuzzleHttp\Exception\GuzzleException 1293 | */ 1294 | public function ListFinancialEventsByNextToken($nextToken) 1295 | { 1296 | $query = [ 1297 | 'NextToken' => $nextToken, 1298 | ]; 1299 | $response = $this->request( 1300 | 'ListFinancialEventsByNextToken', 1301 | $query 1302 | ); 1303 | return $this->processListFinancialEventsResponse($response, 'ListFinancialEventsByNextTokenResult'); 1304 | } 1305 | 1306 | /** 1307 | * @param array $ReportTypeList 1308 | * @param $limit 1309 | * @return array 1310 | * @throws \GuzzleHttp\Exception\GuzzleException 1311 | */ 1312 | public function GetReportRequestList($ReportTypeList = null, $limit = null) 1313 | { 1314 | $array = []; 1315 | $counter = 1; 1316 | if (count($ReportTypeList)) { 1317 | foreach ($ReportTypeList as $ReportType) { 1318 | $array['ReportTypeList.Type.' . $counter] = $ReportType; 1319 | $counter++; 1320 | } 1321 | } 1322 | $array['MaxCount'] = $limit; 1323 | return $this->request('GetReportRequestList', $array); 1324 | } 1325 | 1326 | /** 1327 | * @param array $ReportTypeList 1328 | * @param $nextToken 1329 | * @param $limit 1330 | * @return array 1331 | * @throws \GuzzleHttp\Exception\GuzzleException 1332 | */ 1333 | public function GetReportListByNextToken($ReportTypeList = [], $nextToken = null, $limit = null) 1334 | { 1335 | $array = []; 1336 | $counter = 1; 1337 | if (count($ReportTypeList)) { 1338 | foreach ($ReportTypeList as $ReportType) { 1339 | $array['ReportTypeList.Type.' . $counter] = $ReportType; 1340 | $counter++; 1341 | } 1342 | } 1343 | if ($nextToken != null) { 1344 | $array['NextToken'] = $nextToken; 1345 | } 1346 | $array['MaxCount'] = $limit; 1347 | return $this->request('GetReportListByNextToken', $array); 1348 | } 1349 | 1350 | /** 1351 | * Request MWS 1352 | * 1353 | * @param $endPoint 1354 | * @param array $query 1355 | * @param null $body 1356 | * @param bool $raw 1357 | * @return string|array 1358 | * @throws \GuzzleHttp\Exception\GuzzleException 1359 | * @throws Exception 1360 | */ 1361 | protected function request($endPoint, array $query = [], $body = null, $raw = false) 1362 | { 1363 | $endPoint = MWSEndPoint::get($endPoint); 1364 | $merge = [ 1365 | 'Timestamp' => gmdate(self::DATE_FORMAT, time()), 1366 | 'AWSAccessKeyId' => $this->config['Access_Key_ID'], 1367 | 'Action' => $endPoint['action'], 1368 | //'MarketplaceId.Id.1' => $this->config['Marketplace_Id'], 1369 | 'SellerId' => $this->config['Seller_Id'], 1370 | 'SignatureMethod' => self::SIGNATURE_METHOD, 1371 | 'SignatureVersion' => self::SIGNATURE_VERSION, 1372 | 'Version' => $endPoint['date'], 1373 | ]; 1374 | $query = array_merge($merge, $query); 1375 | if (!isset($query['MarketplaceId.Id.1'])) { 1376 | $query['MarketplaceId.Id.1'] = $this->config['Marketplace_Id']; 1377 | } 1378 | if (!is_null($this->config['MWSAuthToken']) and $this->config['MWSAuthToken'] != "") { 1379 | $query['MWSAuthToken'] = $this->config['MWSAuthToken']; 1380 | } 1381 | if (isset($query['MarketplaceId'])) { 1382 | unset($query['MarketplaceId.Id.1']); 1383 | } 1384 | if (isset($query['MarketplaceIdList.Id.1'])) { 1385 | unset($query['MarketplaceId.Id.1']); 1386 | } 1387 | try { 1388 | $headers = [ 1389 | 'Accept' => 'application/xml', 1390 | 'x-amazon-user-agent' => $this->config['Application_Name'] . '/' . $this->config['Application_Version'] 1391 | ]; 1392 | if ($endPoint['action'] === 'SubmitFeed') { 1393 | $headers['Content-MD5'] = base64_encode(md5($body, true)); 1394 | if (in_array($this->config['Marketplace_Id'], ['AAHKV2X7AFYLW', 'A1VC38T7YXB528'])) { 1395 | $headers['Content-Type'] = 'text/xml; charset=UTF-8'; 1396 | } else { 1397 | $headers['Content-Type'] = 'text/xml; charset=iso-8859-16'; 1398 | } 1399 | 1400 | $headers['Host'] = $this->config['Region_Host']; 1401 | unset( 1402 | $query['MarketplaceId.Id.1'], 1403 | $query['SellerId'] 1404 | ); 1405 | } 1406 | $requestOptions = [ 1407 | 'headers' => $headers, 1408 | 'body' => $body, 1409 | 'curl' => [ 1410 | CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2 1411 | ] 1412 | ]; 1413 | ksort($query); 1414 | $query['Signature'] = base64_encode( 1415 | hash_hmac( 1416 | 'sha256', 1417 | $endPoint['method'] 1418 | . "\n" 1419 | . $this->config['Region_Host'] 1420 | . "\n" 1421 | . $endPoint['path'] 1422 | . "\n" 1423 | . http_build_query($query, null, '&', PHP_QUERY_RFC3986), 1424 | $this->config['Secret_Access_Key'], 1425 | true 1426 | ) 1427 | ); 1428 | if ($endPoint['action'] === 'GetLowestPricedOffersForASIN') { 1429 | $requestOptions['form_params'] = $query; 1430 | } else { 1431 | $requestOptions['query'] = $query; 1432 | } 1433 | 1434 | if ($this->client === null) { 1435 | $this->client = new Client(); 1436 | } 1437 | $response = $this->client->request( 1438 | $endPoint['method'], 1439 | $this->config['Region_Url'] . $endPoint['path'], 1440 | $requestOptions 1441 | ); 1442 | $body = (string)$response->getBody(); 1443 | if ($raw) { 1444 | return $body; 1445 | } else { 1446 | if (strpos(strtolower($response->getHeader('Content-Type')[0]), 'xml') !== false) { 1447 | return $this->xmlToArray($body); 1448 | } else { 1449 | return $body; 1450 | } 1451 | } 1452 | } catch (BadResponseException $e) { 1453 | if ($e->hasResponse()) { 1454 | $message = $e->getResponse(); 1455 | $message = $message->getBody(); 1456 | if (strpos($message, 'Error->Message; 1459 | } 1460 | } else { 1461 | $message = 'An error occured'; 1462 | } 1463 | throw new Exception($message); 1464 | } 1465 | } 1466 | 1467 | public function setClient(Client $client) 1468 | { 1469 | $this->client = $client; 1470 | } 1471 | } 1472 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "9ea4b0f244db91f83788d3140ec73d56", 8 | "packages": [ 9 | { 10 | "name": "guzzlehttp/guzzle", 11 | "version": "dev-master", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/guzzle/guzzle.git", 15 | "reference": "ca2892a8c2778c1821899fd2c79932e3b895f2ad" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ca2892a8c2778c1821899fd2c79932e3b895f2ad", 20 | "reference": "ca2892a8c2778c1821899fd2c79932e3b895f2ad", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-json": "*", 25 | "guzzlehttp/promises": "^1.0", 26 | "guzzlehttp/psr7": "^1.4", 27 | "php": ">=5.5" 28 | }, 29 | "require-dev": { 30 | "ext-curl": "*", 31 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", 32 | "psr/log": "^1.1" 33 | }, 34 | "suggest": { 35 | "psr/log": "Required for using the Log middleware" 36 | }, 37 | "type": "library", 38 | "extra": { 39 | "branch-alias": { 40 | "dev-master": "6.3-dev" 41 | } 42 | }, 43 | "autoload": { 44 | "psr-4": { 45 | "GuzzleHttp\\": "src/" 46 | }, 47 | "files": [ 48 | "src/functions_include.php" 49 | ] 50 | }, 51 | "notification-url": "https://packagist.org/downloads/", 52 | "license": [ 53 | "MIT" 54 | ], 55 | "authors": [ 56 | { 57 | "name": "Michael Dowling", 58 | "email": "mtdowling@gmail.com", 59 | "homepage": "https://github.com/mtdowling" 60 | } 61 | ], 62 | "description": "Guzzle is a PHP HTTP client library", 63 | "homepage": "http://guzzlephp.org/", 64 | "keywords": [ 65 | "client", 66 | "curl", 67 | "framework", 68 | "http", 69 | "http client", 70 | "rest", 71 | "web service" 72 | ], 73 | "time": "2019-05-12T12:35:22+00:00" 74 | }, 75 | { 76 | "name": "guzzlehttp/promises", 77 | "version": "dev-master", 78 | "source": { 79 | "type": "git", 80 | "url": "https://github.com/guzzle/promises.git", 81 | "reference": "17d36ed176c998839582c739ce0753381598edf0" 82 | }, 83 | "dist": { 84 | "type": "zip", 85 | "url": "https://api.github.com/repos/guzzle/promises/zipball/17d36ed176c998839582c739ce0753381598edf0", 86 | "reference": "17d36ed176c998839582c739ce0753381598edf0", 87 | "shasum": "" 88 | }, 89 | "require": { 90 | "php": ">=5.6" 91 | }, 92 | "require-dev": { 93 | "phpunit/phpunit": "^5.7.27 || ^7.5" 94 | }, 95 | "type": "library", 96 | "extra": { 97 | "branch-alias": { 98 | "dev-master": "1.4-dev" 99 | } 100 | }, 101 | "autoload": { 102 | "psr-4": { 103 | "GuzzleHttp\\Promise\\": "src/" 104 | }, 105 | "files": [ 106 | "src/functions_include.php" 107 | ] 108 | }, 109 | "notification-url": "https://packagist.org/downloads/", 110 | "license": [ 111 | "MIT" 112 | ], 113 | "authors": [ 114 | { 115 | "name": "Michael Dowling", 116 | "email": "mtdowling@gmail.com", 117 | "homepage": "https://github.com/mtdowling" 118 | } 119 | ], 120 | "description": "Guzzle promises library", 121 | "keywords": [ 122 | "promise" 123 | ], 124 | "time": "2019-07-02T14:54:06+00:00" 125 | }, 126 | { 127 | "name": "guzzlehttp/psr7", 128 | "version": "1.x-dev", 129 | "source": { 130 | "type": "git", 131 | "url": "https://github.com/guzzle/psr7.git", 132 | "reference": "239400de7a173fe9901b9ac7c06497751f00727a" 133 | }, 134 | "dist": { 135 | "type": "zip", 136 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", 137 | "reference": "239400de7a173fe9901b9ac7c06497751f00727a", 138 | "shasum": "" 139 | }, 140 | "require": { 141 | "php": ">=5.4.0", 142 | "psr/http-message": "~1.0", 143 | "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" 144 | }, 145 | "provide": { 146 | "psr/http-message-implementation": "1.0" 147 | }, 148 | "require-dev": { 149 | "ext-zlib": "*", 150 | "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" 151 | }, 152 | "suggest": { 153 | "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" 154 | }, 155 | "type": "library", 156 | "extra": { 157 | "branch-alias": { 158 | "dev-master": "1.6-dev" 159 | } 160 | }, 161 | "autoload": { 162 | "psr-4": { 163 | "GuzzleHttp\\Psr7\\": "src/" 164 | }, 165 | "files": [ 166 | "src/functions_include.php" 167 | ] 168 | }, 169 | "notification-url": "https://packagist.org/downloads/", 170 | "license": [ 171 | "MIT" 172 | ], 173 | "authors": [ 174 | { 175 | "name": "Michael Dowling", 176 | "email": "mtdowling@gmail.com", 177 | "homepage": "https://github.com/mtdowling" 178 | }, 179 | { 180 | "name": "Tobias Schultze", 181 | "homepage": "https://github.com/Tobion" 182 | } 183 | ], 184 | "description": "PSR-7 message implementation that also provides common utility methods", 185 | "keywords": [ 186 | "http", 187 | "message", 188 | "psr-7", 189 | "request", 190 | "response", 191 | "stream", 192 | "uri", 193 | "url" 194 | ], 195 | "time": "2019-07-01T23:21:34+00:00" 196 | }, 197 | { 198 | "name": "league/csv", 199 | "version": "dev-master", 200 | "source": { 201 | "type": "git", 202 | "url": "https://github.com/thephpleague/csv.git", 203 | "reference": "3ae0efd15c3d13effbeac474fe205e23c5c86648" 204 | }, 205 | "dist": { 206 | "type": "zip", 207 | "url": "https://api.github.com/repos/thephpleague/csv/zipball/3ae0efd15c3d13effbeac474fe205e23c5c86648", 208 | "reference": "3ae0efd15c3d13effbeac474fe205e23c5c86648", 209 | "shasum": "" 210 | }, 211 | "require": { 212 | "ext-dom": "*", 213 | "ext-json": "*", 214 | "ext-mbstring": "*", 215 | "php": ">=7.0.10" 216 | }, 217 | "require-dev": { 218 | "ext-curl": "*", 219 | "friendsofphp/php-cs-fixer": "^2.12", 220 | "phpstan/phpstan": "^0.9.2", 221 | "phpstan/phpstan-phpunit": "^0.9.4", 222 | "phpstan/phpstan-strict-rules": "^0.9.0", 223 | "phpunit/phpunit": "^6.0" 224 | }, 225 | "suggest": { 226 | "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters" 227 | }, 228 | "type": "library", 229 | "extra": { 230 | "branch-alias": { 231 | "dev-master": "9.x-dev" 232 | } 233 | }, 234 | "autoload": { 235 | "psr-4": { 236 | "League\\Csv\\": "src" 237 | }, 238 | "files": [ 239 | "src/functions_include.php" 240 | ] 241 | }, 242 | "notification-url": "https://packagist.org/downloads/", 243 | "license": [ 244 | "MIT" 245 | ], 246 | "authors": [ 247 | { 248 | "name": "Ignace Nyamagana Butera", 249 | "email": "nyamsprod@gmail.com", 250 | "homepage": "https://github.com/nyamsprod/", 251 | "role": "Developer" 252 | } 253 | ], 254 | "description": "Csv data manipulation made easy in PHP", 255 | "homepage": "http://csv.thephpleague.com", 256 | "keywords": [ 257 | "csv", 258 | "export", 259 | "filter", 260 | "import", 261 | "read", 262 | "write" 263 | ], 264 | "time": "2019-07-16T10:23:56+00:00" 265 | }, 266 | { 267 | "name": "psr/http-message", 268 | "version": "dev-master", 269 | "source": { 270 | "type": "git", 271 | "url": "https://github.com/php-fig/http-message.git", 272 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 273 | }, 274 | "dist": { 275 | "type": "zip", 276 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 277 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 278 | "shasum": "" 279 | }, 280 | "require": { 281 | "php": ">=5.3.0" 282 | }, 283 | "type": "library", 284 | "extra": { 285 | "branch-alias": { 286 | "dev-master": "1.0.x-dev" 287 | } 288 | }, 289 | "autoload": { 290 | "psr-4": { 291 | "Psr\\Http\\Message\\": "src/" 292 | } 293 | }, 294 | "notification-url": "https://packagist.org/downloads/", 295 | "license": [ 296 | "MIT" 297 | ], 298 | "authors": [ 299 | { 300 | "name": "PHP-FIG", 301 | "homepage": "http://www.php-fig.org/" 302 | } 303 | ], 304 | "description": "Common interface for HTTP messages", 305 | "homepage": "https://github.com/php-fig/http-message", 306 | "keywords": [ 307 | "http", 308 | "http-message", 309 | "psr", 310 | "psr-7", 311 | "request", 312 | "response" 313 | ], 314 | "time": "2016-08-06T14:39:51+00:00" 315 | }, 316 | { 317 | "name": "ralouphie/getallheaders", 318 | "version": "3.0.3", 319 | "source": { 320 | "type": "git", 321 | "url": "https://github.com/ralouphie/getallheaders.git", 322 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 323 | }, 324 | "dist": { 325 | "type": "zip", 326 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 327 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 328 | "shasum": "" 329 | }, 330 | "require": { 331 | "php": ">=5.6" 332 | }, 333 | "require-dev": { 334 | "php-coveralls/php-coveralls": "^2.1", 335 | "phpunit/phpunit": "^5 || ^6.5" 336 | }, 337 | "type": "library", 338 | "autoload": { 339 | "files": [ 340 | "src/getallheaders.php" 341 | ] 342 | }, 343 | "notification-url": "https://packagist.org/downloads/", 344 | "license": [ 345 | "MIT" 346 | ], 347 | "authors": [ 348 | { 349 | "name": "Ralph Khattar", 350 | "email": "ralph.khattar@gmail.com" 351 | } 352 | ], 353 | "description": "A polyfill for getallheaders.", 354 | "time": "2019-03-08T08:55:37+00:00" 355 | }, 356 | { 357 | "name": "spatie/array-to-xml", 358 | "version": "2.10.0", 359 | "source": { 360 | "type": "git", 361 | "url": "https://github.com/spatie/array-to-xml.git", 362 | "reference": "eb035710f44400ec820c664426a92753b6e19c17" 363 | }, 364 | "dist": { 365 | "type": "zip", 366 | "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/eb035710f44400ec820c664426a92753b6e19c17", 367 | "reference": "eb035710f44400ec820c664426a92753b6e19c17", 368 | "shasum": "" 369 | }, 370 | "require": { 371 | "ext-dom": "*", 372 | "php": "^7.1" 373 | }, 374 | "require-dev": { 375 | "mockery/mockery": "^1.0", 376 | "phpunit/phpunit": "^7.0", 377 | "spatie/phpunit-snapshot-assertions": "^2.0" 378 | }, 379 | "type": "library", 380 | "autoload": { 381 | "psr-4": { 382 | "Spatie\\ArrayToXml\\": "src" 383 | } 384 | }, 385 | "notification-url": "https://packagist.org/downloads/", 386 | "license": [ 387 | "MIT" 388 | ], 389 | "authors": [ 390 | { 391 | "name": "Freek Van der Herten", 392 | "email": "freek@spatie.be", 393 | "homepage": "https://murze.be", 394 | "role": "Developer" 395 | } 396 | ], 397 | "description": "Convert an array to xml", 398 | "homepage": "https://github.com/spatie/array-to-xml", 399 | "keywords": [ 400 | "array", 401 | "convert", 402 | "xml" 403 | ], 404 | "time": "2019-06-26T21:53:11+00:00" 405 | } 406 | ], 407 | "packages-dev": [ 408 | { 409 | "name": "doctrine/instantiator", 410 | "version": "dev-master", 411 | "source": { 412 | "type": "git", 413 | "url": "https://github.com/doctrine/instantiator.git", 414 | "reference": "7c71fc2932158d00f24f10635bf3b3b8b6ee5b68" 415 | }, 416 | "dist": { 417 | "type": "zip", 418 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/7c71fc2932158d00f24f10635bf3b3b8b6ee5b68", 419 | "reference": "7c71fc2932158d00f24f10635bf3b3b8b6ee5b68", 420 | "shasum": "" 421 | }, 422 | "require": { 423 | "php": "^7.1" 424 | }, 425 | "require-dev": { 426 | "doctrine/coding-standard": "^6.0", 427 | "ext-pdo": "*", 428 | "ext-phar": "*", 429 | "phpbench/phpbench": "^0.13", 430 | "phpstan/phpstan-phpunit": "^0.11", 431 | "phpstan/phpstan-shim": "^0.11", 432 | "phpunit/phpunit": "^7.0" 433 | }, 434 | "type": "library", 435 | "extra": { 436 | "branch-alias": { 437 | "dev-master": "1.2.x-dev" 438 | } 439 | }, 440 | "autoload": { 441 | "psr-4": { 442 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 443 | } 444 | }, 445 | "notification-url": "https://packagist.org/downloads/", 446 | "license": [ 447 | "MIT" 448 | ], 449 | "authors": [ 450 | { 451 | "name": "Marco Pivetta", 452 | "email": "ocramius@gmail.com", 453 | "homepage": "http://ocramius.github.com/" 454 | } 455 | ], 456 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 457 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 458 | "keywords": [ 459 | "constructor", 460 | "instantiate" 461 | ], 462 | "time": "2019-07-02T13:37:32+00:00" 463 | }, 464 | { 465 | "name": "myclabs/deep-copy", 466 | "version": "1.x-dev", 467 | "source": { 468 | "type": "git", 469 | "url": "https://github.com/myclabs/DeepCopy.git", 470 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" 471 | }, 472 | "dist": { 473 | "type": "zip", 474 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", 475 | "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", 476 | "shasum": "" 477 | }, 478 | "require": { 479 | "php": "^7.1" 480 | }, 481 | "replace": { 482 | "myclabs/deep-copy": "self.version" 483 | }, 484 | "require-dev": { 485 | "doctrine/collections": "^1.0", 486 | "doctrine/common": "^2.6", 487 | "phpunit/phpunit": "^7.1" 488 | }, 489 | "type": "library", 490 | "autoload": { 491 | "psr-4": { 492 | "DeepCopy\\": "src/DeepCopy/" 493 | }, 494 | "files": [ 495 | "src/DeepCopy/deep_copy.php" 496 | ] 497 | }, 498 | "notification-url": "https://packagist.org/downloads/", 499 | "license": [ 500 | "MIT" 501 | ], 502 | "description": "Create deep copies (clones) of your objects", 503 | "keywords": [ 504 | "clone", 505 | "copy", 506 | "duplicate", 507 | "object", 508 | "object graph" 509 | ], 510 | "time": "2019-04-07T13:18:21+00:00" 511 | }, 512 | { 513 | "name": "phar-io/manifest", 514 | "version": "1.0.3", 515 | "source": { 516 | "type": "git", 517 | "url": "https://github.com/phar-io/manifest.git", 518 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" 519 | }, 520 | "dist": { 521 | "type": "zip", 522 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 523 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 524 | "shasum": "" 525 | }, 526 | "require": { 527 | "ext-dom": "*", 528 | "ext-phar": "*", 529 | "phar-io/version": "^2.0", 530 | "php": "^5.6 || ^7.0" 531 | }, 532 | "type": "library", 533 | "extra": { 534 | "branch-alias": { 535 | "dev-master": "1.0.x-dev" 536 | } 537 | }, 538 | "autoload": { 539 | "classmap": [ 540 | "src/" 541 | ] 542 | }, 543 | "notification-url": "https://packagist.org/downloads/", 544 | "license": [ 545 | "BSD-3-Clause" 546 | ], 547 | "authors": [ 548 | { 549 | "name": "Arne Blankerts", 550 | "email": "arne@blankerts.de", 551 | "role": "Developer" 552 | }, 553 | { 554 | "name": "Sebastian Heuer", 555 | "email": "sebastian@phpeople.de", 556 | "role": "Developer" 557 | }, 558 | { 559 | "name": "Sebastian Bergmann", 560 | "email": "sebastian@phpunit.de", 561 | "role": "Developer" 562 | } 563 | ], 564 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 565 | "time": "2018-07-08T19:23:20+00:00" 566 | }, 567 | { 568 | "name": "phar-io/version", 569 | "version": "2.0.1", 570 | "source": { 571 | "type": "git", 572 | "url": "https://github.com/phar-io/version.git", 573 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" 574 | }, 575 | "dist": { 576 | "type": "zip", 577 | "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", 578 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", 579 | "shasum": "" 580 | }, 581 | "require": { 582 | "php": "^5.6 || ^7.0" 583 | }, 584 | "type": "library", 585 | "autoload": { 586 | "classmap": [ 587 | "src/" 588 | ] 589 | }, 590 | "notification-url": "https://packagist.org/downloads/", 591 | "license": [ 592 | "BSD-3-Clause" 593 | ], 594 | "authors": [ 595 | { 596 | "name": "Arne Blankerts", 597 | "email": "arne@blankerts.de", 598 | "role": "Developer" 599 | }, 600 | { 601 | "name": "Sebastian Heuer", 602 | "email": "sebastian@phpeople.de", 603 | "role": "Developer" 604 | }, 605 | { 606 | "name": "Sebastian Bergmann", 607 | "email": "sebastian@phpunit.de", 608 | "role": "Developer" 609 | } 610 | ], 611 | "description": "Library for handling version information and constraints", 612 | "time": "2018-07-08T19:19:57+00:00" 613 | }, 614 | { 615 | "name": "phpdocumentor/reflection-common", 616 | "version": "1.0.1", 617 | "source": { 618 | "type": "git", 619 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 620 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 621 | }, 622 | "dist": { 623 | "type": "zip", 624 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 625 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 626 | "shasum": "" 627 | }, 628 | "require": { 629 | "php": ">=5.5" 630 | }, 631 | "require-dev": { 632 | "phpunit/phpunit": "^4.6" 633 | }, 634 | "type": "library", 635 | "extra": { 636 | "branch-alias": { 637 | "dev-master": "1.0.x-dev" 638 | } 639 | }, 640 | "autoload": { 641 | "psr-4": { 642 | "phpDocumentor\\Reflection\\": [ 643 | "src" 644 | ] 645 | } 646 | }, 647 | "notification-url": "https://packagist.org/downloads/", 648 | "license": [ 649 | "MIT" 650 | ], 651 | "authors": [ 652 | { 653 | "name": "Jaap van Otterdijk", 654 | "email": "opensource@ijaap.nl" 655 | } 656 | ], 657 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 658 | "homepage": "http://www.phpdoc.org", 659 | "keywords": [ 660 | "FQSEN", 661 | "phpDocumentor", 662 | "phpdoc", 663 | "reflection", 664 | "static analysis" 665 | ], 666 | "time": "2017-09-11T18:02:19+00:00" 667 | }, 668 | { 669 | "name": "phpdocumentor/reflection-docblock", 670 | "version": "4.3.1", 671 | "source": { 672 | "type": "git", 673 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 674 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" 675 | }, 676 | "dist": { 677 | "type": "zip", 678 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", 679 | "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", 680 | "shasum": "" 681 | }, 682 | "require": { 683 | "php": "^7.0", 684 | "phpdocumentor/reflection-common": "^1.0.0", 685 | "phpdocumentor/type-resolver": "^0.4.0", 686 | "webmozart/assert": "^1.0" 687 | }, 688 | "require-dev": { 689 | "doctrine/instantiator": "~1.0.5", 690 | "mockery/mockery": "^1.0", 691 | "phpunit/phpunit": "^6.4" 692 | }, 693 | "type": "library", 694 | "extra": { 695 | "branch-alias": { 696 | "dev-master": "4.x-dev" 697 | } 698 | }, 699 | "autoload": { 700 | "psr-4": { 701 | "phpDocumentor\\Reflection\\": [ 702 | "src/" 703 | ] 704 | } 705 | }, 706 | "notification-url": "https://packagist.org/downloads/", 707 | "license": [ 708 | "MIT" 709 | ], 710 | "authors": [ 711 | { 712 | "name": "Mike van Riel", 713 | "email": "me@mikevanriel.com" 714 | } 715 | ], 716 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 717 | "time": "2019-04-30T17:48:53+00:00" 718 | }, 719 | { 720 | "name": "phpdocumentor/type-resolver", 721 | "version": "0.4.0", 722 | "source": { 723 | "type": "git", 724 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 725 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 726 | }, 727 | "dist": { 728 | "type": "zip", 729 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 730 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 731 | "shasum": "" 732 | }, 733 | "require": { 734 | "php": "^5.5 || ^7.0", 735 | "phpdocumentor/reflection-common": "^1.0" 736 | }, 737 | "require-dev": { 738 | "mockery/mockery": "^0.9.4", 739 | "phpunit/phpunit": "^5.2||^4.8.24" 740 | }, 741 | "type": "library", 742 | "extra": { 743 | "branch-alias": { 744 | "dev-master": "1.0.x-dev" 745 | } 746 | }, 747 | "autoload": { 748 | "psr-4": { 749 | "phpDocumentor\\Reflection\\": [ 750 | "src/" 751 | ] 752 | } 753 | }, 754 | "notification-url": "https://packagist.org/downloads/", 755 | "license": [ 756 | "MIT" 757 | ], 758 | "authors": [ 759 | { 760 | "name": "Mike van Riel", 761 | "email": "me@mikevanriel.com" 762 | } 763 | ], 764 | "time": "2017-07-14T14:27:02+00:00" 765 | }, 766 | { 767 | "name": "phpspec/prophecy", 768 | "version": "dev-master", 769 | "source": { 770 | "type": "git", 771 | "url": "https://github.com/phpspec/prophecy.git", 772 | "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" 773 | }, 774 | "dist": { 775 | "type": "zip", 776 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", 777 | "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", 778 | "shasum": "" 779 | }, 780 | "require": { 781 | "doctrine/instantiator": "^1.0.2", 782 | "php": "^5.3|^7.0", 783 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 784 | "sebastian/comparator": "^1.1|^2.0|^3.0", 785 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 786 | }, 787 | "require-dev": { 788 | "phpspec/phpspec": "^2.5|^3.2", 789 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 790 | }, 791 | "type": "library", 792 | "extra": { 793 | "branch-alias": { 794 | "dev-master": "1.8.x-dev" 795 | } 796 | }, 797 | "autoload": { 798 | "psr-4": { 799 | "Prophecy\\": "src/Prophecy" 800 | } 801 | }, 802 | "notification-url": "https://packagist.org/downloads/", 803 | "license": [ 804 | "MIT" 805 | ], 806 | "authors": [ 807 | { 808 | "name": "Konstantin Kudryashov", 809 | "email": "ever.zet@gmail.com", 810 | "homepage": "http://everzet.com" 811 | }, 812 | { 813 | "name": "Marcello Duarte", 814 | "email": "marcello.duarte@gmail.com" 815 | } 816 | ], 817 | "description": "Highly opinionated mocking framework for PHP 5.3+", 818 | "homepage": "https://github.com/phpspec/prophecy", 819 | "keywords": [ 820 | "Double", 821 | "Dummy", 822 | "fake", 823 | "mock", 824 | "spy", 825 | "stub" 826 | ], 827 | "time": "2019-06-13T12:50:23+00:00" 828 | }, 829 | { 830 | "name": "phpunit/php-code-coverage", 831 | "version": "6.1.4", 832 | "source": { 833 | "type": "git", 834 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 835 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" 836 | }, 837 | "dist": { 838 | "type": "zip", 839 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 840 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 841 | "shasum": "" 842 | }, 843 | "require": { 844 | "ext-dom": "*", 845 | "ext-xmlwriter": "*", 846 | "php": "^7.1", 847 | "phpunit/php-file-iterator": "^2.0", 848 | "phpunit/php-text-template": "^1.2.1", 849 | "phpunit/php-token-stream": "^3.0", 850 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 851 | "sebastian/environment": "^3.1 || ^4.0", 852 | "sebastian/version": "^2.0.1", 853 | "theseer/tokenizer": "^1.1" 854 | }, 855 | "require-dev": { 856 | "phpunit/phpunit": "^7.0" 857 | }, 858 | "suggest": { 859 | "ext-xdebug": "^2.6.0" 860 | }, 861 | "type": "library", 862 | "extra": { 863 | "branch-alias": { 864 | "dev-master": "6.1-dev" 865 | } 866 | }, 867 | "autoload": { 868 | "classmap": [ 869 | "src/" 870 | ] 871 | }, 872 | "notification-url": "https://packagist.org/downloads/", 873 | "license": [ 874 | "BSD-3-Clause" 875 | ], 876 | "authors": [ 877 | { 878 | "name": "Sebastian Bergmann", 879 | "email": "sebastian@phpunit.de", 880 | "role": "lead" 881 | } 882 | ], 883 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 884 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 885 | "keywords": [ 886 | "coverage", 887 | "testing", 888 | "xunit" 889 | ], 890 | "time": "2018-10-31T16:06:48+00:00" 891 | }, 892 | { 893 | "name": "phpunit/php-file-iterator", 894 | "version": "dev-master", 895 | "source": { 896 | "type": "git", 897 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 898 | "reference": "7f0f29702170e2786b2df813af970135765de6fc" 899 | }, 900 | "dist": { 901 | "type": "zip", 902 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/7f0f29702170e2786b2df813af970135765de6fc", 903 | "reference": "7f0f29702170e2786b2df813af970135765de6fc", 904 | "shasum": "" 905 | }, 906 | "require": { 907 | "php": "^7.1" 908 | }, 909 | "require-dev": { 910 | "phpunit/phpunit": "^7.1" 911 | }, 912 | "type": "library", 913 | "extra": { 914 | "branch-alias": { 915 | "dev-master": "2.0.x-dev" 916 | } 917 | }, 918 | "autoload": { 919 | "classmap": [ 920 | "src/" 921 | ] 922 | }, 923 | "notification-url": "https://packagist.org/downloads/", 924 | "license": [ 925 | "BSD-3-Clause" 926 | ], 927 | "authors": [ 928 | { 929 | "name": "Sebastian Bergmann", 930 | "email": "sebastian@phpunit.de", 931 | "role": "lead" 932 | } 933 | ], 934 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 935 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 936 | "keywords": [ 937 | "filesystem", 938 | "iterator" 939 | ], 940 | "time": "2019-07-02T07:44:20+00:00" 941 | }, 942 | { 943 | "name": "phpunit/php-text-template", 944 | "version": "1.2.1", 945 | "source": { 946 | "type": "git", 947 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 948 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 949 | }, 950 | "dist": { 951 | "type": "zip", 952 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 953 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 954 | "shasum": "" 955 | }, 956 | "require": { 957 | "php": ">=5.3.3" 958 | }, 959 | "type": "library", 960 | "autoload": { 961 | "classmap": [ 962 | "src/" 963 | ] 964 | }, 965 | "notification-url": "https://packagist.org/downloads/", 966 | "license": [ 967 | "BSD-3-Clause" 968 | ], 969 | "authors": [ 970 | { 971 | "name": "Sebastian Bergmann", 972 | "email": "sebastian@phpunit.de", 973 | "role": "lead" 974 | } 975 | ], 976 | "description": "Simple template engine.", 977 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 978 | "keywords": [ 979 | "template" 980 | ], 981 | "time": "2015-06-21T13:50:34+00:00" 982 | }, 983 | { 984 | "name": "phpunit/php-timer", 985 | "version": "dev-master", 986 | "source": { 987 | "type": "git", 988 | "url": "https://github.com/sebastianbergmann/php-timer.git", 989 | "reference": "37d2894f3650acccb6e57207e63eb9699c1a82a6" 990 | }, 991 | "dist": { 992 | "type": "zip", 993 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/37d2894f3650acccb6e57207e63eb9699c1a82a6", 994 | "reference": "37d2894f3650acccb6e57207e63eb9699c1a82a6", 995 | "shasum": "" 996 | }, 997 | "require": { 998 | "php": "^7.1" 999 | }, 1000 | "require-dev": { 1001 | "phpunit/phpunit": "^7.0" 1002 | }, 1003 | "type": "library", 1004 | "extra": { 1005 | "branch-alias": { 1006 | "dev-master": "2.1-dev" 1007 | } 1008 | }, 1009 | "autoload": { 1010 | "classmap": [ 1011 | "src/" 1012 | ] 1013 | }, 1014 | "notification-url": "https://packagist.org/downloads/", 1015 | "license": [ 1016 | "BSD-3-Clause" 1017 | ], 1018 | "authors": [ 1019 | { 1020 | "name": "Sebastian Bergmann", 1021 | "email": "sebastian@phpunit.de", 1022 | "role": "lead" 1023 | } 1024 | ], 1025 | "description": "Utility class for timing", 1026 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1027 | "keywords": [ 1028 | "timer" 1029 | ], 1030 | "time": "2019-07-02T07:42:03+00:00" 1031 | }, 1032 | { 1033 | "name": "phpunit/php-token-stream", 1034 | "version": "dev-master", 1035 | "source": { 1036 | "type": "git", 1037 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1038 | "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c" 1039 | }, 1040 | "dist": { 1041 | "type": "zip", 1042 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", 1043 | "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", 1044 | "shasum": "" 1045 | }, 1046 | "require": { 1047 | "ext-tokenizer": "*", 1048 | "php": "^7.1" 1049 | }, 1050 | "require-dev": { 1051 | "phpunit/phpunit": "^7.0" 1052 | }, 1053 | "type": "library", 1054 | "extra": { 1055 | "branch-alias": { 1056 | "dev-master": "3.0-dev" 1057 | } 1058 | }, 1059 | "autoload": { 1060 | "classmap": [ 1061 | "src/" 1062 | ] 1063 | }, 1064 | "notification-url": "https://packagist.org/downloads/", 1065 | "license": [ 1066 | "BSD-3-Clause" 1067 | ], 1068 | "authors": [ 1069 | { 1070 | "name": "Sebastian Bergmann", 1071 | "email": "sebastian@phpunit.de" 1072 | } 1073 | ], 1074 | "description": "Wrapper around PHP's tokenizer extension.", 1075 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1076 | "keywords": [ 1077 | "tokenizer" 1078 | ], 1079 | "time": "2019-07-08T05:24:54+00:00" 1080 | }, 1081 | { 1082 | "name": "phpunit/phpunit", 1083 | "version": "7.5.x-dev", 1084 | "source": { 1085 | "type": "git", 1086 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1087 | "reference": "7cf077177f6ae0152fd219d14958c05062bfec4d" 1088 | }, 1089 | "dist": { 1090 | "type": "zip", 1091 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7cf077177f6ae0152fd219d14958c05062bfec4d", 1092 | "reference": "7cf077177f6ae0152fd219d14958c05062bfec4d", 1093 | "shasum": "" 1094 | }, 1095 | "require": { 1096 | "doctrine/instantiator": "^1.1", 1097 | "ext-dom": "*", 1098 | "ext-json": "*", 1099 | "ext-libxml": "*", 1100 | "ext-mbstring": "*", 1101 | "ext-xml": "*", 1102 | "myclabs/deep-copy": "^1.7", 1103 | "phar-io/manifest": "^1.0.2", 1104 | "phar-io/version": "^2.0", 1105 | "php": "^7.1", 1106 | "phpspec/prophecy": "^1.7", 1107 | "phpunit/php-code-coverage": "^6.0.7", 1108 | "phpunit/php-file-iterator": "^2.0.1", 1109 | "phpunit/php-text-template": "^1.2.1", 1110 | "phpunit/php-timer": "^2.1", 1111 | "sebastian/comparator": "^3.0", 1112 | "sebastian/diff": "^3.0", 1113 | "sebastian/environment": "^4.0", 1114 | "sebastian/exporter": "^3.1", 1115 | "sebastian/global-state": "^2.0", 1116 | "sebastian/object-enumerator": "^3.0.3", 1117 | "sebastian/resource-operations": "^2.0", 1118 | "sebastian/version": "^2.0.1" 1119 | }, 1120 | "conflict": { 1121 | "phpunit/phpunit-mock-objects": "*" 1122 | }, 1123 | "require-dev": { 1124 | "ext-pdo": "*" 1125 | }, 1126 | "suggest": { 1127 | "ext-soap": "*", 1128 | "ext-xdebug": "*", 1129 | "phpunit/php-invoker": "^2.0" 1130 | }, 1131 | "bin": [ 1132 | "phpunit" 1133 | ], 1134 | "type": "library", 1135 | "extra": { 1136 | "branch-alias": { 1137 | "dev-master": "7.5-dev" 1138 | } 1139 | }, 1140 | "autoload": { 1141 | "classmap": [ 1142 | "src/" 1143 | ] 1144 | }, 1145 | "notification-url": "https://packagist.org/downloads/", 1146 | "license": [ 1147 | "BSD-3-Clause" 1148 | ], 1149 | "authors": [ 1150 | { 1151 | "name": "Sebastian Bergmann", 1152 | "email": "sebastian@phpunit.de", 1153 | "role": "lead" 1154 | } 1155 | ], 1156 | "description": "The PHP Unit Testing framework.", 1157 | "homepage": "https://phpunit.de/", 1158 | "keywords": [ 1159 | "phpunit", 1160 | "testing", 1161 | "xunit" 1162 | ], 1163 | "time": "2019-07-06T12:13:05+00:00" 1164 | }, 1165 | { 1166 | "name": "sebastian/code-unit-reverse-lookup", 1167 | "version": "dev-master", 1168 | "source": { 1169 | "type": "git", 1170 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1171 | "reference": "5e860800beea5ea4c8590df866338c09c20d3a48" 1172 | }, 1173 | "dist": { 1174 | "type": "zip", 1175 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e860800beea5ea4c8590df866338c09c20d3a48", 1176 | "reference": "5e860800beea5ea4c8590df866338c09c20d3a48", 1177 | "shasum": "" 1178 | }, 1179 | "require": { 1180 | "php": "^5.6 || ^7.0" 1181 | }, 1182 | "require-dev": { 1183 | "phpunit/phpunit": "^5.7 || ^6.0" 1184 | }, 1185 | "type": "library", 1186 | "extra": { 1187 | "branch-alias": { 1188 | "dev-master": "1.0.x-dev" 1189 | } 1190 | }, 1191 | "autoload": { 1192 | "classmap": [ 1193 | "src/" 1194 | ] 1195 | }, 1196 | "notification-url": "https://packagist.org/downloads/", 1197 | "license": [ 1198 | "BSD-3-Clause" 1199 | ], 1200 | "authors": [ 1201 | { 1202 | "name": "Sebastian Bergmann", 1203 | "email": "sebastian@phpunit.de" 1204 | } 1205 | ], 1206 | "description": "Looks up which function or method a line of code belongs to", 1207 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1208 | "time": "2019-07-02T07:44:03+00:00" 1209 | }, 1210 | { 1211 | "name": "sebastian/comparator", 1212 | "version": "dev-master", 1213 | "source": { 1214 | "type": "git", 1215 | "url": "https://github.com/sebastianbergmann/comparator.git", 1216 | "reference": "9a1267ac19ecd74163989bcb3e01c5c9587f9e3b" 1217 | }, 1218 | "dist": { 1219 | "type": "zip", 1220 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/9a1267ac19ecd74163989bcb3e01c5c9587f9e3b", 1221 | "reference": "9a1267ac19ecd74163989bcb3e01c5c9587f9e3b", 1222 | "shasum": "" 1223 | }, 1224 | "require": { 1225 | "php": "^7.1", 1226 | "sebastian/diff": "^3.0", 1227 | "sebastian/exporter": "^3.1" 1228 | }, 1229 | "require-dev": { 1230 | "phpunit/phpunit": "^7.1" 1231 | }, 1232 | "type": "library", 1233 | "extra": { 1234 | "branch-alias": { 1235 | "dev-master": "3.0-dev" 1236 | } 1237 | }, 1238 | "autoload": { 1239 | "classmap": [ 1240 | "src/" 1241 | ] 1242 | }, 1243 | "notification-url": "https://packagist.org/downloads/", 1244 | "license": [ 1245 | "BSD-3-Clause" 1246 | ], 1247 | "authors": [ 1248 | { 1249 | "name": "Jeff Welch", 1250 | "email": "whatthejeff@gmail.com" 1251 | }, 1252 | { 1253 | "name": "Volker Dusch", 1254 | "email": "github@wallbash.com" 1255 | }, 1256 | { 1257 | "name": "Bernhard Schussek", 1258 | "email": "bschussek@2bepublished.at" 1259 | }, 1260 | { 1261 | "name": "Sebastian Bergmann", 1262 | "email": "sebastian@phpunit.de" 1263 | } 1264 | ], 1265 | "description": "Provides the functionality to compare PHP values for equality", 1266 | "homepage": "https://github.com/sebastianbergmann/comparator", 1267 | "keywords": [ 1268 | "comparator", 1269 | "compare", 1270 | "equality" 1271 | ], 1272 | "time": "2019-07-02T07:45:15+00:00" 1273 | }, 1274 | { 1275 | "name": "sebastian/diff", 1276 | "version": "dev-master", 1277 | "source": { 1278 | "type": "git", 1279 | "url": "https://github.com/sebastianbergmann/diff.git", 1280 | "reference": "d7e7810940c78f3343420f76adf92dc437b7a557" 1281 | }, 1282 | "dist": { 1283 | "type": "zip", 1284 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/d7e7810940c78f3343420f76adf92dc437b7a557", 1285 | "reference": "d7e7810940c78f3343420f76adf92dc437b7a557", 1286 | "shasum": "" 1287 | }, 1288 | "require": { 1289 | "php": "^7.1" 1290 | }, 1291 | "require-dev": { 1292 | "phpunit/phpunit": "^7.5 || ^8.0", 1293 | "symfony/process": "^2 || ^3.3 || ^4" 1294 | }, 1295 | "type": "library", 1296 | "extra": { 1297 | "branch-alias": { 1298 | "dev-master": "3.0-dev" 1299 | } 1300 | }, 1301 | "autoload": { 1302 | "classmap": [ 1303 | "src/" 1304 | ] 1305 | }, 1306 | "notification-url": "https://packagist.org/downloads/", 1307 | "license": [ 1308 | "BSD-3-Clause" 1309 | ], 1310 | "authors": [ 1311 | { 1312 | "name": "Kore Nordmann", 1313 | "email": "mail@kore-nordmann.de" 1314 | }, 1315 | { 1316 | "name": "Sebastian Bergmann", 1317 | "email": "sebastian@phpunit.de" 1318 | } 1319 | ], 1320 | "description": "Diff implementation", 1321 | "homepage": "https://github.com/sebastianbergmann/diff", 1322 | "keywords": [ 1323 | "diff", 1324 | "udiff", 1325 | "unidiff", 1326 | "unified diff" 1327 | ], 1328 | "time": "2019-07-02T07:43:30+00:00" 1329 | }, 1330 | { 1331 | "name": "sebastian/environment", 1332 | "version": "dev-master", 1333 | "source": { 1334 | "type": "git", 1335 | "url": "https://github.com/sebastianbergmann/environment.git", 1336 | "reference": "1c91ab3fb351373cf86ead6006ea9daa8e4ce027" 1337 | }, 1338 | "dist": { 1339 | "type": "zip", 1340 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1c91ab3fb351373cf86ead6006ea9daa8e4ce027", 1341 | "reference": "1c91ab3fb351373cf86ead6006ea9daa8e4ce027", 1342 | "shasum": "" 1343 | }, 1344 | "require": { 1345 | "php": "^7.1" 1346 | }, 1347 | "require-dev": { 1348 | "phpunit/phpunit": "^7.5" 1349 | }, 1350 | "suggest": { 1351 | "ext-posix": "*" 1352 | }, 1353 | "type": "library", 1354 | "extra": { 1355 | "branch-alias": { 1356 | "dev-master": "4.2-dev" 1357 | } 1358 | }, 1359 | "autoload": { 1360 | "classmap": [ 1361 | "src/" 1362 | ] 1363 | }, 1364 | "notification-url": "https://packagist.org/downloads/", 1365 | "license": [ 1366 | "BSD-3-Clause" 1367 | ], 1368 | "authors": [ 1369 | { 1370 | "name": "Sebastian Bergmann", 1371 | "email": "sebastian@phpunit.de" 1372 | } 1373 | ], 1374 | "description": "Provides functionality to handle HHVM/PHP environments", 1375 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1376 | "keywords": [ 1377 | "Xdebug", 1378 | "environment", 1379 | "hhvm" 1380 | ], 1381 | "time": "2019-07-02T07:44:59+00:00" 1382 | }, 1383 | { 1384 | "name": "sebastian/exporter", 1385 | "version": "dev-master", 1386 | "source": { 1387 | "type": "git", 1388 | "url": "https://github.com/sebastianbergmann/exporter.git", 1389 | "reference": "97cc7aeb5bbc21a59df4e4e9e976831fa1b41fbe" 1390 | }, 1391 | "dist": { 1392 | "type": "zip", 1393 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/97cc7aeb5bbc21a59df4e4e9e976831fa1b41fbe", 1394 | "reference": "97cc7aeb5bbc21a59df4e4e9e976831fa1b41fbe", 1395 | "shasum": "" 1396 | }, 1397 | "require": { 1398 | "php": "^7.0", 1399 | "sebastian/recursion-context": "^3.0" 1400 | }, 1401 | "require-dev": { 1402 | "ext-mbstring": "*", 1403 | "phpunit/phpunit": "^6.0" 1404 | }, 1405 | "type": "library", 1406 | "extra": { 1407 | "branch-alias": { 1408 | "dev-master": "3.1.x-dev" 1409 | } 1410 | }, 1411 | "autoload": { 1412 | "classmap": [ 1413 | "src/" 1414 | ] 1415 | }, 1416 | "notification-url": "https://packagist.org/downloads/", 1417 | "license": [ 1418 | "BSD-3-Clause" 1419 | ], 1420 | "authors": [ 1421 | { 1422 | "name": "Jeff Welch", 1423 | "email": "whatthejeff@gmail.com" 1424 | }, 1425 | { 1426 | "name": "Volker Dusch", 1427 | "email": "github@wallbash.com" 1428 | }, 1429 | { 1430 | "name": "Bernhard Schussek", 1431 | "email": "bschussek@2bepublished.at" 1432 | }, 1433 | { 1434 | "name": "Sebastian Bergmann", 1435 | "email": "sebastian@phpunit.de" 1436 | }, 1437 | { 1438 | "name": "Adam Harvey", 1439 | "email": "aharvey@php.net" 1440 | } 1441 | ], 1442 | "description": "Provides the functionality to export PHP variables for visualization", 1443 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1444 | "keywords": [ 1445 | "export", 1446 | "exporter" 1447 | ], 1448 | "time": "2019-07-02T07:44:27+00:00" 1449 | }, 1450 | { 1451 | "name": "sebastian/global-state", 1452 | "version": "2.0.0", 1453 | "source": { 1454 | "type": "git", 1455 | "url": "https://github.com/sebastianbergmann/global-state.git", 1456 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" 1457 | }, 1458 | "dist": { 1459 | "type": "zip", 1460 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1461 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1462 | "shasum": "" 1463 | }, 1464 | "require": { 1465 | "php": "^7.0" 1466 | }, 1467 | "require-dev": { 1468 | "phpunit/phpunit": "^6.0" 1469 | }, 1470 | "suggest": { 1471 | "ext-uopz": "*" 1472 | }, 1473 | "type": "library", 1474 | "extra": { 1475 | "branch-alias": { 1476 | "dev-master": "2.0-dev" 1477 | } 1478 | }, 1479 | "autoload": { 1480 | "classmap": [ 1481 | "src/" 1482 | ] 1483 | }, 1484 | "notification-url": "https://packagist.org/downloads/", 1485 | "license": [ 1486 | "BSD-3-Clause" 1487 | ], 1488 | "authors": [ 1489 | { 1490 | "name": "Sebastian Bergmann", 1491 | "email": "sebastian@phpunit.de" 1492 | } 1493 | ], 1494 | "description": "Snapshotting of global state", 1495 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1496 | "keywords": [ 1497 | "global state" 1498 | ], 1499 | "time": "2017-04-27T15:39:26+00:00" 1500 | }, 1501 | { 1502 | "name": "sebastian/object-enumerator", 1503 | "version": "dev-master", 1504 | "source": { 1505 | "type": "git", 1506 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1507 | "reference": "63e5a3e0881ebf28c9fbb2a2e12b77d373850c12" 1508 | }, 1509 | "dist": { 1510 | "type": "zip", 1511 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/63e5a3e0881ebf28c9fbb2a2e12b77d373850c12", 1512 | "reference": "63e5a3e0881ebf28c9fbb2a2e12b77d373850c12", 1513 | "shasum": "" 1514 | }, 1515 | "require": { 1516 | "php": "^7.0", 1517 | "sebastian/object-reflector": "^1.1.1", 1518 | "sebastian/recursion-context": "^3.0" 1519 | }, 1520 | "require-dev": { 1521 | "phpunit/phpunit": "^6.0" 1522 | }, 1523 | "type": "library", 1524 | "extra": { 1525 | "branch-alias": { 1526 | "dev-master": "3.0.x-dev" 1527 | } 1528 | }, 1529 | "autoload": { 1530 | "classmap": [ 1531 | "src/" 1532 | ] 1533 | }, 1534 | "notification-url": "https://packagist.org/downloads/", 1535 | "license": [ 1536 | "BSD-3-Clause" 1537 | ], 1538 | "authors": [ 1539 | { 1540 | "name": "Sebastian Bergmann", 1541 | "email": "sebastian@phpunit.de" 1542 | } 1543 | ], 1544 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1545 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1546 | "time": "2019-07-02T07:43:46+00:00" 1547 | }, 1548 | { 1549 | "name": "sebastian/object-reflector", 1550 | "version": "dev-master", 1551 | "source": { 1552 | "type": "git", 1553 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1554 | "reference": "3053ae3e6286fdf98769f18ec10894dbc6260a34" 1555 | }, 1556 | "dist": { 1557 | "type": "zip", 1558 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3053ae3e6286fdf98769f18ec10894dbc6260a34", 1559 | "reference": "3053ae3e6286fdf98769f18ec10894dbc6260a34", 1560 | "shasum": "" 1561 | }, 1562 | "require": { 1563 | "php": "^7.0" 1564 | }, 1565 | "require-dev": { 1566 | "phpunit/phpunit": "^6.0" 1567 | }, 1568 | "type": "library", 1569 | "extra": { 1570 | "branch-alias": { 1571 | "dev-master": "1.1-dev" 1572 | } 1573 | }, 1574 | "autoload": { 1575 | "classmap": [ 1576 | "src/" 1577 | ] 1578 | }, 1579 | "notification-url": "https://packagist.org/downloads/", 1580 | "license": [ 1581 | "BSD-3-Clause" 1582 | ], 1583 | "authors": [ 1584 | { 1585 | "name": "Sebastian Bergmann", 1586 | "email": "sebastian@phpunit.de" 1587 | } 1588 | ], 1589 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1590 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1591 | "time": "2019-07-02T07:44:36+00:00" 1592 | }, 1593 | { 1594 | "name": "sebastian/recursion-context", 1595 | "version": "dev-master", 1596 | "source": { 1597 | "type": "git", 1598 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1599 | "reference": "a58220ae18565f6004bbe15321efc4470bfe02fd" 1600 | }, 1601 | "dist": { 1602 | "type": "zip", 1603 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/a58220ae18565f6004bbe15321efc4470bfe02fd", 1604 | "reference": "a58220ae18565f6004bbe15321efc4470bfe02fd", 1605 | "shasum": "" 1606 | }, 1607 | "require": { 1608 | "php": "^7.0" 1609 | }, 1610 | "require-dev": { 1611 | "phpunit/phpunit": "^6.0" 1612 | }, 1613 | "type": "library", 1614 | "extra": { 1615 | "branch-alias": { 1616 | "dev-master": "3.0.x-dev" 1617 | } 1618 | }, 1619 | "autoload": { 1620 | "classmap": [ 1621 | "src/" 1622 | ] 1623 | }, 1624 | "notification-url": "https://packagist.org/downloads/", 1625 | "license": [ 1626 | "BSD-3-Clause" 1627 | ], 1628 | "authors": [ 1629 | { 1630 | "name": "Jeff Welch", 1631 | "email": "whatthejeff@gmail.com" 1632 | }, 1633 | { 1634 | "name": "Sebastian Bergmann", 1635 | "email": "sebastian@phpunit.de" 1636 | }, 1637 | { 1638 | "name": "Adam Harvey", 1639 | "email": "aharvey@php.net" 1640 | } 1641 | ], 1642 | "description": "Provides functionality to recursively process PHP variables", 1643 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1644 | "time": "2019-07-02T07:43:54+00:00" 1645 | }, 1646 | { 1647 | "name": "sebastian/resource-operations", 1648 | "version": "dev-master", 1649 | "source": { 1650 | "type": "git", 1651 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1652 | "reference": "d67fc89d3107c396d161411b620619f3e7a7c270" 1653 | }, 1654 | "dist": { 1655 | "type": "zip", 1656 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/d67fc89d3107c396d161411b620619f3e7a7c270", 1657 | "reference": "d67fc89d3107c396d161411b620619f3e7a7c270", 1658 | "shasum": "" 1659 | }, 1660 | "require": { 1661 | "php": "^7.1" 1662 | }, 1663 | "type": "library", 1664 | "extra": { 1665 | "branch-alias": { 1666 | "dev-master": "2.0-dev" 1667 | } 1668 | }, 1669 | "autoload": { 1670 | "classmap": [ 1671 | "src/" 1672 | ] 1673 | }, 1674 | "notification-url": "https://packagist.org/downloads/", 1675 | "license": [ 1676 | "BSD-3-Clause" 1677 | ], 1678 | "authors": [ 1679 | { 1680 | "name": "Sebastian Bergmann", 1681 | "email": "sebastian@phpunit.de" 1682 | } 1683 | ], 1684 | "description": "Provides a list of PHP built-in functions that operate on resources", 1685 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1686 | "time": "2019-07-02T07:42:50+00:00" 1687 | }, 1688 | { 1689 | "name": "sebastian/version", 1690 | "version": "2.0.1", 1691 | "source": { 1692 | "type": "git", 1693 | "url": "https://github.com/sebastianbergmann/version.git", 1694 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1695 | }, 1696 | "dist": { 1697 | "type": "zip", 1698 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1699 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1700 | "shasum": "" 1701 | }, 1702 | "require": { 1703 | "php": ">=5.6" 1704 | }, 1705 | "type": "library", 1706 | "extra": { 1707 | "branch-alias": { 1708 | "dev-master": "2.0.x-dev" 1709 | } 1710 | }, 1711 | "autoload": { 1712 | "classmap": [ 1713 | "src/" 1714 | ] 1715 | }, 1716 | "notification-url": "https://packagist.org/downloads/", 1717 | "license": [ 1718 | "BSD-3-Clause" 1719 | ], 1720 | "authors": [ 1721 | { 1722 | "name": "Sebastian Bergmann", 1723 | "email": "sebastian@phpunit.de", 1724 | "role": "lead" 1725 | } 1726 | ], 1727 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1728 | "homepage": "https://github.com/sebastianbergmann/version", 1729 | "time": "2016-10-03T07:35:21+00:00" 1730 | }, 1731 | { 1732 | "name": "symfony/polyfill-ctype", 1733 | "version": "dev-master", 1734 | "source": { 1735 | "type": "git", 1736 | "url": "https://github.com/symfony/polyfill-ctype.git", 1737 | "reference": "82ebae02209c21113908c229e9883c419720738a" 1738 | }, 1739 | "dist": { 1740 | "type": "zip", 1741 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", 1742 | "reference": "82ebae02209c21113908c229e9883c419720738a", 1743 | "shasum": "" 1744 | }, 1745 | "require": { 1746 | "php": ">=5.3.3" 1747 | }, 1748 | "suggest": { 1749 | "ext-ctype": "For best performance" 1750 | }, 1751 | "type": "library", 1752 | "extra": { 1753 | "branch-alias": { 1754 | "dev-master": "1.11-dev" 1755 | } 1756 | }, 1757 | "autoload": { 1758 | "psr-4": { 1759 | "Symfony\\Polyfill\\Ctype\\": "" 1760 | }, 1761 | "files": [ 1762 | "bootstrap.php" 1763 | ] 1764 | }, 1765 | "notification-url": "https://packagist.org/downloads/", 1766 | "license": [ 1767 | "MIT" 1768 | ], 1769 | "authors": [ 1770 | { 1771 | "name": "Symfony Community", 1772 | "homepage": "https://symfony.com/contributors" 1773 | }, 1774 | { 1775 | "name": "Gert de Pagter", 1776 | "email": "BackEndTea@gmail.com" 1777 | } 1778 | ], 1779 | "description": "Symfony polyfill for ctype functions", 1780 | "homepage": "https://symfony.com", 1781 | "keywords": [ 1782 | "compatibility", 1783 | "ctype", 1784 | "polyfill", 1785 | "portable" 1786 | ], 1787 | "time": "2019-02-06T07:57:58+00:00" 1788 | }, 1789 | { 1790 | "name": "theseer/tokenizer", 1791 | "version": "1.1.3", 1792 | "source": { 1793 | "type": "git", 1794 | "url": "https://github.com/theseer/tokenizer.git", 1795 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" 1796 | }, 1797 | "dist": { 1798 | "type": "zip", 1799 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 1800 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 1801 | "shasum": "" 1802 | }, 1803 | "require": { 1804 | "ext-dom": "*", 1805 | "ext-tokenizer": "*", 1806 | "ext-xmlwriter": "*", 1807 | "php": "^7.0" 1808 | }, 1809 | "type": "library", 1810 | "autoload": { 1811 | "classmap": [ 1812 | "src/" 1813 | ] 1814 | }, 1815 | "notification-url": "https://packagist.org/downloads/", 1816 | "license": [ 1817 | "BSD-3-Clause" 1818 | ], 1819 | "authors": [ 1820 | { 1821 | "name": "Arne Blankerts", 1822 | "email": "arne@blankerts.de", 1823 | "role": "Developer" 1824 | } 1825 | ], 1826 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1827 | "time": "2019-06-13T22:48:21+00:00" 1828 | }, 1829 | { 1830 | "name": "webmozart/assert", 1831 | "version": "1.4.0", 1832 | "source": { 1833 | "type": "git", 1834 | "url": "https://github.com/webmozart/assert.git", 1835 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" 1836 | }, 1837 | "dist": { 1838 | "type": "zip", 1839 | "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", 1840 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", 1841 | "shasum": "" 1842 | }, 1843 | "require": { 1844 | "php": "^5.3.3 || ^7.0", 1845 | "symfony/polyfill-ctype": "^1.8" 1846 | }, 1847 | "require-dev": { 1848 | "phpunit/phpunit": "^4.6", 1849 | "sebastian/version": "^1.0.1" 1850 | }, 1851 | "type": "library", 1852 | "extra": { 1853 | "branch-alias": { 1854 | "dev-master": "1.3-dev" 1855 | } 1856 | }, 1857 | "autoload": { 1858 | "psr-4": { 1859 | "Webmozart\\Assert\\": "src/" 1860 | } 1861 | }, 1862 | "notification-url": "https://packagist.org/downloads/", 1863 | "license": [ 1864 | "MIT" 1865 | ], 1866 | "authors": [ 1867 | { 1868 | "name": "Bernhard Schussek", 1869 | "email": "bschussek@gmail.com" 1870 | } 1871 | ], 1872 | "description": "Assertions to validate method input/output with nice error messages.", 1873 | "keywords": [ 1874 | "assert", 1875 | "check", 1876 | "validate" 1877 | ], 1878 | "time": "2018-12-25T11:19:39+00:00" 1879 | } 1880 | ], 1881 | "aliases": [], 1882 | "minimum-stability": "dev", 1883 | "stability-flags": [], 1884 | "prefer-stable": false, 1885 | "prefer-lowest": false, 1886 | "platform": { 1887 | "php": ">= 5.4", 1888 | "ext-mbstring": "*", 1889 | "ext-json": "*", 1890 | "ext-simplexml": "*" 1891 | }, 1892 | "platform-dev": [] 1893 | } 1894 | --------------------------------------------------------------------------------