diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..af78f761 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: php +php: + - '5.4' + - '5.5' + - '5.6' + - '7' +script: cd test-cases && phpunit --bootstrap bootstrap.php diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..89f32937 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,102 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## 1.3.0 - 2016-08-03 +### Added +- Travis support +- PHPUnit XML configuration file +- Change log file +- Contribution guidelines file +- Credits file +- Added support for MWS Auth Token, which can be set for each store in the config file. +- Added methods for getting the last response code, error message, and error response. +- Added support for the Merchant Fulfillment API with three new classes. +- Added support for the Recommendations API with one new class. +- Added support for the Subscriptions API with three new classes. +- Added support for the Finance API two new classes. +- Added four new Inbound classes relating to preorders, transport, and item prep instructions. +- The marketplace can now be specified in the Order List class, Fulfillment Order class, and all Product classes. +- New response fields in the Feed class: `StartedProcessingDate` and `CompletedProcessingDate` +- New response fields in the Order class: `IsBusinessOrder`, `PurchaseOrderNumber`, `IsPrime`, and `IsPremiumOrder` +- New response fields in the Order Item List class: `BuyerCustomizedInfo`, `PointsGranted`, and `PriceDesignation` +- Added a method for getting the order ID from the Order Item List class. +- New parameter in the Order List class: `TFMShipmentStatus` +- Added a method for getting the raw report data from the Report class. +- New response field in the Report List class: `AcknowledgedDate` +- New response fields in the Fulfillment Order class: `MarketplaceId`, `DeliveryWindow`, `FulfillmentAction`, `CODSettings`, `PerUnitPrice`, and `PerUnitTax`. +- New parameters in the Fulfillment Order Creator class: `MarketplaceId`, `FulfillmentAction`, `CODSettings`, and `DeliveryWindow`. The method for setting items now also has `PerUnitPrice` and `PerUnitTax`. +- New method in the Fulfillment Order Creator class for updating orders. +- New response fields in the Fulfillment Order List class: `MarketplaceId`, `DeliveryWindow`, `FulfillmentAction`, and `CODSettings`. +- New options in the Fulfillment Preview class: `IncludeCODFulfillmentPreview` and `IncludeDeliveryWindows`. +- New response fields in the Fulfillment Preview class: `ShippingSpeedCategory`, `IsFulfillable`, `IsCODCapable`, `MarketplaceId`, and `ScheduledDeliveryInfo`. +- New method in the Product Info class for getting lowest-priced offers. +- The Product class now keeps the identifier used to search for an item under the key `Request`. +- New methods in the Shipment class for setting parameters previously restricted to use of `usePlan`. +- New parameter in the Shipment class: `ShipmentName`. The method for setting items now also supports `PrepDetailsList` and `ReleaseDate` for each item. +- New response fields in the Shipment Item List class: `PrepDetailsList` and `ReleaseDate` +- New response field in the Shipment List class: `ConfirmedNeedByDate` +- New parameters in the Shipment Planner class: `ShipToCountryCode` and `ShipToCountrySubdivisionCode`. The method for setting items now also supports `ASIN` and `PrepDetailsList` for each item. +- New response field in the Shipment Planner class: `PrepDetailsList` +- Added support for new styles of token responses used by some classes. + +### Changed +- Some tests that tried to load the normal configuration file now properly load test configuration. +- Corrected many small mistakes in documentation. +- The `setShowSalesChannel` method in the Report class now properly sets the parameter. +- The Service URL setting now works with or without a slash at the end. +- Changed all private methods and properties to protected. +- Updated the Composer file to allow for newer PHP versions. +- Fixed the spelling of `StateOrProvinceCode` throughout the Outbound and Inbound classes. +- The `genTime` method now supports Unix timestamps, though some methods that use `genTime` still do not. +- Updated the name of the `CompletedProcessingDate` field in the Report Request List class to `CompletedDate`. +- Deprecated `getDateProcessingCompleted` in favor of `getDateCompleted`. +- Updated the name of the `ShipServiceLevelCategory` field in the Order class to `ShipmentServiceLevelCategory`. +- Deprecated `getShipServiceLevelCategory` in favor of `getShipmentServiceLevelCategory`. +- Deprecated `setFulfillmentMethod` in the Fulfillment Order Creator class. +- Deprecated `setMethodFilter` in the Fulfillment Order List class. +- The Product Info class now properly gets all relationships. +- The Shipment class no longer sets the address when using `usePlan` and correctly sets other parameters. +- Fixed a loop caused by an empty response to actions that use tokens. + +### Removed +- Removed all of the old leftover test XML files from the mock folder +- Removed old environment config lines from the test config file + +## 1.2.0 - 2016-03-10 +### Added +- The store name can now be omitted when initiating objects if there is only one store is set in the config file. +- Added support for four relatively-new fields returned for Orders: `CbaDisplayableShippingLabel`, `ShippedByAmazonTFM`, `TFMShipmentStatus`, and `OrderType`. +- Each store in the config file can have its own `serviceUrl`, which will override the normal service URL. + +### Changed +- Log messages now display time using the 24 hour format, rather than 12 hour. + +### Fixed +- Inventory lists no longer cause an error if detailed information is not given. +- Logging function no longer gives an error when PHP is in strict mode. +- Removed bad include paths from NetBeans project settings. +- Product class no longer gives an error when PHP is in strict mode. +- Product Info class now uses the correct identifier parameters when fetching categories. +- Product Info class now correctly gets child relationship data. + +### Removed +- Removed the obsolete `checkResponse` method from the Feed class. + +## 1.1.0 - 2014-05-06 +### Added +- Raw responses are stored for debugging purposes and can be accessed with getLastResponse() or getRawResponses() +- Created a folder for example scripts and added some examples to the readme +- Updated the Orders API to the 2013-09-01 version, which adds Earliest/Latest Ship Date and Delivery Date to returned order data + +### Changed +- Feeds now allow for direct string input rather than relying entirely on files +- Amazon-defined constants, such as API version numbers and throttle times, have been moved to a separate file since users shouldn't have to worry about them. Users who already have a config file should redo them. + +### Fixed +- HTTP 100 Continue responses are properly handled + +## 1.0.0 - 2014-02-12 +### Added +- Core class +- Classes for eight APIs: Feeds, Fulfillment Inbound, Fulfillment Inventory, Fulfillment Outbound, Orders, Products, Reports, and Sellers diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e69de29b..117ba55f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing +##General +All pull requests should target the master branch. Commits should not have different code changes mixed together and should have descriptive messages. + +##Project Scope +The goal of this project is to provide a library with which the average merchant can communicate with Amazon's MWS services without needing to learn the complex language of the API. When contributing, think about whether or not the contribution is something that the average Amazon merchant would need to intract with Amazon. + +Code for handling the merchant's data, such as for generating feeds or data crunching, falls outside of the library's intended scope and, while useful, is best left to separate projects. + +##Code Guidelines +The library is written using a custom style and does not follow any particular standard. For the sake of cohesion, changes to the code should be written in this same style. Please do not make changes to the style of the code. + +Any new changes should fit within the previously-mentioned goal of the project. New public methods and classes should have names that are easy to understand and use without needing to consult the API's documentation. Try to follow the trend of similar existing functions, such as how methods that send requests to get information from Amazon usually have names that start with "fetch." + +New methods should have phpdocs explaining how to use them and how they will affect the options sent in the next request. New classes should have phpdocs explaining their purpose and the workflow for using them. If the class is one that sends requests to Amazon, the documentation should indicate which Amazon actions it can perform and which of its methods are required before a request can be sent. Check the phpdocs on existing classes for examples. diff --git a/CREDITS b/CREDITS new file mode 100644 index 00000000..e7831257 --- /dev/null +++ b/CREDITS @@ -0,0 +1 @@ +The phpAmazonMWS library was designed and written by Thomas Hernandez (peardian at gmail) for the CPI Group. diff --git a/README.md b/README.md index 13ad8358..a1f64302 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ phpAmazonMWS ============ +[![Build Status](https://travis-ci.org/CPIGroup/phpAmazonMWS.svg?branch=stable)](https://travis-ci.org/CPIGroup/phpAmazonMWS) + A library to connect to Amazon's Merchant Web Services (MWS) in an object-oriented manner, with a focus on intuitive usage. This is __NOT__ for Amazon Web Services (AWS) - Cloud Computing Services. diff --git a/amazon-config.default.php b/amazon-config.default.php index 8f1874a9..08f93dab 100644 --- a/amazon-config.default.php +++ b/amazon-config.default.php @@ -22,6 +22,7 @@ $store['YourAmazonStore']['keyId'] = ''; //Access Key ID $store['YourAmazonStore']['secretKey'] = ''; //Secret Access Key for this store $store['YourAmazonStore']['serviceUrl'] = ''; //optional override for Service URL +$store['YourAmazonStore']['MWSAuthToken'] = ''; //token needed for web apps and third-party developers //Service URL Base //Current setting is United States diff --git a/composer.json b/composer.json index 78a06bd6..10c0a2dd 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "keywords": ["API", "Amazon", "PHP"], "require":{ - "php": "~5.4", + "php": ">=5.4", "ext-curl": "*" }, "require-dev": { diff --git a/environment.php b/environment.php index e221ff3f..800ef873 100644 --- a/environment.php +++ b/environment.php @@ -28,13 +28,17 @@ //Version numbers for cores $AMAZON_VERSION_FEEDS = '2009-01-01'; +$AMAZON_VERSION_FINANCE = '2015-05-01'; $AMAZON_VERSION_INBOUND = '2010-10-01'; $AMAZON_VERSION_INVENTORY = '2010-10-01'; +$AMAZON_VERSION_MERCHANT = '2015-06-01'; $AMAZON_VERSION_ORDERS = '2013-09-01'; $AMAZON_VERSION_OUTBOUND = '2010-10-01'; $AMAZON_VERSION_PRODUCTS = '2011-10-01'; +$AMAZON_VERSION_RECOMMEND = '2013-04-01'; $AMAZON_VERSION_REPORTS = '2009-01-01'; $AMAZON_VERSION_SELLERS = '2011-07-01'; +$AMAZON_VERSION_SUBSCRIBE = '2013-07-01'; //Amazon Throttle Values in seconds //Fetching Orders @@ -82,11 +86,23 @@ //Submitting a Feed $THROTTLE_LIMIT_FEEDSUBMIT = 15; $THROTTLE_TIME_FEEDSUBMIT = 120; -//Getting a Feed +//Fetching a Feed List $THROTTLE_LIMIT_FEEDLIST = 10; $THROTTLE_TIME_FEEDLIST = 45; //Getting a Feed $THROTTLE_LIMIT_FEEDRESULT = 15; $THROTTLE_TIME_FEEDRESULT = 60; +//Merchant Fulfillments +$THROTTLE_LIMIT_MERCHANT = 10; +$THROTTLE_TIME_MERCHANT = 1; +//Subscriptions +$THROTTLE_LIMIT_SUBSCRIBE = 25; +$THROTTLE_TIME_SUBSCRIBE = 1; +//Recommendations +$THROTTLE_LIMIT_RECOMMEND = 8; +$THROTTLE_TIME_RECOMMEND = 2; +//Recommendations +$THROTTLE_LIMIT_FINANCE = 30; +$THROTTLE_TIME_FINANCE = 2; ?> diff --git a/includes/classes/AmazonCore.php b/includes/classes/AmazonCore.php index 42d0b00b..3cc301b3 100644 --- a/includes/classes/AmazonCore.php +++ b/includes/classes/AmazonCore.php @@ -190,10 +190,10 @@ public function setMock($b = true,$files = null){ * including the name and path of the file involved. For retrieving response * codes, see fetchMockResponse. * @param boolean $load [optional]
Set this to FALSE to prevent the - * method from loading the file's contents into a SimpleXMLObject. This is + * method from loading the file's contents into a SimpleXMLElement. This is * for when the contents of the file are not in XML format, or if you simply * want to retrieve the raw string of the file.
- * @return SimpleXMLObject|string|booleanA SimpleXMLObject holding the + * @return SimpleXMLElement|string|boolean
A SimpleXMLElement holding the * contents of the file, or a string of said contents if $load is set to * FALSE. The return will be FALSE if the file cannot be * fetched for any reason.
@@ -362,7 +362,7 @@ public function setConfig($path){ $this->config = $path; $this->setLogPath($logpath); if (isset($AMAZON_SERVICE_URL)) { - $this->urlbase = $AMAZON_SERVICE_URL; + $this->urlbase = rtrim($AMAZON_SERVICE_URL, '/') . '/'; } } else { throw new Exception("Config file does not exist or cannot be read! ($path)"); @@ -431,6 +431,9 @@ public function setStore($s=null){ if (!empty($store[$s]['serviceUrl'])) { $this->urlbase = $store[$s]['serviceUrl']; } + if (!empty($store[$s]['MWSAuthToken'])) { + $this->options['MWSAuthToken'] = $store[$s]['MWSAuthToken']; + } } else { $this->log("Store $s does not exist!",'Warning'); @@ -543,17 +546,22 @@ public function getOptions(){ * The string given is passed through strtotime before being used. The * value returned is actually two minutes early, to prevent it from tripping up * Amazon. If no time is given, the current time is used. - * @param string $time [optional]The time to use. Since this value is + * @param string|int $time [optional]
The time to use. Since any string values are * passed through strtotime first, values such as "-1 hour" are fine. + * Unix timestamps are also allowed. Purely numeric values are treated as unix timestamps. * Defaults to the current time.
* @return string Unix timestamp of the time, minus 2 minutes. + * @throws InvalidArgumentException */ protected function genTime($time=false){ if (!$time){ $time = time(); - } else { + } else if (is_numeric($time)) { + $time = (int)$time; + } else if (is_string($time)) { $time = strtotime($time); - + } else { + throw new InvalidArgumentException('Invalid time input given'); } return date('Y-m-d\TH:i:sO',$time-120); @@ -646,6 +654,69 @@ public function getRawResponses() { return false; } } + + /** + * Gives the response code from the last response. + * This data can also be found in the array given by getLastResponse. + * @return string|int standard REST response code (200, 404, etc.) or NULL if no response + * @see getLastResponse + */ + public function getLastResponseCode() { + $last = $this->getLastResponse(); + if (!empty($last['code'])) { + return $last['code']; + } + } + + /** + * Gives the last response with an error code. + * This may or may not be the same as the last response if multiple requests were made. + * @return array associative array of HTTP response or NULL if no error response yet + * @see getLastResponse + */ + public function getLastErrorResponse() { + if (!empty($this->rawResponses)) { + foreach (array_reverse($this->rawResponses) as $x) { + if (isset($x['error'])) { + return $x; + } + } + } + } + + /** + * Gives the Amazon error code from the last error response. + * The error code uses words rather than numbers. (Ex: "InvalidParameterValue") + * This data can also be found in the XML body given by getLastErrorResponse. + * @return string Amazon error code or NULL if not set yet or no error response yet + * @see getLastErrorResponse + */ + public function getLastErrorCode() { + $last = $this->getLastErrorResponse(); + if (!empty($last['body'])) { + $xml = simplexml_load_string($last['body']); + if (isset($xml->Error->Code)) { + return $xml->Error->Code; + } + } + } + + /** + * Gives the error message from the last error response. + * Not all error responses will have error messages. + * This data can also be found in the XML body given by getLastErrorResponse. + * @return string Amazon error code or NULL if not set yet or no error response yet + * @see getLastErrorResponse + */ + public function getLastErrorMessage() { + $last = $this->getLastErrorResponse(); + if (!empty($last['body'])) { + $xml = simplexml_load_string($last['body']); + if (isset($xml->Error->Message)) { + return $xml->Error->Message; + } + } + } /** * Sleeps for the throttle time and records to the log. @@ -659,14 +730,11 @@ protected function sleep(){ /** * Checks for a token and changes the proper options - * @param SimpleXMLObject $xmlresponse data
+ * @param SimpleXMLElement $xmlresponse data
* @return boolean FALSE if no XML data */ protected function checkToken($xml){ - if (!$xml){ - return false; - } - if ($xml->NextToken){ + if ($xml && $xml->NextToken && (string)$xml->HasNext != 'false' && (string)$xml->MoreResultsAvailable != 'false'){ $this->tokenFlag = true; $this->options['NextToken'] = (string)$xml->NextToken; } else { @@ -768,7 +836,8 @@ function fetchURL ($url, $param) { */ protected function _urlencode($value) { return rawurlencode($value); - return str_replace('%7E', '~', rawurlencode($value)); + //Amazon suggests doing this, but it seems to break things rather than fix them: + //return str_replace('%7E', '~', rawurlencode($value)); } /** diff --git a/includes/classes/AmazonFeed.php b/includes/classes/AmazonFeed.php index 34e3b52a..f45e7e68 100644 --- a/includes/classes/AmazonFeed.php +++ b/includes/classes/AmazonFeed.php @@ -25,9 +25,9 @@ * the response from Amazon can be viewed with getResponse. */ class AmazonFeed extends AmazonFeedsCore{ - private $response; - private $feedContent; - private $feedMD5; + protected $response; + protected $feedContent; + protected $feedMD5; /** * AmazonFeed submits a Feed to Amazon. @@ -80,7 +80,7 @@ public function setFeedContent($s){ * * This method loads the contents of a file to send as the feed. This * parameter is required in order to submit a feed to Amazon. - * @param string $urlThe path to a file you want to use. + * @param string $path
The path to a file you want to use. * It can be relative or absolute.
*/ public function loadFeedFile($path){ @@ -113,40 +113,43 @@ public function setFeedType($s){ } /* * List of valid Feed Types: - * XML Feeds: + * Product & Inventory Feeds (XML): * Product Feed ~ _POST_PRODUCT_DATA_ - * Relationships Feed ~ _POST_PRODUCT_RELATIONSHIP_DATA_ - * Single Format Item Feed ~ _POST_ITEM_DATA_ - * Shipping Override Feed ~ _POST_PRODUCT_OVERRIDES_DATA_ - * Product Images Feed ~ _POST_PRODUCT_IMAGE_DATA_ - * Pricing Feed ~ _POST_PRODUCT_PRICING_DATA_ * Inventory Feed ~ _POST_INVENTORY_AVAILABILITY_DATA_ + * Overrides Feed ~ _POST_PRODUCT_OVERRIDES_DATA_ + * Pricing Feed ~ _POST_PRODUCT_PRICING_DATA_ + * Product Images Feed ~ _POST_PRODUCT_IMAGE_DATA_ + * Relationships Feed ~ _POST_PRODUCT_RELATIONSHIP_DATA_ + * ACES 3.0 Data (Automotive Part Finder) Feed ~ _POST_STD_ACES_DATA_ + * Product & Inventory Feeds (Tab Delimited): + * Flat File Inventory Loader Feed ~ _POST_FLAT_FILE_INVLOADER_DATA_ + * Flat File Listings Feed ~ _POST_FLAT_FILE_LISTINGS_DATA_ + * Flat File Book Loader File ~ _POST_FLAT_FILE_BOOKLOADER_DATA_ + * Flat File Music Loader File ~ _POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_ + * Flat File Video Loader File ~ _POST_FLAT_FILE_LISTINGS_DATA_ + * Flat File Price and Quantity Update File ~ _POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_ + * Product & Inventory Feeds (Other): + * UIEE Inventory File ~ _POST_UIEE_BOOKLOADER_DATA_ + * Order Feeds (XML): * Order Acknowledgement Feed ~ _POST_ORDER_ACKNOWLEDGEMENT_DATA_ - * Order Fulfillment Feed ~ _POST_ORDER_FULFILLMENT_DATA_ - * FBA Shipment Injection Fulfillment Feed~ _POST_FULFILLMENT_ORDER_REQUEST_DATA_ - * FBA Shipment Injection ~ _POST_FULFILLMENT_ORDER_CANCELLATION_ - * Cancellation Feed ~ _REQUEST_DATA_ * Order Adjustment Feed ~ _POST_PAYMENT_ADJUSTMENT_DATA_ + * Order Fulfillment Feed ~ _POST_ORDER_FULFILLMENT_DATA_ * Invoice Confirmation Feed ~ _POST_INVOICE_CONFIRMATION_DATA_ - * Tab Delimited Feeds: - * Flat File Listings Feed ~ _POST_FLAT_FILE_LISTINGS_DATA_ + * Order Feeds (Tab Delimited): * Flat File Order Acknowledgement Feed ~ _POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_ - * Flat File Order Fulfillment Feed ~ _POST_FLAT_FILE_FULFILLMENT_DATA_ - * Flat File FBA Shipment Injection Fulfillment Feed ~ _POST_FLAT_FILE_FULFILLMENT_ORDER_REQUEST_DATA_ - * Flat File FBA Shipment Injection Cancellation Feed ~ _POST_FLAT_FILE_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_ - * FBA Flat File Create Inbound Shipment Feed ~ _POST_FLAT_FILE_FBA_CREATE_INBOUND_SHIPMENT_ - * FBA Flat File Update Inbound Shipment Feed ~ _POST_FLAT_FILE_FBA_UPDATE_INBOUND_SHIPMENT_ - * FBA Flat File Shipment Notification Feed ~ _POST_FLAT_FILE_FBA_SHIPMENT_NOTIFICATION_FEED_ * Flat File Order Adjustment Feed ~ _POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_ + * Flat File Order Fulfillment Feed ~ _POST_FLAT_FILE_FULFILLMENT_DATA_ * Flat File Invoice Confirmation Feed ~ _POST_FLAT_FILE_INVOICE_CONFIRMATION_DATA_ - * Flat File Inventory Loader Feed ~ _POST_FLAT_FILE_INVLOADER_DATA_ - * Flat File Music Loader File ~ _POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA_ - * Flat File Book Loader File ~ _POST_FLAT_FILE_BOOKLOADER_DATA_ - * Flat File Video Loader File ~ _POST_FLAT_FILE_LISTINGS_DATA_ - * Flat File Price and Quantity Update File ~ _POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_ - * Product Ads Flat File Feed ~ _POST_FLAT_FILE_SHOPZILLA_DATA_ - * Universal Information Exchange Environment (UIEE) Feeds: - * UIEE Inventory File ~ _POST_UIEE_BOOKLOADER_DATA_ + * Fulfillment By Amazon Feeds (XML): + * FBA Fulfillment Order Feed ~ _POST_FULFILLMENT_ORDER_REQUEST_DATA_ + * FBA Fulfillment Order Cancellation Request ~ _POST_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_ + * FBA Inbound Shipment Carton Information Feed ~ _POST_FBA_INBOUND_CARTON_CONTENTS_ + * Fulfillment By Amazon Feeds (Tab Delimited): + * Flat File FBA Fulfillment Order Feed ~ _POST_FLAT_FILE_FULFILLMENT_ORDER_REQUEST_DATA_ + * Flat File FBA Fulfillment Order Cancellation Feed ~ _POST_FLAT_FILE_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_ + * Flat File FBA Create Inbound Shipment Plan Feed ~ _POST_FLAT_FILE_FBA_CREATE_INBOUND_PLAN_ + * Flat File FBA Update Inbound Shipment Plan Feed ~ _POST_FLAT_FILE_FBA_UPDATE_INBOUND_PLAN_ + * Flat File FBA Create Removal Feed ~ _POST_FLAT_FILE_FBA_CREATE_REMOVAL_ */ } @@ -274,7 +277,7 @@ public function submitFeed(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -312,7 +315,7 @@ protected function genHeader(){ *A list of Feed Statuses, or a single status string.
- * Valid values are "_SUBMITTED_", "_IN_PROGRESS_", "_CANCELLED_", and "_DONE_".
When set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchFeedSubmissions($r = true){ @@ -341,7 +342,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -362,6 +363,13 @@ protected function parseXML($xml){ $this->feedList[$i]['FeedType'] = (string)$x->FeedType; $this->feedList[$i]['SubmittedDate'] = (string)$x->SubmittedDate; $this->feedList[$i]['FeedProcessingStatus'] = (string)$x->FeedProcessingStatus; + //this fields are not always returned + if (isset($x->StartedProcessingDate)) { + $this->feedList[$i]['StartedProcessingDate'] = (string)$x->StartedProcessingDate; + } + if (isset($x->CompletedProcessingDate)) { + $this->feedList[$i]['CompletedProcessingDate'] = (string)$x->CompletedProcessingDate; + } $this->index++; } @@ -538,6 +546,38 @@ public function getFeedStatus($i = 0){ } } + /** + * Returns the date that the specified entry started being processed. + * + * This method will return FALSE if the list has not yet been filled. + * The time will be in the ISO8601 date format. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getDateStarted($i = 0){ + if (is_numeric($i) && isset($this->feedList) && is_array($this->feedList) && isset($this->feedList[$i]['StartedProcessingDate'])){ + return $this->feedList[$i]['StartedProcessingDate']; + } else { + return false; + } + } + + /** + * Returns the date that the specified entry finished being processed. + * + * This method will return FALSE if the list has not yet been filled. + * The time will be in the ISO8601 date format. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getDateCompleted($i = 0){ + if (is_numeric($i) && isset($this->feedList) && is_array($this->feedList) && isset($this->feedList[$i]['CompletedProcessingDate'])){ + return $this->feedList[$i]['CompletedProcessingDate']; + } else { + return false; + } + } + /** * Returns the full info for the specified entry. * @@ -548,6 +588,8 @@ public function getFeedStatus($i = 0){ *List index to retrieve the value from. Defaults to 0.
* @return array|boolean array of values, or FALSE if Non-numeric index diff --git a/includes/classes/AmazonFeedResult.php b/includes/classes/AmazonFeedResult.php index eda8cce1..55cfcfb6 100644 --- a/includes/classes/AmazonFeedResult.php +++ b/includes/classes/AmazonFeedResult.php @@ -25,7 +25,7 @@ * In order to fetch feed results, the feed's ID must be given. */ class AmazonFeedResult extends AmazonFeedsCore{ - private $rawFeed; + protected $rawFeed; /** * AmazonFeedResult gets the result of a Feed from Amazon. diff --git a/includes/classes/AmazonFinanceCore.php b/includes/classes/AmazonFinanceCore.php new file mode 100644 index 00000000..cd582ba9 --- /dev/null +++ b/includes/classes/AmazonFinanceCore.php @@ -0,0 +1,57 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + include($this->env); + + if(isset($AMAZON_VERSION_FINANCE)){ + $this->urlbranch = 'Finances/'.$AMAZON_VERSION_FINANCE; + $this->options['Version'] = $AMAZON_VERSION_FINANCE; + } + + if(isset($THROTTLE_LIMIT_FINANCE)) { + $this->throttleLimit = $THROTTLE_LIMIT_FINANCE; + } + if(isset($THROTTLE_TIME_FINANCE)) { + $this->throttleTime = $THROTTLE_TIME_FINANCE; + } + $this->throttleGroup = 'Finance'; + } +} diff --git a/includes/classes/AmazonFinancialEventList.php b/includes/classes/AmazonFinancialEventList.php new file mode 100644 index 00000000..fa263d13 --- /dev/null +++ b/includes/classes/AmazonFinancialEventList.php @@ -0,0 +1,994 @@ +tokenFlag; + } + + /** + * Sets whether or not the object should automatically use tokens if it receives one. + * + * If this option is set to TRUE, the object will automatically perform + * the necessary operations to retrieve the rest of the list using tokens. If + * this option is off, the object will only ever retrieve the first section of + * the list. + * @param boolean $b [optional]Defaults to TRUE
+ * @return boolean FALSE if improper input + */ + public function setUseToken($b = true) { + if (is_bool($b)) { + $this->tokenUseFlag = $b; + } else { + return false; + } + } + + /** + * Sets the maximum number of responses per page. (Optional) + * + * This method sets the maximum number of Financial Events for Amazon to return per page. + * If this parameter is not set, Amazon will send 100 at a time. + * @param int $numPositive integer from 1 to 100.
+ * @return boolean FALSE if improper input + */ + public function setMaxResultsPerPage($num){ + if (is_numeric($num) && $num <= 100 && $num >= 1){ + $this->options['MaxResultsPerPage'] = $num; + } else { + return false; + } + } + + /** + * Sets the order ID filter. (Required*) + * + * If this parameter is set, Amazon will only return Financial Events that + * relate to the given order. This parameter is required if none of the + * other filter options are set. + * If this parameter is set, the group ID and time range options will be removed. + * @param string $sAmazon Order ID in 3-7-7 format
+ * @return boolean FALSE if improper input + */ + public function setOrderFilter($s){ + if ($s && is_string($s)) { + $this->resetFilters(); + $this->options['AmazonOrderId'] = $s; + } else { + return false; + } + } + + /** + * Sets the financial event group ID filter. (Required*) + * + * If this parameter is set, Amazon will only return Financial Events that + * belong to the given financial event group. This parameter is required if + * none of the other filter options are set. + * If this parameter is set, the order ID and time range options will be removed. + * @param string $sFinancial Event Group ID
+ * @return boolean FALSE if improper input + */ + public function setGroupFilter($s){ + if ($s && is_string($s)) { + $this->resetFilters(); + $this->options['FinancialEventGroupId'] = $s; + } else { + return false; + } + } + + /** + * Sets the time frame options. (Required*) + * + * This method sets the start and end times for the next request. If this + * parameter is set, Amazon will only return Financial Events posted + * between the two times given. This parameter is required if none of the + * other filter options are set. + * The parameters are passed through strtotime, so values such as "-1 hour" are fine. + * If this parameter is set, the order ID and group ID options will be removed. + * @param string $sA time string for the earliest time.
+ * @param string $e [optional]A time string for the latest time.
+ * @return boolean FALSE if improper input + */ + public function setTimeLimits($s, $e = null) { + if (empty($s)) { + return FALSE; + } + $this->resetFilters(); + + $times = $this->genTime($s); + $this->options['PostedAfter'] = $times; + if (!empty($e)) { + $timee = $this->genTime($e); + $this->options['PostedBefore'] = $timee; + } + } + + /** + * Removes time limit options. + * + * Use this in case you change your mind and want to remove the time limit + * parameters you previously set. + */ + public function resetTimeLimits(){ + unset($this->options['PostedAfter']); + unset($this->options['PostedBefore']); + } + + /** + * Removes all filter options. + * + * Use this in case you change your mind and want to remove all filter + * parameters you previously set. + */ + public function resetFilters(){ + unset($this->options['AmazonOrderId']); + unset($this->options['FinancialEventGroupId']); + $this->resetTimeLimits(); + } + + /** + * Fetches the inventory supply list from Amazon. + * + * Submits a ListFinancialEvents request to Amazon. Amazon will send + * the list back as a response, which can be retrieved using getEvents. + * Other methods are available for fetching specific values from the list. + * This operation can potentially involve tokens. + * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
+ * @return boolean FALSE if something goes wrong + */ + public function fetchEventList($r = true) { + $this->prepareToken(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + + if ($this->mockMode) { + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)) { + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml->FinancialEvents); + + $this->checkToken($xml); + + if ($this->tokenFlag && $this->tokenUseFlag && $r === true) { + while ($this->tokenFlag) { + $this->log("Recursively fetching more Financial Events"); + $this->fetchEventList(false); + } + } + } + + /** + * Sets up options for using tokens. + * + * This changes key options for switching between simply fetching a list and + * fetching the rest of a list using a token. Please note: because the + * operation for using tokens does not use any other parameters, all other + * parameters will be removed. + */ + protected function prepareToken() { + if ($this->tokenFlag && $this->tokenUseFlag) { + $this->options['Action'] = 'ListFinancialEventsByNextToken'; + unset($this->options['MaxResultsPerPage']); + $this->resetFilters(); + } else { + $this->options['Action'] = 'ListFinancialEvents'; + unset($this->options['NextToken']); + $this->list = array(); + } + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml) { + return false; + } + if (isset($xml->ShipmentEventList)) { + foreach($xml->ShipmentEventList->children() as $x) { + $this->list['Shipment'][] = $this->parseShipmentEvent($x); + } + } + if (isset($xml->RefundEventList)) { + foreach($xml->RefundEventList->children() as $x) { + $this->list['Refund'][] = $this->parseShipmentEvent($x); + } + } + if (isset($xml->GuaranteeClaimEventList)) { + foreach($xml->GuaranteeClaimEventList->children() as $x) { + $this->list['GuaranteeClaim'][] = $this->parseShipmentEvent($x); + } + } + if (isset($xml->ChargebackEventList)) { + foreach($xml->ChargebackEventList->children() as $x) { + $this->list['Chargeback'][] = $this->parseShipmentEvent($x); + } + } + if (isset($xml->PayWithAmazonEventList)) { + foreach($xml->PayWithAmazonEventList->children() as $x) { + $temp = array(); + $temp['SellerOrderId'] = (string)$x->SellerOrderId; + $temp['TransactionPostedDate'] = (string)$x->TransactionPostedDate; + $temp['BusinessObjectType'] = (string)$x->BusinessObjectType; + $temp['SalesChannel'] = (string)$x->SalesChannel; + $temp['Charge'] = $this->parseCharge($x->Charge); + if (isset($x->FeeList)) { + foreach($x->FeeList->children() as $z) { + $temp['FeeList'][] = $this->parseFee($z); + } + } + $temp['PaymentAmountType'] = (string)$x->PaymentAmountType; + $temp['AmountDescription'] = (string)$x->AmountDescription; + $temp['FulfillmentChannel'] = (string)$x->FulfillmentChannel; + $temp['StoreName'] = (string)$x->StoreName; + $this->list['PayWithAmazon'][] = $temp; + } + } + if (isset($xml->ServiceProviderCreditEventList)) { + foreach($xml->ServiceProviderCreditEventList->children() as $x) { + $temp = array(); + $temp['ProviderTransactionType'] = (string)$x->ProviderTransactionType; + $temp['SellerOrderId'] = (string)$x->SellerOrderId; + $temp['MarketplaceId'] = (string)$x->MarketplaceId; + $temp['MarketplaceCountryCode'] = (string)$x->MarketplaceCountryCode; + $temp['SellerId'] = (string)$x->SellerId; + $temp['SellerStoreName'] = (string)$x->SellerStoreName; + $temp['ProviderId'] = (string)$x->ProviderId; + $temp['ProviderStoreName'] = (string)$x->ProviderStoreName; + $this->list['ServiceProviderCredit'][] = $temp; + } + } + if (isset($xml->RetrochargeEventList)) { + foreach($xml->RetrochargeEventList->children() as $x) { + $temp = array(); + $temp['RetrochargeEventType'] = (string)$x->RetrochargeEventType; + $temp['AmazonOrderId'] = (string)$x->AmazonOrderId; + $temp['PostedDate'] = (string)$x->PostedDate; + $temp['BaseTax']['Amount'] = (string)$x->BaseTax->CurrencyAmount; + $temp['BaseTax']['CurrencyCode'] = (string)$x->BaseTax->CurrencyCode; + $temp['ShippingTax']['Amount'] = (string)$x->ShippingTax->CurrencyAmount; + $temp['ShippingTax']['CurrencyCode'] = (string)$x->ShippingTax->CurrencyCode; + $temp['MarketplaceName'] = (string)$x->MarketplaceName; + $this->list['Retrocharge'][] = $temp; + } + } + if (isset($xml->RentalTransactionEventList)) { + foreach($xml->RentalTransactionEventList->children() as $x) { + $temp = array(); + $temp['AmazonOrderId'] = (string)$x->AmazonOrderId; + $temp['RentalEventType'] = (string)$x->RentalEventType; + $temp['ExtensionLength'] = (string)$x->ExtensionLength; + $temp['PostedDate'] = (string)$x->PostedDate; + if (isset($x->RentalChargeList)) { + foreach($x->RentalChargeList->children() as $z) { + $temp['RentalChargeList'][] = $this->parseCharge($z); + } + } + if (isset($x->RentalFeeList)) { + foreach($x->RentalFeeList->children() as $z) { + $temp['RentalFeeList'][] = $this->parseFee($z); + } + } + $temp['MarketplaceName'] = (string)$x->MarketplaceName; + if (isset($x->RentalInitialValue)) { + $temp['RentalInitialValue']['Amount'] = (string)$x->RentalInitialValue->CurrencyAmount; + $temp['RentalInitialValue']['CurrencyCode'] = (string)$x->RentalInitialValue->CurrencyCode; + } + if (isset($x->RentalReimbursement)) { + $temp['RentalReimbursement']['Amount'] = (string)$x->RentalReimbursement->CurrencyAmount; + $temp['RentalReimbursement']['CurrencyCode'] = (string)$x->RentalReimbursement->CurrencyCode; + } + $this->list['RentalTransaction'][] = $temp; + } + } + if (isset($xml->PerformanceBondRefundEventList)) { + foreach($xml->PerformanceBondRefundEventList->children() as $x) { + $temp = array(); + $temp['MarketplaceCountryCode'] = (string)$x->MarketplaceCountryCode; + $temp['Amount'] = (string)$x->Amount->CurrencyAmount; + $temp['CurrencyCode'] = (string)$x->Amount->CurrencyCode; + if (isset($x->ProductGroupList)) { + foreach($x->ProductGroupList->children() as $z) { + $temp['ProductGroupList'][] = (string)$z; + } + } + $this->list['PerformanceBondRefund'][] = $temp; + } + } + if (isset($xml->ServiceFeeEventList)) { + foreach($xml->ServiceFeeEventList->children() as $x) { + $temp = array(); + $temp['AmazonOrderId'] = (string)$x->AmazonOrderId; + $temp['FeeReason'] = (string)$x->FeeReason; + if (isset($x->FeeList)) { + foreach($x->FeeList->children() as $z) { + $temp['FeeList'][] = $this->parseFee($z); + } + } + $temp['SellerSKU'] = (string)$x->SellerSKU; + $temp['FnSKU'] = (string)$x->FnSKU; + $temp['FeeDescription'] = (string)$x->FeeDescription; + $temp['ASIN'] = (string)$x->ASIN; + $this->list['ServiceFee'][] = $temp; + } + } + if (isset($xml->DebtRecoveryEventList)) { + foreach($xml->DebtRecoveryEventList->children() as $x) { + $temp = array(); + $temp['DebtRecoveryType'] = (string)$x->DebtRecoveryType; + $temp['RecoveryAmount']['Amount'] = (string)$x->RecoveryAmount->CurrencyAmount; + $temp['RecoveryAmount']['CurrencyCode'] = (string)$x->RecoveryAmount->CurrencyCode; + $temp['OverPaymentCredit']['Amount'] = (string)$x->OverPaymentCredit->CurrencyAmount; + $temp['OverPaymentCredit']['CurrencyCode'] = (string)$x->OverPaymentCredit->CurrencyCode; + if (isset($x->DebtRecoveryItemList)) { + foreach($x->DebtRecoveryItemList->children() as $z) { + $ztemp = array(); + $ztemp['RecoveryAmount']['Amount'] = (string)$z->RecoveryAmount->CurrencyAmount; + $ztemp['RecoveryAmount']['CurrencyCode'] = (string)$z->RecoveryAmount->CurrencyCode; + $ztemp['OriginalAmount']['Amount'] = (string)$z->OriginalAmount->CurrencyAmount; + $ztemp['OriginalAmount']['CurrencyCode'] = (string)$z->OriginalAmount->CurrencyCode; + $ztemp['GroupBeginDate'] = (string)$z->GroupBeginDate; + $ztemp['GroupEndDate'] = (string)$z->GroupEndDate; + $temp['DebtRecoveryItemList'][] = $ztemp; + } + } + if (isset($x->ChargeInstrumentList)) { + foreach($x->ChargeInstrumentList->children() as $z) { + $ztemp = array(); + $ztemp['Description'] = (string)$z->Description; + $ztemp['Tail'] = (string)$z->Tail; + $ztemp['Amount'] = (string)$z->Amount->CurrencyAmount; + $ztemp['CurrencyCode'] = (string)$z->Amount->CurrencyCode; + $temp['ChargeInstrumentList'][] = $ztemp; + } + } + $this->list['DebtRecovery'][] = $temp; + } + } + if (isset($xml->LoanServicingEventList)) { + foreach($xml->LoanServicingEventList->children() as $x) { + $temp = array(); + $temp['Amount'] = (string)$x->LoanAmount->CurrencyAmount; + $temp['CurrencyCode'] = (string)$x->LoanAmount->CurrencyCode; + $temp['SourceBusinessEventType'] = (string)$x->SourceBusinessEventType; + $this->list['LoanServicing'][] = $temp; + } + } + if (isset($xml->AdjustmentEventList)) { + foreach($xml->AdjustmentEventList->children() as $x) { + $temp = array(); + $temp['AdjustmentType'] = (string)$x->AdjustmentType; + $temp['Amount'] = (string)$x->AdjustmentAmount->CurrencyAmount; + $temp['CurrencyCode'] = (string)$x->AdjustmentAmount->CurrencyCode; + if (isset($x->AdjustmentItemList)) { + foreach($x->AdjustmentItemList->children() as $z) { + $ztemp = array(); + $ztemp['Quantity'] = (string)$z->Quantity; + $ztemp['PerUnitAmount']['Amount'] = (string)$z->PerUnitAmount->CurrencyAmount; + $ztemp['PerUnitAmount']['CurrencyCode'] = (string)$z->PerUnitAmount->CurrencyCode; + $ztemp['TotalAmount']['Amount'] = (string)$z->TotalAmount->CurrencyAmount; + $ztemp['TotalAmount']['CurrencyCode'] = (string)$z->TotalAmount->CurrencyCode; + $ztemp['SellerSKU'] = (string)$z->SellerSKU; + $ztemp['FnSKU'] = (string)$z->FnSKU; + $ztemp['ProductDescription'] = (string)$z->ProductDescription; + $ztemp['ASIN'] = (string)$z->ASIN; + $temp['AdjustmentItemList'][] = $ztemp; + } + } + $this->list['Adjustment'][] = $temp; + } + } + } + + /** + * Parses XML for a single shipment event into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return array parsed structure from XML + */ + protected function parseShipmentEvent($xml) { + $r = array(); + $r['AmazonOrderId'] = (string)$xml->AmazonOrderId; + $r['SellerOrderId'] = (string)$xml->SellerOrderId; + $r['MarketplaceName'] = (string)$xml->MarketplaceName; + $chargeLists = array( + 'OrderChargeList', + 'OrderChargeAdjustmentList', + ); + foreach ($chargeLists as $key) { + if (isset($xml->$key)) { + foreach($xml->$key->children() as $x) { + $r[$key][] = $this->parseCharge($x); + } + } + } + $feelists = array( + 'ShipmentFeeList', + 'ShipmentFeeAdjustmentList', + 'OrderFeeList', + 'OrderFeeAdjustmentList', + ); + foreach ($feelists as $key) { + if (isset($xml->$key)) { + foreach($xml->$key->children() as $x) { + $r[$key][] = $this->parseFee($x); + } + } + } + if (isset($xml->DirectPaymentList)) { + foreach($xml->DirectPaymentList->children() as $x){ + $temp = array(); + $temp['DirectPaymentType'] = (string)$x->DirectPaymentType; + $temp['Amount'] = (string)$x->DirectPaymentAmount->CurrencyAmount; + $temp['CurrencyCode'] = (string)$x->DirectPaymentAmount->CurrencyCode; + $r['DirectPaymentList'][] = $temp; + } + } + $r['PostedDate'] = (string)$xml->PostedDate; + $itemLists = array( + 'ShipmentItemList', + 'ShipmentItemAdjustmentList', + ); + $itemChargeLists = array( + 'ItemChargeList', + 'ItemChargeAdjustmentList', + ); + $itemFeeLists = array( + 'ItemFeeList', + 'ItemFeeAdjustmentList', + ); + $itemPromoLists = array( + 'PromotionList', + 'PromotionAdjustmentList', + ); + foreach ($itemLists as $key) { + if (isset($xml->$key)) { + foreach($xml->$key->children() as $x) { + $temp = array(); + $temp['SellerSKU'] = (string)$x->SellerSKU; + $temp['OrderItemId'] = (string)$x->OrderItemId; + if (isset($x->OrderAdjustmentItemId)) { + $temp['OrderAdjustmentItemId'] = (string)$x->OrderAdjustmentItemId; + } + $temp['QuantityShipped'] = (string)$x->QuantityShipped; + foreach ($itemChargeLists as $zkey) { + if (isset($x->$zkey)) { + foreach($x->$zkey->children() as $z) { + $temp[$zkey][] = $this->parseCharge($z); + } + } + } + foreach ($itemFeeLists as $zkey) { + if (isset($x->$zkey)) { + foreach($x->$zkey->children() as $z) { + $temp[$zkey][] = $this->parseFee($z); + } + } + } + foreach ($itemPromoLists as $zkey) { + if (isset($x->$zkey)) { + foreach($x->$zkey->children() as $z) { + $ztemp = array(); + $ztemp['PromotionType'] = (string)$z->PromotionType; + $ztemp['PromotionId'] = (string)$z->PromotionId; + $ztemp['Amount'] = (string)$z->PromotionAmount->CurrencyAmount; + $ztemp['CurrencyCode'] = (string)$z->PromotionAmount->CurrencyCode; + $temp[$zkey][] = $ztemp; + } + } + } + if (isset($x->CostOfPointsGranted)) { + $temp['CostOfPointsGranted']['Amount'] = (string)$x->CostOfPointsGranted->CurrencyAmount; + $temp['CostOfPointsGranted']['CurrencyCode'] = (string)$x->CostOfPointsGranted->CurrencyCode; + } + if (isset($x->CostOfPointsReturned)) { + $temp['CostOfPointsReturned']['Amount'] = (string)$x->CostOfPointsReturned->CurrencyAmount; + $temp['CostOfPointsReturned']['CurrencyCode'] = (string)$x->CostOfPointsReturned->CurrencyCode; + } + $r[$key][] = $temp; + } + } + } + return $r; + } + + /** + * Parses XML for a single charge into an array. + * This structure is used many times throughout shipment events. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return array parsed structure from XML + */ + protected function parseCharge($xml) { + $r = array(); + $r['ChargeType'] = (string)$xml->ChargeType; + $r['Amount'] = (string)$xml->ChargeAmount->CurrencyAmount; + $r['CurrencyCode'] = (string)$xml->ChargeAmount->CurrencyCode; + return $r; + } + + /** + * Parses XML for a single charge into an array. + * This structure is used many times throughout shipment events. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return array parsed structure from XML + */ + protected function parseFee($xml) { + $r = array(); + $r['FeeType'] = (string)$xml->FeeType; + $r['Amount'] = (string)$xml->FeeAmount->CurrencyAmount; + $r['CurrencyCode'] = (string)$xml->FeeAmount->CurrencyCode; + return $r; + } + + /** + * Returns all financial events. + * + * The array will have the following keys: + *Defaults to TRUE
+ * @return boolean FALSE if improper input + */ + public function setUseToken($b = true) { + if (is_bool($b)) { + $this->tokenUseFlag = $b; + } else { + return false; + } + } + + /** + * Sets the maximum number of responses per page. (Optional) + * + * This method sets the maximum number of Financial Event Groups for Amazon to return per page. + * If this parameter is not set, Amazon will send 100 at a time. + * @param int $numPositive integer from 1 to 100.
+ * @return boolean FALSE if improper input + */ + public function setMaxResultsPerPage($num){ + if (is_numeric($num) && $num <= 100 && $num >= 1){ + $this->options['MaxResultsPerPage'] = $num; + } else { + return false; + } + } + + /** + * Sets the time frame options. (Required*) + * + * This method sets the start and end times for the next request. If this + * parameter is set, Amazon will only return Financial Event Groups that occurred + * between the two times given. Only the starting time is required to fetch financial event groups. + * The parameters are passed through strtotime, so values such as "-1 hour" are fine. + * @param string $sA time string for the earliest time.
+ * @param string $e [optional]A time string for the latest time.
+ * @return boolean FALSE if improper input + */ + public function setTimeLimits($s, $e = null) { + if (empty($s)) { + return FALSE; + } + $times = $this->genTime($s); + $this->options['FinancialEventGroupStartedAfter'] = $times; + if (!empty($e)) { + $timee = $this->genTime($e); + $this->options['FinancialEventGroupStartedBefore'] = $timee; + } else { + unset($this->options['FinancialEventGroupStartedBefore']); + } + } + + /** + * Fetches a list of financial event groups from Amazon. + * + * Submits a ListFinancialEventGroups request to Amazon. In order to do this, + * a start date must be set. Amazon will send the list back as a response, + * which can be retrieved using getGroups. + * Other methods are available for fetching specific values from the list. + * This operation can potentially involve tokens. + * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
+ * @return boolean FALSE if something goes wrong + */ + public function fetchGroupList($r = true) { + if (!array_key_exists('FinancialEventGroupStartedAfter', $this->options)) { + $this->log("Start date must be set in order to fetch financial event groups", 'Warning'); + return false; + } + + $this->prepareToken(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + + if ($this->mockMode) { + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)) { + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + + $this->checkToken($xml); + + if ($this->tokenFlag && $this->tokenUseFlag && $r === true) { + while ($this->tokenFlag) { + $this->log("Recursively fetching more Financial Event Groups"); + $this->fetchGroupList(false); + } + } + } + + /** + * Sets up options for using tokens. + * + * This changes key options for switching between simply fetching a list and + * fetching the rest of a list using a token. Please note: because the + * operation for using tokens does not use any other parameters, all other + * parameters will be removed. + */ + protected function prepareToken() { + if ($this->tokenFlag && $this->tokenUseFlag) { + $this->options['Action'] = 'ListFinancialEventGroupsByNextToken'; + unset($this->options['MaxResultsPerPage']); + unset($this->options['FinancialEventGroupStartedAfter']); + unset($this->options['FinancialEventGroupStartedBefore']); + } else { + $this->options['Action'] = 'ListFinancialEventGroups'; + unset($this->options['NextToken']); + $this->index = 0; + $this->list = array(); + } + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml || !$xml->FinancialEventGroupList) { + return false; + } + foreach($xml->FinancialEventGroupList->children() as $x) { + $temp = array(); + $temp['FinancialEventGroupId'] = (string)$x->FinancialEventGroupId; + $temp['ProcessingStatus'] = (string)$x->ProcessingStatus; + if (isset($x->FundTransferStatus)) { + $temp['FundTransferStatus'] = (string)$x->FundTransferStatus; + } + $temp['OriginalTotal']['Amount'] = (string)$x->OriginalTotal->CurrencyAmount; + $temp['OriginalTotal']['CurrencyCode'] = (string)$x->OriginalTotal->CurrencyCode; + if (isset($x->ConvertedTotal)) { + $temp['ConvertedTotal']['Amount'] = (string)$x->ConvertedTotal->CurrencyAmount; + $temp['ConvertedTotal']['CurrencyCode'] = (string)$x->ConvertedTotal->CurrencyCode; + } + if (isset($x->FundTransferDate)) { + $temp['FundTransferDate'] = (string)$x->FundTransferDate; + } + if (isset($x->TraceId)) { + $temp['TraceId'] = (string)$x->TraceId; + } + if (isset($x->AccountTail)) { + $temp['AccountTail'] = (string)$x->AccountTail; + } + $temp['BeginningBalance']['Amount'] = (string)$x->BeginningBalance->CurrencyAmount; + $temp['BeginningBalance']['CurrencyCode'] = (string)$x->BeginningBalance->CurrencyCode; + $temp['FinancialEventGroupStart'] = (string)$x->FinancialEventGroupStart; + if (isset($x->FinancialEventGroupEnd)) { + $temp['FinancialEventGroupEnd'] = (string)$x->FinancialEventGroupEnd; + } + $this->list[$this->index] = $temp; + $this->index++; + } + } + + /** + * Returns all financial event groups. + * + * Each financial event group array will have the following keys: + *List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getGroupId($i = 0) { + if (isset($this->list[$i]['FinancialEventGroupId'])) { + return $this->list[$i]['FinancialEventGroupId']; + } else { + return false; + } + } + + /** + * Returns the processing status for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean "Open" or "Closed", or FALSE if Non-numeric index + */ + public function getProcessingStatus($i = 0) { + if (isset($this->list[$i]['ProcessingStatus'])) { + return $this->list[$i]['ProcessingStatus']; + } else { + return false; + } + } + + /** + * Returns the transfer status for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getTransferStatus($i = 0) { + if (isset($this->list[$i]['FundTransferStatus'])) { + return $this->list[$i]['FundTransferStatus']; + } else { + return false; + } + } + + /** + * Returns the original total for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * If an array is returned, it will have the fields Amount and CurrencyCode. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param boolean $only [optional]set to TRUE to get only the amount
+ * @return array|string|boolean array, single value, or FALSE if Non-numeric index + */ + public function getOriginalTotal($i = 0, $only = false) { + if (isset($this->list[$i]['OriginalTotal'])) { + if ($only) { + return $this->list[$i]['OriginalTotal']['Amount']; + } else { + return $this->list[$i]['OriginalTotal']; + } + } else { + return false; + } + } + + /** + * Returns the converted total for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * If an array is returned, it will have the fields Amount and CurrencyCode. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param boolean $only [optional]set to TRUE to get only the amount
+ * @return array|string|boolean array, single value, or FALSE if Non-numeric index + */ + public function getConvertedTotal($i = 0, $only = false) { + if (isset($this->list[$i]['ConvertedTotal'])) { + if ($only) { + return $this->list[$i]['ConvertedTotal']['Amount']; + } else { + return $this->list[$i]['ConvertedTotal']; + } + } else { + return false; + } + } + + /** + * Returns the transfer date for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean date in ISO 8601 format, or FALSE if Non-numeric index + */ + public function getTransferDate($i = 0) { + if (isset($this->list[$i]['FundTransferDate'])) { + return $this->list[$i]['FundTransferDate']; + } else { + return false; + } + } + + /** + * Returns the trace ID for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getTraceId($i = 0) { + if (isset($this->list[$i]['TraceId'])) { + return $this->list[$i]['TraceId']; + } else { + return false; + } + } + + /** + * Returns the account tail for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getAccountTail($i = 0) { + if (isset($this->list[$i]['AccountTail'])) { + return $this->list[$i]['AccountTail']; + } else { + return false; + } + } + + /** + * Returns the balance at the beginning of the settlement period for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * If an array is returned, it will have the fields Amount and CurrencyCode. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param boolean $only [optional]set to TRUE to get only the amount
+ * @return array|string|boolean array, single value, or FALSE if Non-numeric index + */ + public function getBeginningBalance($i = 0, $only = false) { + if (isset($this->list[$i]['BeginningBalance'])) { + if ($only) { + return $this->list[$i]['BeginningBalance']['Amount']; + } else { + return $this->list[$i]['BeginningBalance']; + } + } else { + return false; + } + } + + /** + * Returns the start date for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean date in ISO 8601 format, or FALSE if Non-numeric index + */ + public function getStartDate($i = 0) { + if (isset($this->list[$i]['FinancialEventGroupStart'])) { + return $this->list[$i]['FinancialEventGroupStart']; + } else { + return false; + } + } + + /** + * Returns the end date for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean date in ISO 8601 format, or FALSE if Non-numeric index + */ + public function getEndDate($i = 0) { + if (isset($this->list[$i]['FinancialEventGroupEnd'])) { + return $this->list[$i]['FinancialEventGroupEnd']; + } else { + return false; + } + } + + /** + * Iterator function + * @return type + */ + public function current() { + return $this->list[$this->i]; + } + + /** + * Iterator function + */ + public function rewind() { + $this->i = 0; + } + + /** + * Iterator function + * @return type + */ + public function key() { + return $this->i; + } + + /** + * Iterator function + */ + public function next() { + $this->i++; + } + + /** + * Iterator function + * @return type + */ + public function valid() { + return isset($this->list[$this->i]); + } + +} diff --git a/includes/classes/AmazonFulfillmentOrder.php b/includes/classes/AmazonFulfillmentOrder.php index 05081bde..499dc990 100644 --- a/includes/classes/AmazonFulfillmentOrder.php +++ b/includes/classes/AmazonFulfillmentOrder.php @@ -25,7 +25,7 @@ * using the AmazonFulfillmentPreview object. */ class AmazonFulfillmentOrder extends AmazonOutboundCore{ - private $order; + protected $order; /** * AmazonFulfillmentOrder fetches a fulfillment order from Amazon. You need a Fulfillment Order ID. @@ -107,7 +107,7 @@ public function fetchOrder(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml) { @@ -126,10 +126,15 @@ protected function parseXML($xml) { //Section 1: ShipmentOrder $d = $xml->FulfillmentOrder; $this->order['Details']['SellerFulfillmentOrderId'] = (string)$d->SellerFulfillmentOrderId; + $this->order['Details']['MarketplaceId'] = (string)$d->MarketplaceId; $this->order['Details']['DisplayableOrderId'] = (string)$d->DisplayableOrderId; $this->order['Details']['DisplayableOrderDateTime'] = (string)$d->DisplayableOrderDateTime; $this->order['Details']['DisplayableOrderComment'] = (string)$d->DisplayableOrderComment; $this->order['Details']['ShippingSpeedCategory'] = (string)$d->ShippingSpeedCategory; + if (isset($d->DeliveryWindow)) { + $this->order['Details']['DeliveryWindow']['StartDateTime'] = (string)$d->DeliveryWindow->StartDateTime; + $this->order['Details']['DeliveryWindow']['EndDateTime'] = (string)$d->DeliveryWindow->EndDateTime; + } //Address $this->order['Details']['DestinationAddress']['Name'] = (string)$d->DestinationAddress->Name; $this->order['Details']['DestinationAddress']['Line1'] = (string)$d->DestinationAddress->Line1; @@ -152,10 +157,14 @@ protected function parseXML($xml) { $this->order['Details']['DestinationAddress']['PhoneNumber'] = (string)$d->DestinationAddress->PhoneNumber; } //End of Address + if (isset($d->FulfillmentAction)){ + $this->order['Details']['FulfillmentAction'] = (string)$d->FulfillmentAction; + } if (isset($d->FulfillmentPolicy)){ $this->order['Details']['FulfillmentPolicy'] = (string)$d->FulfillmentPolicy; } if (isset($d->FulfillmentMethod)){ + //deprecated $this->order['Details']['FulfillmentMethod'] = (string)$d->FulfillmentMethod; } $this->order['Details']['ReceivedDateTime'] = (string)$d->ReceivedDateTime; @@ -167,6 +176,25 @@ protected function parseXML($xml) { $this->order['Details']['NotificationEmailList'][$i++] = (string)$x; } } + if (isset($d->CODSettings->IsCODRequired)){ + $this->order['Details']['CODSettings']['IsCODRequired'] = (string)$d->CODSettings->IsCODRequired; + } + if (isset($d->CODSettings->CODCharge)){ + $this->order['Details']['CODSettings']['CODCharge']['CurrencyCode'] = (string)$d->CODSettings->CODCharge->CurrencyCode; + $this->order['Details']['CODSettings']['CODCharge']['Value'] = (string)$d->CODSettings->CODCharge->Value; + } + if (isset($d->CODSettings->CODChargeTax)){ + $this->order['Details']['CODSettings']['CODChargeTax']['CurrencyCode'] = (string)$d->CODSettings->CODChargeTax->CurrencyCode; + $this->order['Details']['CODSettings']['CODChargeTax']['Value'] = (string)$d->CODSettings->CODChargeTax->Value; + } + if (isset($d->CODSettings->ShippingCharge)){ + $this->order['Details']['CODSettings']['ShippingCharge']['CurrencyCode'] = (string)$d->CODSettings->ShippingCharge->CurrencyCode; + $this->order['Details']['CODSettings']['ShippingCharge']['Value'] = (string)$d->CODSettings->ShippingCharge->Value; + } + if (isset($d->CODSettings->ShippingChargeTax)){ + $this->order['Details']['CODSettings']['ShippingChargeTax']['CurrencyCode'] = (string)$d->CODSettings->ShippingChargeTax->CurrencyCode; + $this->order['Details']['CODSettings']['ShippingChargeTax']['Value'] = (string)$d->CODSettings->ShippingChargeTax->Value; + } //Section 2: Order Items $i = 0; @@ -198,6 +226,14 @@ protected function parseXML($xml) { $this->order['Items'][$i]['PerUnitDeclaredValue']['CurrencyCode'] = (string)$x->PerUnitDeclaredValue->CurrencyCode; $this->order['Items'][$i]['PerUnitDeclaredValue']['Value'] = (string)$x->PerUnitDeclaredValue->Value; } + if (isset($x->PerUnitPrice)){ + $this->order['Items'][$i]['PerUnitPrice']['CurrencyCode'] = (string)$x->PerUnitPrice->CurrencyCode; + $this->order['Items'][$i]['PerUnitPrice']['Value'] = (string)$x->PerUnitPrice->Value; + } + if (isset($x->PerUnitTax)){ + $this->order['Items'][$i]['PerUnitTax']['CurrencyCode'] = (string)$x->PerUnitTax->CurrencyCode; + $this->order['Items'][$i]['PerUnitTax']['Value'] = (string)$x->PerUnitTax->Value; + } $i++; } diff --git a/includes/classes/AmazonFulfillmentOrderCreator.php b/includes/classes/AmazonFulfillmentOrderCreator.php index 9bb1e691..a59acab2 100644 --- a/includes/classes/AmazonFulfillmentOrderCreator.php +++ b/includes/classes/AmazonFulfillmentOrderCreator.php @@ -27,22 +27,16 @@ class AmazonFulfillmentOrderCreator extends AmazonOutboundCore{ /** - * AmazonFulfillmentOrderCreator creates a fulfillment order. You need a fulfillment order ID. - * - * The parameters are passed to the parent constructor, which are - * in turn passed to the AmazonCore constructor. See it for more information - * on these parameters and common methods. - * @param string $s [optional]Name for the store you want to use. - * This parameter is optional if only one store is defined in the config file.
- * @param boolean $mock [optional]This is a flag for enabling Mock Mode. - * This defaults to FALSE.
- * @param array|string $m [optional]The files (or file) to use in Mock Mode.
- * @param string $config [optional]An alternate config file to set. Used for testing.
+ * Sets the marketplace associated with the fulfillment order. (Optional) + * @param string $mMarketplace ID
+ * @return boolean FALSE if improper input */ - public function __construct($s = null, $mock = false, $m = null, $config = null) { - parent::__construct($s, $mock, $m, $config); - - $this->options['Action'] = 'CreateFulfillmentOrder'; + public function setMarketplace($m){ + if (is_string($m)){ + $this->options['MarketplaceId'] = $m; + } else { + return false; + } } /** @@ -78,6 +72,23 @@ public function setDisplayableOrderId($s){ return false; } } + + /** + * Sets the fulfillment action that the shipment should use. (Optional) + * + * This method indicates whether the order should ship now or be put on hold. + * If this option is not sent, Amazon will assume that the order will ship now. + * @param string $s"Ship" or "Hold"
+ * @return boolean FALSE if improper input + */ + public function setFulfillmentAction($s){ + if ($s === 'Ship' || $s === 'Hold'){ + $this->options['FulfillmentAction'] = $s; + } else { + $this->log("Tried to set fulfillment action to invalid value", 'Warning'); + return false; + } + } /** * Sets the displayed timestamp. (Required) @@ -147,7 +158,7 @@ public function setShippingSpeed($s){ *"Consumer" or "Removal"
- * @return boolean FALSE if improper input + * The "FulfillmentMethod" option is no longer used. + * @return boolean FALSE + * @deprecated since 1.3.0 */ - public function setFulfillmentMethod($s){ - if (is_string($s)){ - if ($s == 'Consumer' || $s == 'Removal'){ - $this->options['FulfillmentMethod'] = $s; - } else { - $this->log("Tried to set fulfillment method to invalid value",'Warning'); - return false; - } - } else { - return false; - } + public function setFulfillmentMethod(){ + $this->log("The FulfillmentMethod option is no longer used for creating fulfillment orders.", 'Warning'); + return FALSE; } /** @@ -299,6 +294,98 @@ public function resetEmails(){ } } } + + /** + * Sets the COD settings. (Optional) + * + * This method sets various settings related to COD (Cash on Delivery) orders. + * Any setting that is passed asNULL
will not be set. + * Amazon will assume a value of 0 for any of the currency options not set. + * @param string $cuISO 4217 currency code
+ * @param boolean $r [optional]Whether or not COD is required for the order.
+ * @param float $c [optional]COD charge to collect
+ * @param float $ct [optional]tax on the COD charge to collect
+ * @param float $s [optional]shipping charge to collect
+ * @param float $st [optional]tax on the shipping charge to collect
+ * @return boolean FALSE if improper input + */ + public function setCodSettings($cu, $r = null, $c = null, $ct = null, $s = null, $st = null) { + if (empty($cu)) { + return false; + } + if (isset($r)) { + if (filter_var($r, FILTER_VALIDATE_BOOLEAN)) { + $r = 'true'; + } else { + $r = 'false'; + } + $this->options['CODSettings.IsCODRequired'] = $r; + } + //COD charge + if (isset($c) && is_numeric($c)) { + $this->options['CODSettings.CODCharge.Value'] = $c; + $this->options['CODSettings.CODCharge.CurrencyCode'] = $cu; + } + //COD charge tax + if (isset($ct) && is_numeric($ct)) { + $this->options['CODSettings.CODChargeTax.Value'] = $ct; + $this->options['CODSettings.CODChargeTax.CurrencyCode'] = $cu; + } + //shipping charge + if (isset($s) && is_numeric($s)) { + $this->options['CODSettings.ShippingCharge.Value'] = $s; + $this->options['CODSettings.ShippingCharge.CurrencyCode'] = $cu; + } + //shipping charge tax + if (isset($st) && is_numeric($st)) { + $this->options['CODSettings.ShippingChargeTax.Value'] = $st; + $this->options['CODSettings.ShippingChargeTax.CurrencyCode'] = $cu; + } + } + + /** + * Removes COD settings options. + * + * Use this in case you change your mind and want to remove the COD settings you previously set. + */ + public function resetCodSettings(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#CODSettings#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the delivery window for the order. (Optional) + * + * This method sets the delivery window's start and end times for the next request. + * This option is required if the shipping speed is set to "ScheduledDelivery". + * The parameters are passed through strtotime, so values such as "-1 hour" are fine. + * @param string $sA time string for the earliest time.
+ * @param string $eA time string for the latest time.
+ * @return boolean FALSE if improper input + * @see genTime + */ + public function setDeliveryWindow($s, $e){ + if (empty($s) || empty($e)) { + return false; + } + $times = $this->genTime($s); + $this->options['DeliveryWindow.StartDateTime'] = $times; + $timee = $this->genTime($e); + $this->options['DeliveryWindow.EndDateTime'] = $timee; + } + + /** + * Removes delivery window options. + * + * Use this in case you change your mind and want to remove the delivery window option you previously set. + */ + public function resetDeliveryWindow(){ + unset($this->options['DeliveryWindow.StartDateTime']); + unset($this->options['DeliveryWindow.EndDateTime']); + } /** * Sets the items. (Required) @@ -319,6 +406,8 @@ public function resetEmails(){ *See above.
* @return boolean FALSE if improper input @@ -351,6 +440,14 @@ public function setItems($a){ $this->options['Items.member.'.$i.'.PerUnitDeclaredValue.CurrencyCode'] = $x['PerUnitDeclaredValue']['CurrencyCode']; $this->options['Items.member.'.$i.'.PerUnitDeclaredValue.Value'] = $x['PerUnitDeclaredValue']['Value']; } + if (array_key_exists('PerUnitPrice', $x)){ + $this->options['Items.member.'.$i.'.PerUnitPrice.CurrencyCode'] = $x['PerUnitPrice']['CurrencyCode']; + $this->options['Items.member.'.$i.'.PerUnitPrice.Value'] = $x['PerUnitPrice']['Value']; + } + if (array_key_exists('PerUnitTax', $x)){ + $this->options['Items.member.'.$i.'.PerUnitTax.CurrencyCode'] = $x['PerUnitTax']['CurrencyCode']; + $this->options['Items.member.'.$i.'.PerUnitTax.Value'] = $x['PerUnitTax']['Value']; + } $i++; } else { @@ -382,12 +479,12 @@ protected function resetItems(){ * a number of parameters are required. Amazon will send back an HTTP response, * so there is no data to retrieve afterwards. The following parameters are required: * fulfillment order ID, displayed order ID, displayed timestamp, comment, - * shipping speed, address, items. + * shipping speed, address, and items. * @return boolean TRUE if the order creation was successful, FALSE if something goes wrong */ public function createOrder(){ if (!array_key_exists('SellerFulfillmentOrderId',$this->options)){ - $this->log("Seller Fulfillment OrderID must be set in order to create an order",'Warning'); + $this->log("Seller Fulfillment Order ID must be set in order to create an order",'Warning'); return false; } if (!array_key_exists('DisplayableOrderId',$this->options)){ @@ -414,6 +511,8 @@ public function createOrder(){ $this->log("Items must be set in order to create an order",'Warning'); return false; } + + $this->prepareCreate(); $url = $this->urlbase.$this->urlbranch; @@ -431,6 +530,62 @@ public function createOrder(){ return true; } } + + /** + * Updates a Fulfillment Order with Amazon. + * + * Submits an UpdateFulfillmentOrder request to Amazon. In order to do this, + * a fulfillment order ID is required. Amazon will send back an HTTP response, + * so there is no data to retrieve afterwards. + * @return boolean TRUE if the order creation was successful, FALSE if something goes wrong + */ + public function updateOrder(){ + if (!array_key_exists('SellerFulfillmentOrderId',$this->options)){ + $this->log("Seller Fulfillment Order ID must be set in order to update an order",'Warning'); + return false; + } + + $this->prepareUpdate(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + if ($this->mockMode){ + $response = $this->fetchMockResponse(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + } + if (!$this->checkResponse($response)){ + return false; + } else { + $this->log("Successfully updated Fulfillment Order ".$this->options['SellerFulfillmentOrderId']); + return true; + } + } + + /** + * Sets up options for using createOrder. + * + * This changes key options for using createOrder. + */ + protected function prepareCreate() { + $this->options['Action'] = 'CreateFulfillmentOrder'; + } + + /** + * Sets up options for using updateOrder. + * + * This changes key options for using updateOrder. Please note: because the + * operation for updating the order does not use all of the parameters, some of the + * parameters will be removed. The following parameters are removed: + * COD settings and delivery window. + */ + protected function prepareUpdate() { + $this->options['Action'] = 'UpdateFulfillmentOrder'; + $this->resetCodSettings(); + $this->resetDeliveryWindow(); + } } ?> diff --git a/includes/classes/AmazonFulfillmentOrderList.php b/includes/classes/AmazonFulfillmentOrderList.php index a84a23a7..e425e518 100644 --- a/includes/classes/AmazonFulfillmentOrderList.php +++ b/includes/classes/AmazonFulfillmentOrderList.php @@ -25,11 +25,11 @@ * This object can use tokens when retrieving the list. */ class AmazonFulfillmentOrderList extends AmazonOutboundCore implements Iterator{ - private $orderList; + protected $orderList; protected $tokenFlag = false; protected $tokenUseFlag = false; - private $i = 0; - private $index = 0; + protected $i = 0; + protected $index = 0; /** * AmazonFulfillmentOrderList retrieves a list of fulfillment orders from Amazon. @@ -71,26 +71,13 @@ public function setStartTime($s){ } /** - * Sets the fulfillment method filter. (Optional) - * - * This method sets the Fulfillment Method to be sent in the next request. - * If this parameter is set, Amazon will return fulfillment orders using the given method. - * If this parameter is not set, Amazon will only return fulfillment orders - * with a Consumer method. - * Here is a quick description of the methods: - *"Consumer" or "Removal"
- * @return boolean FALSE if improper input + * The "FulfillmentMethod" option is no longer used. + * @return boolean FALSE + * @deprecated since 1.3.0 */ public function setMethodFilter($s){ - if ($s == 'Consumer' || $s == 'Removal'){ - $this->options['FulfillmentMethod'] = $s; - } else { - return false; - } + $this->log("The FulfillmentMethod option is no longer used for getting fulfillment orders.", 'Warning'); + return FALSE; } /** @@ -176,7 +163,6 @@ protected function prepareToken(){ if ($this->tokenFlag && $this->tokenUseFlag){ $this->options['Action'] = 'ListAllFulfillmentOrdersByNextToken'; unset($this->options['QueryStartDateTime']); - unset($this->options['FulfillmentMethod']); } else { $this->options['Action'] = 'ListAllFulfillmentOrders'; unset($this->options['NextToken']); @@ -189,7 +175,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -199,10 +185,15 @@ protected function parseXML($xml){ foreach($xml->children() as $x){ $i = $this->index; $this->orderList[$i]['SellerFulfillmentOrderId'] = (string)$x->SellerFulfillmentOrderId; + $this->orderList[$i]['MarketplaceId'] = (string)$x->MarketplaceId; $this->orderList[$i]['DisplayableOrderId'] = (string)$x->DisplayableOrderId; $this->orderList[$i]['DisplayableOrderDateTime'] = (string)$x->DisplayableOrderDateTime; $this->orderList[$i]['DisplayableOrderComment'] = (string)$x->DisplayableOrderComment; $this->orderList[$i]['ShippingSpeedCategory'] = (string)$x->ShippingSpeedCategory; + if (isset($x->DeliveryWindow)) { + $this->orderList[$i]['DeliveryWindow']['StartDateTime'] = (string)$x->DeliveryWindow->StartDateTime; + $this->orderList[$i]['DeliveryWindow']['EndDateTime'] = (string)$x->DeliveryWindow->EndDateTime; + } if (isset($x->DestinationAddress)){ $this->orderList[$i]['DestinationAddress']['Name'] = (string)$x->DestinationAddress->Name; $this->orderList[$i]['DestinationAddress']['Line1'] = (string)$x->DestinationAddress->Line1; @@ -225,11 +216,15 @@ protected function parseXML($xml){ $this->orderList[$i]['DestinationAddress']['PhoneNumber'] = (string)$x->DestinationAddress->PhoneNumber; } } + if (isset($x->FulfillmentAction)){ + $this->orderList[$i]['FulfillmentAction'] = (string)$x->FulfillmentAction; + } if (isset($x->FulfillmentPolicy)){ $this->orderList[$i]['FulfillmentPolicy'] = (string)$x->FulfillmentPolicy; } if (isset($x->FulfillmentMethod)){ - $this->orderList[$i]['FulfillmentPolicy'] = (string)$x->FulfillmentMethod; + //deprecated + $this->orderList[$i]['FulfillmentMethod'] = (string)$x->FulfillmentMethod; } $this->orderList[$i]['ReceivedDateTime'] = (string)$x->ReceivedDateTime; $this->orderList[$i]['FulfillmentOrderStatus'] = (string)$x->FulfillmentOrderStatus; @@ -240,6 +235,25 @@ protected function parseXML($xml){ $this->orderList[$i]['NotificationEmailList'][$j++] = (string)$y; } } + if (isset($x->CODSettings->IsCODRequired)){ + $this->orderList[$i]['CODSettings']['IsCODRequired'] = (string)$x->CODSettings->IsCODRequired; + } + if (isset($x->CODSettings->CODCharge)){ + $this->orderList[$i]['CODSettings']['CODCharge']['CurrencyCode'] = (string)$x->CODSettings->CODCharge->CurrencyCode; + $this->orderList[$i]['CODSettings']['CODCharge']['Value'] = (string)$x->CODSettings->CODCharge->Value; + } + if (isset($x->CODSettings->CODChargeTax)){ + $this->orderList[$i]['CODSettings']['CODChargeTax']['CurrencyCode'] = (string)$x->CODSettings->CODChargeTax->CurrencyCode; + $this->orderList[$i]['CODSettings']['CODChargeTax']['Value'] = (string)$x->CODSettings->CODChargeTax->Value; + } + if (isset($x->CODSettings->ShippingCharge)){ + $this->orderList[$i]['CODSettings']['ShippingCharge']['CurrencyCode'] = (string)$x->CODSettings->ShippingCharge->CurrencyCode; + $this->orderList[$i]['CODSettings']['ShippingCharge']['Value'] = (string)$x->CODSettings->ShippingCharge->Value; + } + if (isset($x->CODSettings->ShippingChargeTax)){ + $this->orderList[$i]['CODSettings']['ShippingChargeTax']['CurrencyCode'] = (string)$x->CODSettings->ShippingChargeTax->CurrencyCode; + $this->orderList[$i]['CODSettings']['ShippingChargeTax']['Value'] = (string)$x->CODSettings->ShippingChargeTax->Value; + } $this->index++; } } @@ -277,13 +291,15 @@ public function getFullList(){ *List index to retrieve the value from. * If none is given, the entire list will be returned. Defaults to NULL.
diff --git a/includes/classes/AmazonFulfillmentPreview.php b/includes/classes/AmazonFulfillmentPreview.php index 28782972..8ad7546c 100644 --- a/includes/classes/AmazonFulfillmentPreview.php +++ b/includes/classes/AmazonFulfillmentPreview.php @@ -24,7 +24,7 @@ * Shipment IDs, which are needed for dealing with fulfillment orders. */ class AmazonFulfillmentPreview extends AmazonOutboundCore{ - private $previewList; + protected $previewList; /** * AmazonFulfillmentPreview sends a request to Amazon to generate a Fulfillment Shipment Preview. @@ -58,7 +58,7 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) *Defaults to TRUE
+ */ + public function setIncludeCod($s = 'true') { + if (filter_var($s, FILTER_VALIDATE_BOOLEAN)) { + $s = 'true'; + } else { + $s = 'false'; + } + $this->options['IncludeCODFulfillmentPreview'] = $s; + } + + /** + * Sets the option for getting delivery window data in the fetched previews. (Optional) + * + * If this option is set, Amazon will give delivery window data for applicable order previews. + * If this option is not set or is set to FALSE, Amazon will not give delivery window data. + * @param boolean $s [optional]Defaults to TRUE
+ */ + public function setIncludeDeliveryWindows($s = 'true') { + if (filter_var($s, FILTER_VALIDATE_BOOLEAN)) { + $s = 'true'; + } else { + $s = 'false'; + } + $this->options['IncludeDeliveryWindows'] = $s; + } /** * Generates a Fulfillment Preview with Amazon. @@ -250,7 +282,7 @@ public function fetchPreview(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml) { @@ -259,11 +291,14 @@ protected function parseXML($xml) { } $i = 0; foreach($xml->children() as $x){ + $this->previewList[$i]['ShippingSpeedCategory'] = (string)$x->ShippingSpeedCategory; + $this->previewList[$i]['IsFulfillable'] = (string)$x->IsFulfillable; + $this->previewList[$i]['IsCODCapable'] = (string)$x->IsCODCapable; + $this->previewList[$i]['MarketplaceId'] = (string)$x->MarketplaceId; if (isset($x->EstimatedShippingWeight)){ $this->previewList[$i]['EstimatedShippingWeight']['Unit'] = (string)$x->EstimatedShippingWeight->Unit; $this->previewList[$i]['EstimatedShippingWeight']['Value'] = (string)$x->EstimatedShippingWeight->Value; } - $this->previewList[$i]['ShippingSpeedCategory'] = (string)$x->ShippingSpeedCategory; if (isset($x->FulfillmentPreviewShipments)){ $j = 0; foreach ($x->FulfillmentPreviewShipments->children() as $y){ @@ -310,7 +345,15 @@ protected function parseXML($xml) { $j++; } } - $this->previewList[$i]['IsFulfillable'] = (string)$x->IsFulfillable; + if (isset($x->ScheduledDeliveryInfo)){ + $this->previewList[$i]['ScheduledDeliveryInfo']['DeliveryTimeZone'] = (string)$x->ScheduledDeliveryInfo->DeliveryTimeZone; + foreach ($x->ScheduledDeliveryInfo->DeliveryWindows->children() as $y){ + $temp = array(); + $temp['StartDateTime'] = (string)$y->DeliveryWindow->StartDateTime; + $temp['EndDateTime'] = (string)$y->DeliveryWindow->EndDateTime; + $this->previewList[$i]['ScheduledDeliveryInfo']['DeliveryWindows'][] = $temp; + } + } $i++; } @@ -324,6 +367,8 @@ protected function parseXML($xml) { *List index to retrieve the value from. * If none is given, the entire list will be returned. Defaults to NULL.
diff --git a/includes/classes/AmazonInventoryList.php b/includes/classes/AmazonInventoryList.php index 6705e6e9..d7055129 100644 --- a/includes/classes/AmazonInventoryList.php +++ b/includes/classes/AmazonInventoryList.php @@ -26,9 +26,9 @@ class AmazonInventoryList extends AmazonInventoryCore implements Iterator{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $supplyList; - private $index = 0; - private $i = 0; + protected $supplyList; + protected $index = 0; + protected $i = 0; /** * AmazonInventoryList fetches a list of inventory supplies Amazon. @@ -81,7 +81,7 @@ public function setUseToken($b = true){ * were updated after the given time. * If this parameters is set, seller SKUs cannot be set. * The parameter is passed through strtotime, so values such as "-1 hour" are fine. - * @param string $sTime string.
+ * @param string $tTime string.
* @return boolean FALSE if improper input */ public function setStartTime($t = null){ @@ -101,7 +101,7 @@ public function setStartTime($t = null){ * This method sets the list of seller SKUs to be sent in the next request. * Setting this parameter tells Amazon to only return inventory supplies that match * the IDs in the list. If this parameter is set, Start Time cannot be set. - * @param array|string $sA list of Seller SKUs, or a single ID string.
+ * @param array|string $aA list of Seller SKUs, or a single ID string.
* @return boolean FALSE if improper input */ public function setSellerSkus($a){ @@ -127,7 +127,7 @@ public function setSellerSkus($a){ * Since seller SKU is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetSkus(){ + protected function resetSkus(){ foreach($this->options as $op=>$junk){ if(preg_match("#SellerSkus.member.#",$op)){ unset($this->options[$op]); @@ -159,7 +159,7 @@ public function setResponseGroup($s){ * the list back as a response, which can be retrieved using getSupply. * Other methods are available for fetching specific values from the list. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchInventoryList($r = true){ @@ -208,7 +208,7 @@ public function fetchInventoryList($r = true){ * operation for using tokens does not use any other parameters, all other * parameters will be removed. */ - private function prepareToken(){ + protected function prepareToken(){ if ($this->tokenFlag && $this->tokenUseFlag){ $this->options['Action'] = 'ListInventorySupplyByNextToken'; unset($this->options['QueryStartDateTime']); @@ -226,7 +226,7 @@ private function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonMerchantCore.php b/includes/classes/AmazonMerchantCore.php new file mode 100644 index 00000000..0507f715 --- /dev/null +++ b/includes/classes/AmazonMerchantCore.php @@ -0,0 +1,57 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + include($this->env); + + if(isset($AMAZON_VERSION_MERCHANT)){ + $this->urlbranch = 'MerchantFulfillment/'.$AMAZON_VERSION_MERCHANT; + $this->options['Version'] = $AMAZON_VERSION_MERCHANT; + } + + if(isset($THROTTLE_LIMIT_MERCHANT)) { + $this->throttleLimit = $THROTTLE_LIMIT_MERCHANT; + } + if(isset($THROTTLE_TIME_MERCHANT)) { + $this->throttleTime = $THROTTLE_TIME_MERCHANT; + } + $this->throttleGroup = 'MerchantFulfillment'; + } +} diff --git a/includes/classes/AmazonMerchantServiceList.php b/includes/classes/AmazonMerchantServiceList.php new file mode 100644 index 00000000..5fdb5212 --- /dev/null +++ b/includes/classes/AmazonMerchantServiceList.php @@ -0,0 +1,671 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + + $this->options['Action'] = 'GetEligibleShippingServices'; + } + + /** + * Sets the Amazon Order ID. (Required) + * + * This method sets the Amazon Order ID to be sent in the next request. + * This parameter is required for fetching a list of eligible services from Amazon. + * @param string $idAmazon Order ID
+ * @return boolean FALSE if improper input + */ + public function setOrderId($id) { + if (is_string($id)){ + $this->options['ShipmentRequestDetails.AmazonOrderId'] = $id; + } else { + $this->log("Tried to set AmazonOrderId to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the Seller Order ID. (Optional) + * + * This method sets the Seller Order ID to be sent in the next request. + * @param string $idMaximum 64 characters.
+ * @return boolean FALSE if improper input + */ + public function setSellerOrderId($id) { + if (is_string($id) || is_numeric($id)){ + $this->options['ShipmentRequestDetails.SellerOrderId'] = $id; + } else { + $this->log("Tried to set SellerOrderId to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the items. (Required) + * + * This method sets the items to be sent in the next request. + * This parameter is required for fetching a list of eligible services from Amazon. + * The array provided should contain a list of arrays, each with the following fields: + *See above.
+ * @return boolean FALSE if improper input + */ + public function setItems($a){ + if (is_null($a) || is_string($a) || !$a){ + $this->log("Tried to set Items to invalid values",'Warning'); + return false; + } + $this->resetItems(); + $i = 1; + foreach ($a as $x){ + if (is_array($x) && isset($x['OrderItemId']) && isset($x['Quantity'])){ + $this->options['ShipmentRequestDetails.ItemList.Item.'.$i.'.OrderItemId'] = $x['OrderItemId']; + $this->options['ShipmentRequestDetails.ItemList.Item.'.$i.'.Quantity'] = $x['Quantity']; + $i++; + } else { + $this->resetItems(); + $this->log("Tried to set Items with invalid array",'Warning'); + return false; + } + } + } + + /** + * Resets the item options. + * + * Since the list of items is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetItems(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails.ItemList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the address. (Required) + * + * This method sets the shipper's address to be sent in the next request. + * This parameter is required for fetching a list of eligible services from Amazon. + * The array provided should have the following fields: + *See above.
+ * @return boolean FALSE if improper input + */ + public function setAddress($a){ + if (empty($a) || !is_array($a)){ + $this->log("Tried to set ShipFromAddress to invalid values",'Warning'); + return false; + } + $this->resetAddress(); + $this->options['ShipmentRequestDetails.ShipFromAddress.Name'] = $a['Name']; + $this->options['ShipmentRequestDetails.ShipFromAddress.AddressLine1'] = $a['AddressLine1']; + if (isset($a['AddressLine2'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.AddressLine2'] = $a['AddressLine2']; + } + if (isset($a['AddressLine3'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.AddressLine3'] = $a['AddressLine3']; + } + if (isset($a['DistrictOrCounty'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.DistrictOrCounty'] = $a['DistrictOrCounty']; + } + $this->options['ShipmentRequestDetails.ShipFromAddress.Email'] = $a['Email']; + $this->options['ShipmentRequestDetails.ShipFromAddress.City'] = $a['City']; + if (isset($a['StateOrProvinceCode'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.StateOrProvinceCode'] = $a['StateOrProvinceCode']; + } + $this->options['ShipmentRequestDetails.ShipFromAddress.PostalCode'] = $a['PostalCode']; + $this->options['ShipmentRequestDetails.ShipFromAddress.CountryCode'] = $a['CountryCode']; + $this->options['ShipmentRequestDetails.ShipFromAddress.Phone'] = $a['Phone']; + } + + /** + * Resets the address options. + * + * Since address is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetAddress(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails.ShipFromAddress#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the package dimensions. (Required) + * + * This method sets the package dimensions to be sent in the next request. + * This parameter is required for fetching a list of eligible services from Amazon. + * If this parameter is set, the predefined package name cannot be set. + * The array provided should have the following fields: + *See above.
+ * @return boolean FALSE if improper input + */ + public function setPackageDimensions($d) { + if (empty($d) || !is_array($d)){ + $this->log("Tried to set PackageDimensions to invalid values",'Warning'); + return false; + } + $this->resetPackageDimensions(); + $this->options['ShipmentRequestDetails.PackageDimensions.Length'] = $d['Length']; + $this->options['ShipmentRequestDetails.PackageDimensions.Width'] = $d['Width']; + $this->options['ShipmentRequestDetails.PackageDimensions.Height'] = $d['Height']; + $this->options['ShipmentRequestDetails.PackageDimensions.Unit'] = $d['Unit']; + } + + /** + * Sets the Predefined Package Dimensions. (Required) + * + * This method sets the predefined package name to be sent in the next request. + * Package dimensions are required for fetching a list of eligible services from Amazon. + * This parameter can be used instead of setting the package dimensions. + * If this parameter is set, the manual package dimensions cannot be set. + * @param string $sA value from the list of valid package names. + * See the comment inside the function for the complete list.
+ * @return boolean FALSE if improper input + */ + public function setPredefinedPackage($s) { + $this->resetPackageDimensions(); + if (is_string($s) && $s){ + $this->options['ShipmentRequestDetails.PackageDimensions.PredefinedPackageDimensions'] = $s; + } else { + return false; + } + /* + * List of valid Predefined Packages: + * FedEx_Box_10kg ~ 15.81 x 12.94 x 10.19 in + * FedEx_Box_25kg ~ 54.80 x 42.10 x 33.50 in + * FedEx_Box_Extra_Large_1 ~ 11.88 x 11.00 x 10.75 in + * FedEx_Box_Extra_Large_2 ~ 15.75 x 14.13 x 6.00 in + * FedEx_Box_Large_1 ~ 17.50 x 12.38 x 3.00 in + * FedEx_Box_Large_2 ~ 11.25 x 8.75 x 7.75 in + * FedEx_Box_Medium_1 ~ 13.25 x 11.50 x 2.38 in + * FedEx_Box_Medium_2 ~ 11.25 x 8.75 x 4.38 in + * FedEx_Box_Small_1 ~ 12.38 x 10.88 x 1.50 in + * FedEx_Box_Small_2 ~ 11.25 x 8.75 x 4.38 in + * FedEx_Envelope ~ 12.50 x 9.50 x 0.80 in + * FedEx_Padded_Pak ~ 11.75 x 14.75 x 2.00 in + * FedEx_Pak_1 ~ 15.50 x 12.00 x 0.80 in + * FedEx_Pak_2 ~ 12.75 x 10.25 x 0.80 in + * FedEx_Tube ~ 38.00 x 6.00 x 6.00 in + * FedEx_XL_Pak ~ 17.50 x 20.75 x 2.00 in + * UPS_Box_10kg ~ 41.00 x 33.50 x 26.50 cm + * UPS_Box_25kg ~ 48.40 x 43.30 x 35.00 cm + * UPS_Express_Box ~ 46.00 x 31.50 x 9.50 cm + * UPS_Express_Box_Large ~ 18.00 x 13.00 x 3.00 in + * UPS_Express_Box_Medium ~ 15.00 x 11.00 x 3.00 in + * UPS_Express_Box_Small ~ 13.00 x 11.00 x 2.00 in + * UPS_Express_Envelope ~ 12.50 x 9.50 x 2.00 in + * UPS_Express_Hard_Pak ~ 14.75 x 11.50 x 2.00 in + * UPS_Express_Legal_Envelope ~ 15.00 x 9.50 x 2.00 in + * UPS_Express_Pak ~ 16.00 x 12.75 x 2.00 in + * UPS_Express_Tube ~ 97.00 x 19.00 x 16.50 cm + * UPS_Laboratory_Pak ~ 17.25 x 12.75 x 2.00 in + * UPS_Pad_Pak ~ 14.75 x 11.00 x 2.00 in + * UPS_Pallet ~ 120.00 x 80.00 x 200.00 cm + * USPS_Card ~ 6.00 x 4.25 x 0.01 in + * USPS_Flat ~ 15.00 x 12.00 x 0.75 in + * USPS_FlatRateCardboardEnvelope ~ 12.50 x 9.50 x 4.00 in + * USPS_FlatRateEnvelope ~ 12.50 x 9.50 x 4.00 in + * USPS_FlatRateGiftCardEnvelope ~ 10.00 x 7.00 x 4.00 in + * USPS_FlatRateLegalEnvelope ~ 15.00 x 9.50 x 4.00 in + * USPS_FlatRatePaddedEnvelope ~ 12.50 x 9.50 x 4.00 in + * USPS_FlatRateWindowEnvelope ~ 10.00 x 5.00 x 4.00 in + * USPS_LargeFlatRateBoardGameBox ~ 24.06 x 11.88 x 3.13 in + * USPS_LargeFlatRateBox ~ 12.25 x 12.25 x 6.00 in + * USPS_Letter ~ 11.50 x 6.13 x 0.25 in + * USPS_MediumFlatRateBox1 ~ 11.25 x 8.75 x 6.00 in + * USPS_MediumFlatRateBox2 ~ 14.00 x 12.00 x 3.50 in + * USPS_RegionalRateBoxA1 ~ 10.13 x 7.13 x 5.00 in + * USPS_RegionalRateBoxA2 ~ 13.06 x 11.06 x 2.50 in + * USPS_RegionalRateBoxB1 ~ 16.25 x 14.50 x 3.00 in + * USPS_RegionalRateBoxB2 ~ 12.25 x 10.50 x 5.50 in + * USPS_RegionalRateBoxC ~ 15.00 x 12.00 x 12.00 in + * USPS_SmallFlatRateBox ~ 8.69 x 5.44 x 1.75 in + * USPS_SmallFlatRateEnvelope ~ 10.00 x 6.00 x 4.00 in + */ + } + + /** + * Resets the package dimension options. + * + * Since dimensions are a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetPackageDimensions(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails.PackageDimensions#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the weight. (Required) + * + * This method sets the shipment weight to be sent in the next request. + * @param string $vDecimal number
+ * @param string $u"oz" for ounces, or "g" for grams, defaults to grams
+ * @return boolean FALSE if improper input + */ + public function setWeight($v, $u = 'g') { + if (!empty($v) && !empty($u) && is_numeric($v) && ($u == 'oz' || $u == 'g')){ + $this->options['ShipmentRequestDetails.Weight.Value'] = $v; + $this->options['ShipmentRequestDetails.Weight.Unit'] = $u; + } else { + return false; + } + } + + /** + * Sets the date by which the package must arrive. (Optional) + * + * This method sets the maximum date to be sent in the next request. + * If this parameter is set, Amazon will only give services which + * will be able to deliver by the given date. + * @param string $dA time string
+ * @return boolean FALSE if improper input + */ + public function setMaxArrivalDate($d) { + try{ + $this->options['ShipmentRequestDetails.MustArriveByDate'] = $this->genTime($d); + } catch (Exception $e){ + unset($this->options['ShipmentRequestDetails.MustArriveByDate']); + $this->log('Error: '.$e->getMessage(), 'Warning'); + return false; + } + } + + /** + * Sets the date on which the package will be shipped. (Optional) + * + * This method sets the ship date to be sent in the next request. + * @param string $dA time string
+ * @return boolean FALSE if improper input + */ + public function setShipDate($d) { + try{ + $this->options['ShipmentRequestDetails.ShipDate'] = $this->genTime($d); + } catch (Exception $e){ + unset($this->options['ShipmentRequestDetails.ShipDate']); + $this->log('Error: '.$e->getMessage(), 'Warning'); + return false; + } + } + + /** + * Sets the Delivery Experience Option. (Required) + * + * This method sets the delivery experience shipping option to be sent in the next request. + * This parameter is required for fetching a list of eligible services from Amazon. + * @param string $s"DeliveryConfirmationWithAdultSignature", + * "DeliveryConfirmationWithSignature", + * "DeliveryConfirmationWithoutSignature", + * or "NoTracking"
+ * @return boolean FALSE if improper input + */ + public function setDeliveryOption($s) { + $options = array( + 'DeliveryConfirmationWithAdultSignature', + 'DeliveryConfirmationWithSignature', + 'DeliveryConfirmationWithoutSignature', + 'NoTracking' + ); + if (in_array($s, $options)){ + $this->options['ShipmentRequestDetails.ShippingServiceOptions.DeliveryExperience'] = $s; + } else { + $this->log("Tried to set DeliveryExperience to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the Declared Value. (Optional) + * + * This method sets the declared value to be sent in the next request. + * If this parameter is set and is higher than the carrier's minimum insurance amount, + * the seller will be charged more for the additional insurance. + * @param string $vMoney amount
+ * @param string $cISO 4217 currency code (ex: USD)
+ * @return boolean FALSE if improper input + */ + public function setDeclaredValue($v, $c) { + if (!empty($v) && !empty($c) && is_numeric($v) && is_string($c) && !is_numeric($c)){ + $this->options['ShipmentRequestDetails.ShippingServiceOptions.DeclaredValue.Amount'] = $v; + $this->options['ShipmentRequestDetails.ShippingServiceOptions.DeclaredValue.CurrencyCode'] = $c; + } else { + return false; + } + } + + /** + * Sets the option for whether or not the carrier will pick up the package. (Required) + * + * This method sets whether or not the carrier will pick up the package to be sent in the next request. + * This parameter is required for fetching a list of eligible services from Amazon. + * @param boolean $b [optional]Defaults to TRUE
+ * @return boolean FALSE if improper input + */ + public function setCarrierWillPickUp($b = true) { + if ($b) { + $v = 'true'; + } else { + $v = 'false'; + } + $this->options['ShipmentRequestDetails.ShippingServiceOptions.CarrierWillPickUp'] = $v; + } + + /** + * Sets all of the same Shipment details used by the given Amazon Merchant Shipment Creator object. + * @param AmazonMerchantShipmentCreator $objShipment Creator object with options already set
+ */ + public function setDetailsByCreator(AmazonMerchantShipmentCreator $obj) { + $this->resetDetails(); + + $options = $obj->getOptions(); + foreach($options as $op=>$val){ + if(preg_match("#ShipmentRequestDetails#",$op)){ + $this->options[$op] = $val; + } + } + } + + /** + * Resets the shipment detail options. + * + * Since shipment details are required parameters, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetDetails() { + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Fetches a list of eligible shipping Services from Amazon. + * + * Submits a GetEligibleShippingServices request to Amazon. Amazon will send + * one to three lists back as a response, which can be retrieved using getServiceList. + * Other methods are available for fetching specific values from the valid services list. + * The following parameters are required: Amazon order ID, item list, shipping address, + * package dimensions, shipment weight, delivery experience option, and carrier pick-up option. + * @return boolean FALSE if something goes wrong + */ + public function fetchServices(){ + if (!array_key_exists('ShipmentRequestDetails.AmazonOrderId',$this->options)){ + $this->log("Amazon Order ID must be set in order to fetch a service list",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ItemList.Item.1.OrderItemId',$this->options)){ + $this->log("Items must be set in order to fetch a service list",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ShipFromAddress.Name',$this->options)){ + $this->log("Shipping Address must be set in order to fetch a service list",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.PackageDimensions.Length',$this->options) && + !array_key_exists('ShipmentRequestDetails.PackageDimensions.PredefinedPackageDimensions',$this->options)){ + $this->log("Package Dimensions must be set in order to fetch a service list",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.Weight.Value',$this->options)){ + $this->log("Weight must be set in order to fetch a service list",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ShippingServiceOptions.DeliveryExperience',$this->options)){ + $this->log("Delivery Experience must be set in order to fetch a service list",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ShippingServiceOptions.CarrierWillPickUp',$this->options)){ + $this->log("Carrier Pick-Up Option must be set in order to fetch a service list",'Warning'); + return false; + } + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXML($xml); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXML($xml){ + $this->serviceList = array(); + $this->downList = array(); + $this->termsList = array(); + if (!$xml){ + return false; + } + if (isset($xml->ShippingServiceList)) { + $i = 0; + foreach($xml->ShippingServiceList->children() as $key=>$x){ + if ($key != 'ShippingService'){ + break; + } + + $this->serviceList[$i]['ShippingServiceName'] = (string)$x->ShippingServiceName; + $this->serviceList[$i]['CarrierName'] = (string)$x->CarrierName; + $this->serviceList[$i]['ShippingServiceId'] = (string)$x->ShippingServiceId; + $this->serviceList[$i]['ShippingServiceOfferId'] = (string)$x->ShippingServiceOfferId; + $this->serviceList[$i]['ShipDate'] = (string)$x->ShipDate; + if (isset($x->EarliestEstimatedDeliveryDate)) { + $this->serviceList[$i]['EarliestEstimatedDeliveryDate'] = (string)$x->EarliestEstimatedDeliveryDate; + } + if (isset($x->LatestEstimatedDeliveryDate)) { + $this->serviceList[$i]['LatestEstimatedDeliveryDate'] = (string)$x->LatestEstimatedDeliveryDate; + } + $this->serviceList[$i]['Rate']['Amount'] = (string)$x->Rate->Amount; + $this->serviceList[$i]['Rate']['CurrencyCode'] = (string)$x->Rate->CurrencyCode; + $this->serviceList[$i]['ShippingServiceOptions']['DeliveryExperience'] = (string)$x->ShippingServiceOptions->DeliveryExperience; + $this->serviceList[$i]['ShippingServiceOptions']['CarrierWillPickUp'] = (string)$x->ShippingServiceOptions->CarrierWillPickUp; + if (isset($x->ShippingServiceOptions->DeclaredValue)) { + $this->serviceList[$i]['ShippingServiceOptions']['DeclaredValue']['Amount'] = (string)$x->ShippingServiceOptions->DeclaredValue->Amount; + $this->serviceList[$i]['ShippingServiceOptions']['DeclaredValue']['CurrencyCode'] = (string)$x->ShippingServiceOptions->DeclaredValue->CurrencyCode; + } + + $i++; + } + } + if (isset($xml->TemporarilyUnavailableCarrierList)) { + $i = 0; + foreach($xml->TemporarilyUnavailableCarrierList->children() as $key=>$x){ + if ($key != 'TemporarilyUnavailableCarrier'){ + break; + } + + $this->downList[$i] = (string)$x->CarrierName; + $i++; + } + } + if (isset($xml->TermsAndConditionsNotAcceptedCarrierList)) { + $i = 0; + foreach($xml->TermsAndConditionsNotAcceptedCarrierList->children() as $key=>$x){ + if ($key != 'TermsAndConditionsNotAcceptedCarrier'){ + break; + } + + $this->termsList[$i] = (string)$x->CarrierName; + $i++; + } + } + } + + /** + * Returns the list of eligible services. + * The array for a single service can have the following fields: + *Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file.
+ * @param string $id [optional]The Shipment ID to set for the object.
+ * @param SimpleXMLElement $data [optional]XML data from Amazon to be parsed.
+ * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $id = null, $data = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + + if($id){ + $this->setShipmentId($id); + } + if ($data) { + $this->parseXML($data); + } + } + + /** + * Sets the Shipment ID. (Required) + * + * This method sets the shipment ID to be sent in the next request. + * This parameter is required for fetching the shipment from Amazon. + * @param string $ideither string or number
+ * @return boolean FALSE if improper input + */ + public function setShipmentId($id){ + if (is_string($id) || is_numeric($id)){ + $this->options['ShipmentId'] = $id; + } else { + $this->log("Tried to set ShipmentId to invalid value",'Warning'); + return false; + } + } + + /** + * Fetches the specified merchant-fulfilled shipment from Amazon. + * + * Submits a GetShipment request to Amazon. In order to do this, + * a shipment ID is required. Amazon will send + * the data back as a response, which can be retrieved using getShipment. + * Other methods are available for fetching specific values from the shipment. + * @return boolean FALSE if something goes wrong + */ + public function fetchShipment(){ + if (!array_key_exists('ShipmentId',$this->options)){ + $this->log("Shipment ID must be set in order to fetch it!",'Warning'); + return false; + } + + $this->options['Action'] = 'GetShipment'; + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXML($xml->$path); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXML($xml) { + if (!$xml || !$xml->Shipment){ + return false; + } + $d = $xml->Shipment; + $this->data['ShipmentId'] = (string)$d->ShipmentId; + $this->data['AmazonOrderId'] = (string)$d->AmazonOrderId; + if (isset($d->SellerOrderId)) { + $this->data['SellerOrderId'] = (string)$d->SellerOrderId; + } + $this->data['Status'] = (string)$d->Status; + if (isset($d->TrackingId)) { + $this->data['TrackingId'] = (string)$d->TrackingId; + } + $this->data['CreatedDate'] = (string)$d->CreatedDate; + if (isset($d->LastUpdatedDate)) { + $this->data['LastUpdatedDate'] = (string)$d->LastUpdatedDate; + } + $this->data['Weight']['Value'] = (string)$d->Weight->Value; + $this->data['Weight']['Unit'] = (string)$d->Weight->Unit; + $this->data['Insurance']['Amount'] = (string)$d->Insurance->Amount; + $this->data['Insurance']['CurrencyCode'] = (string)$d->Insurance->CurrencyCode; + if (isset($d->Label)) { + $this->data['Label']['Dimensions']['Length'] = (string)$d->Label->Dimensions->Length; + $this->data['Label']['Dimensions']['Width'] = (string)$d->Label->Dimensions->Width; + $this->data['Label']['Dimensions']['Unit'] = (string)$d->Label->Dimensions->Unit; + $this->data['Label']['FileContents']['Contents'] = (string)$d->Label->FileContents->Contents; + $this->data['Label']['FileContents']['FileType'] = (string)$d->Label->FileContents->FileType; + $this->data['Label']['FileContents']['Checksum'] = (string)$d->Label->FileContents->Checksum; + } + + $this->data['ItemList'] = array(); + foreach ($d->ItemList->children() as $x) { + $temp = array(); + $temp['OrderItemId'] = (string)$x->OrderItemId; + $temp['Quantity'] = (string)$x->Quantity; + $this->data['ItemList'][] = $temp; + } + if (isset($d->PackageDimensions->Length)) { + $this->data['PackageDimensions']['Length'] = (string)$d->PackageDimensions->Length; + $this->data['PackageDimensions']['Width'] = (string)$d->PackageDimensions->Width; + $this->data['PackageDimensions']['Height'] = (string)$d->PackageDimensions->Height; + $this->data['PackageDimensions']['Unit'] = (string)$d->PackageDimensions->Unit; + } + if (isset($d->PackageDimensions->PredefinedPackageDimensions)) { + $this->data['PackageDimensions']['PredefinedPackageDimensions'] = (string)$d->PackageDimensions->PredefinedPackageDimensions; + } + + //Ship From Address + $this->data['ShipFromAddress']['Name'] = (string)$d->ShipFromAddress->Name; + $this->data['ShipFromAddress']['AddressLine1'] = (string)$d->ShipFromAddress->AddressLine1; + if (isset($d->ShipFromAddress->AddressLine3)) { + $this->data['ShipFromAddress']['AddressLine2'] = (string)$d->ShipFromAddress->AddressLine2; + } + if (isset($d->ShipFromAddress->AddressLine3)) { + $this->data['ShipFromAddress']['AddressLine2'] = (string)$d->ShipFromAddress->AddressLine3; + } + if (isset($d->ShipFromAddress->DistrictOrCounty)) { + $this->data['ShipFromAddress']['DistrictOrCounty'] = (string)$d->ShipFromAddress->DistrictOrCounty; + } + $this->data['ShipFromAddress']['Email'] = (string)$d->ShipFromAddress->Email; + $this->data['ShipFromAddress']['City'] = (string)$d->ShipFromAddress->City; + if (isset($d->ShipFromAddress->StateOrProvinceCode)) { + $this->data['ShipFromAddress']['StateOrProvinceCode'] = (string)$d->ShipFromAddress->StateOrProvinceCode; + } + $this->data['ShipFromAddress']['PostalCode'] = (string)$d->ShipFromAddress->PostalCode; + $this->data['ShipFromAddress']['CountryCode'] = (string)$d->ShipFromAddress->CountryCode; + $this->data['ShipFromAddress']['Phone'] = (string)$d->ShipFromAddress->Phone; + + //Ship To Address + $this->data['ShipToAddress']['Name'] = (string)$d->ShipToAddress->Name; + $this->data['ShipToAddress']['AddressLine1'] = (string)$d->ShipToAddress->AddressLine1; + if (isset($d->ShipToAddress->AddressLine3)) { + $this->data['ShipToAddress']['AddressLine2'] = (string)$d->ShipToAddress->AddressLine2; + } + if (isset($d->ShipToAddress->AddressLine3)) { + $this->data['ShipToAddress']['AddressLine2'] = (string)$d->ShipToAddress->AddressLine3; + } + if (isset($d->ShipToAddress->DistrictOrCounty)) { + $this->data['ShipToAddress']['DistrictOrCounty'] = (string)$d->ShipToAddress->DistrictOrCounty; + } + $this->data['ShipToAddress']['Email'] = (string)$d->ShipToAddress->Email; + $this->data['ShipToAddress']['City'] = (string)$d->ShipToAddress->City; + if (isset($d->ShipToAddress->StateOrProvinceCode)) { + $this->data['ShipToAddress']['StateOrProvinceCode'] = (string)$d->ShipToAddress->StateOrProvinceCode; + } + $this->data['ShipToAddress']['PostalCode'] = (string)$d->ShipToAddress->PostalCode; + $this->data['ShipToAddress']['CountryCode'] = (string)$d->ShipToAddress->CountryCode; + $this->data['ShipToAddress']['Phone'] = (string)$d->ShipToAddress->Phone; + + //Service + $this->data['ShippingService']['ShippingServiceName'] = (string)$d->ShippingService->ShippingServiceName; + $this->data['ShippingService']['CarrierName'] = (string)$d->ShippingService->CarrierName; + $this->data['ShippingService']['ShippingServiceId'] = (string)$d->ShippingService->ShippingServiceId; + $this->data['ShippingService']['ShippingServiceOfferId'] = (string)$d->ShippingService->ShippingServiceOfferId; + $this->data['ShippingService']['ShipDate'] = (string)$d->ShippingService->ShipDate; + if (isset($d->ShippingService->EarliestEstimatedDeliveryDate)) { + $this->data['ShippingService']['EarliestEstimatedDeliveryDate'] = (string)$d->ShippingService->EarliestEstimatedDeliveryDate; + } + if (isset($d->ShippingService->LatestEstimatedDeliveryDate)) { + $this->data['ShippingService']['LatestEstimatedDeliveryDate'] = (string)$d->ShippingService->LatestEstimatedDeliveryDate; + } + $this->data['ShippingService']['Rate']['Amount'] = (string)$d->ShippingService->Rate->Amount; + $this->data['ShippingService']['Rate']['CurrencyCode'] = (string)$d->ShippingService->Rate->CurrencyCode; + $this->data['ShippingService']['DeliveryExperience'] = (string)$d->ShippingService->ShippingServiceOptions->DeliveryExperience; + $this->data['ShippingService']['CarrierWillPickUp'] = (string)$d->ShippingService->ShippingServiceOptions->CarrierWillPickUp; + if (isset($d->ShippingService->ShippingServiceOptions->DeclaredValue)) { + $this->data['ShippingService']['DeclaredValue']['Amount'] = (string)$d->ShippingService->ShippingServiceOptions->DeclaredValue->Amount; + $this->data['ShippingService']['DeclaredValue']['CurrencyCode'] = (string)$d->ShippingService->ShippingServiceOptions->DeclaredValue->CurrencyCode; + } + } + + /** + * Cancels a merchant-fulfilled shipment on Amazon. + * + * Submits a CancelShipment request to Amazon. In order to do this, + * a shipment ID is required. Amazon will send back data about the shipment + * as a response, including its status, which can be retrieved using getData. + * Other methods are available for fetching specific values from the shipment. + * @return boolean TRUE if the cancellation was successful, FALSE if something goes wrong + */ + public function cancelShipment(){ + if (!array_key_exists('ShipmentId',$this->options)){ + $this->log("Shipment ID must be set in order to cancel it!",'Warning'); + return false; + } + + $this->options['Action'] = 'CancelShipment'; + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXML($xml->$path); + } + + /** + * Returns the shipment data. + * + * This method will return FALSE if the shipment data has not been retrieved yet. + * @return array|boolean multi-dimensional array, or FALSE if shipment not set yet + */ + public function getData(){ + if (isset($this->data)){ + return $this->data; + } else { + return false; + } + } + + /** + * Returns the Amazon-generated shipment ID. + * + * This method will return FALSE if the shipment ID has not been set yet. + * @return string|boolean single value, or FALSE if shipment ID not set yet + */ + public function getShipmentId(){ + if (isset($this->data['ShipmentId'])){ + return $this->data['ShipmentId']; + } else { + return false; + } + } + + /** + * Returns the Amazon Order ID. + * + * This method will return FALSE if the order ID has not been set yet. + * @return string|boolean single value, or FALSE if order ID not set yet + */ + public function getAmazonOrderId(){ + if (isset($this->data['AmazonOrderId'])){ + return $this->data['AmazonOrderId']; + } else { + return false; + } + } + + /** + * Returns the Seller's Order ID. + * + * This method will return FALSE if the order ID has not been set yet. + * @return string|boolean single value, or FALSE if order ID not set yet + */ + public function getSellerOrderId(){ + if (isset($this->data['SellerOrderId'])){ + return $this->data['SellerOrderId']; + } else { + return false; + } + } + + /** + * Returns a list of Items for the Shipment. + * + * This method will return FALSE if the items have not been set yet. + * The array returned contains one or more arrays with the following fields: + *set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if weight not set yet + */ + public function getWeight($only = false){ + if (isset($this->data['Weight'])){ + if ($only){ + return $this->data['Weight']['Value']; + } else { + return $this->data['Weight']; + } + } else { + return false; + } + } + + /** + * Returns the insurance amount. + * + * This method will return FALSE if the insurance amount has not been set yet. + * If an array is returned, it will have the fields Amount and CurrencyCode. + * @param boolean $only [optional]set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if insurance amount not set yet + */ + public function getInsurance($only = false){ + if (isset($this->data['Insurance'])){ + if ($only){ + return $this->data['Insurance']['Amount']; + } else { + return $this->data['Insurance']; + } + } else { + return false; + } + } + + /** + * Returns an array containing all of the Service information. + * + * This method will return FALSE if the package dimensions have not been set yet. + * The returned array will have the following fields: + *set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if service not set yet + * @see getService + */ + public function getServiceRate($only = false){ + if (isset($this->data['ShippingService'])){ + if ($only){ + return $this->data['ShippingService']['Rate']['Amount']; + } else { + return $this->data['ShippingService']['Rate']; + } + } else { + return false; + } + } + + /** + * Returns the declared value. + * + * This method will return FALSE if the declared value has not been set yet. + * If an array is returned, it will have the fields Amount and CurrencyCode. + * @param boolean $only [optional]set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if declared value not set yet + * @see getService + */ + public function getDeclaredValue($only = false){ + if (isset($this->data['ShippingService']['DeclaredValue'])){ + if ($only){ + return $this->data['ShippingService']['DeclaredValue']['Amount']; + } else { + return $this->data['ShippingService']['DeclaredValue']; + } + } else { + return false; + } + } + + /** + * Returns an array containing all of the Label information. + * + * This method will return FALSE if the label has not been set yet. + * The returned array will have the following fields: + *Set to TRUE to get the raw, double-encoded file contents.
+ * @return array|boolean multi-dimensional array, or FALSE if label not set yet + */ + public function getLabelData($raw = FALSE){ + if (isset($this->data['Label'])){ + if ($raw) { + return $this->data['Label']; + } + //decode label file automatically + $r = $this->data['Label']; + $convert = $this->getLabelFileContents(FALSE); + if ($convert) { + $r['FileContents']['Contents'] = $convert; + } + return $r; + } else { + return false; + } + } + + /** + * Returns the file contents for the Label. + * + * This method will return FALSE if the status has not been set yet. + * @param boolean $raw [optional]Set to TRUE to get the raw, double-encoded file contents.
+ * @return string|boolean single value, or FALSE if status not set yet + */ + public function getLabelFileContents($raw = FALSE){ + if (isset($this->data['Label']['FileContents']['Contents'])){ + if ($raw) { + return $this->data['Label']['FileContents']['Contents']; + } + try { + return gzdecode(base64_decode($this->data['Label']['FileContents']['Contents'])); + } catch (Exception $ex) { + $this->log('Failed to convert label file, file might be corrupt: '.$ex->getMessage(), 'Urgent'); + } + return false; + } else { + return false; + } + } + + /** + * Returns the Shipment's Status. + * + * This method will return FALSE if the status has not been set yet. + * @return string|boolean single value, or FALSE if status not set yet + */ + public function getStatus(){ + if (isset($this->data['Status'])){ + return $this->data['Status']; + } else { + return false; + } + } + + /** + * Returns the Tracking ID. + * + * This method will return FALSE if the tracking ID has not been set yet. + * @return string|boolean single value, or FALSE if tracking ID not set yet + */ + public function getTrackingId(){ + if (isset($this->data['TrackingId'])){ + return $this->data['TrackingId']; + } else { + return false; + } + } + + /** + * Returns the date at which the shipment was created. + * + * This method will return FALSE if the tracking ID has not been set yet. + * @return string|boolean timestamp, or FALSE if tracking ID not set yet + */ + public function getDateCreated(){ + if (isset($this->data['CreatedDate'])){ + return $this->data['CreatedDate']; + } else { + return false; + } + } + + /** + * Returns the date at which the shipment was last updated. + * + * This method will return FALSE if the tracking ID has not been set yet. + * @return string|boolean timestamp, or FALSE if tracking ID not set yet + */ + public function getDateLastUpdated(){ + if (isset($this->data['LastUpdatedDate'])){ + return $this->data['LastUpdatedDate']; + } else { + return false; + } + } +} diff --git a/includes/classes/AmazonMerchantShipmentCreator.php b/includes/classes/AmazonMerchantShipmentCreator.php new file mode 100644 index 00000000..8a1f7f51 --- /dev/null +++ b/includes/classes/AmazonMerchantShipmentCreator.php @@ -0,0 +1,564 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + + $this->options['Action'] = 'CreateShipment'; + } + + /** + * Sets the Amazon Order ID. (Required) + * + * This method sets the Amazon Order ID to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * @param string $idAmazon Order ID
+ * @return boolean FALSE if improper input + */ + public function setOrderId($id) { + if (is_string($id)){ + $this->options['ShipmentRequestDetails.AmazonOrderId'] = $id; + } else { + $this->log("Tried to set AmazonOrderId to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the Seller Order ID. (Optional) + * + * This method sets the Seller Order ID to be sent in the next request. + * @param string $idMaximum 64 characters.
+ * @return boolean FALSE if improper input + */ + public function setSellerOrderId($id) { + if (is_string($id) || is_numeric($id)){ + $this->options['ShipmentRequestDetails.SellerOrderId'] = $id; + } else { + $this->log("Tried to set SellerOrderId to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the items. (Required) + * + * This method sets the items to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * The array provided should contain a list of arrays, each with the following fields: + *See above.
+ * @return boolean FALSE if improper input + */ + public function setItems($a){ + if (is_null($a) || is_string($a) || !$a){ + $this->log("Tried to set Items to invalid values",'Warning'); + return false; + } + $this->resetItems(); + $i = 1; + foreach ($a as $x){ + if (is_array($x) && isset($x['OrderItemId']) && isset($x['Quantity'])){ + $this->options['ShipmentRequestDetails.ItemList.Item.'.$i.'.OrderItemId'] = $x['OrderItemId']; + $this->options['ShipmentRequestDetails.ItemList.Item.'.$i.'.Quantity'] = $x['Quantity']; + $i++; + } else { + $this->resetItems(); + $this->log("Tried to set Items with invalid array",'Warning'); + return false; + } + } + } + + /** + * Resets the item options. + * + * Since the list of items is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetItems(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails.ItemList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the address. (Required) + * + * This method sets the shipper's address to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * The array provided should have the following fields: + *See above.
+ * @return boolean FALSE if improper input + */ + public function setAddress($a){ + if (empty($a) || !is_array($a)){ + $this->log("Tried to set ShipFromAddress to invalid values",'Warning'); + return false; + } + $this->resetAddress(); + $this->options['ShipmentRequestDetails.ShipFromAddress.Name'] = $a['Name']; + $this->options['ShipmentRequestDetails.ShipFromAddress.AddressLine1'] = $a['AddressLine1']; + if (isset($a['AddressLine2'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.AddressLine2'] = $a['AddressLine2']; + } + if (isset($a['AddressLine3'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.AddressLine3'] = $a['AddressLine3']; + } + if (isset($a['DistrictOrCounty'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.DistrictOrCounty'] = $a['DistrictOrCounty']; + } + $this->options['ShipmentRequestDetails.ShipFromAddress.Email'] = $a['Email']; + $this->options['ShipmentRequestDetails.ShipFromAddress.City'] = $a['City']; + if (isset($a['StateOrProvinceCode'])){ + $this->options['ShipmentRequestDetails.ShipFromAddress.StateOrProvinceCode'] = $a['StateOrProvinceCode']; + } + $this->options['ShipmentRequestDetails.ShipFromAddress.PostalCode'] = $a['PostalCode']; + $this->options['ShipmentRequestDetails.ShipFromAddress.CountryCode'] = $a['CountryCode']; + $this->options['ShipmentRequestDetails.ShipFromAddress.Phone'] = $a['Phone']; + } + + /** + * Resets the address options. + * + * Since address is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetAddress(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails.ShipFromAddress#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the package dimensions. (Required) + * + * This method sets the package dimensions to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * If this parameter is set, the predefined package name cannot be set. + * The array provided should have the following fields: + *See above.
+ * @return boolean FALSE if improper input + */ + public function setPackageDimensions($d) { + if (empty($d) || !is_array($d)){ + $this->log("Tried to set PackageDimensions to invalid values",'Warning'); + return false; + } + $this->resetPackageDimensions(); + $this->options['ShipmentRequestDetails.PackageDimensions.Length'] = $d['Length']; + $this->options['ShipmentRequestDetails.PackageDimensions.Width'] = $d['Width']; + $this->options['ShipmentRequestDetails.PackageDimensions.Height'] = $d['Height']; + $this->options['ShipmentRequestDetails.PackageDimensions.Unit'] = $d['Unit']; + } + + /** + * Sets the Predefined Package Dimensions. (Required) + * + * This method sets the predefined package name to be sent in the next request. + * Package dimensions are required for creating a shipment on Amazon. + * This parameter can be used instead of setting the package dimensions. + * If this parameter is set, the manual package dimensions cannot be set. + * @param string $sA value from the list of valid package names. + * See the comment inside the function for the complete list.
+ * @return boolean FALSE if improper input + */ + public function setPredefinedPackage($s) { + $this->resetPackageDimensions(); + if (is_string($s) && $s){ + $this->options['ShipmentRequestDetails.PackageDimensions.PredefinedPackageDimensions'] = $s; + } else { + return false; + } + /* + * List of valid Predefined Packages: + * FedEx_Box_10kg ~ 15.81 x 12.94 x 10.19 in + * FedEx_Box_25kg ~ 54.80 x 42.10 x 33.50 in + * FedEx_Box_Extra_Large_1 ~ 11.88 x 11.00 x 10.75 in + * FedEx_Box_Extra_Large_2 ~ 15.75 x 14.13 x 6.00 in + * FedEx_Box_Large_1 ~ 17.50 x 12.38 x 3.00 in + * FedEx_Box_Large_2 ~ 11.25 x 8.75 x 7.75 in + * FedEx_Box_Medium_1 ~ 13.25 x 11.50 x 2.38 in + * FedEx_Box_Medium_2 ~ 11.25 x 8.75 x 4.38 in + * FedEx_Box_Small_1 ~ 12.38 x 10.88 x 1.50 in + * FedEx_Box_Small_2 ~ 11.25 x 8.75 x 4.38 in + * FedEx_Envelope ~ 12.50 x 9.50 x 0.80 in + * FedEx_Padded_Pak ~ 11.75 x 14.75 x 2.00 in + * FedEx_Pak_1 ~ 15.50 x 12.00 x 0.80 in + * FedEx_Pak_2 ~ 12.75 x 10.25 x 0.80 in + * FedEx_Tube ~ 38.00 x 6.00 x 6.00 in + * FedEx_XL_Pak ~ 17.50 x 20.75 x 2.00 in + * UPS_Box_10kg ~ 41.00 x 33.50 x 26.50 cm + * UPS_Box_25kg ~ 48.40 x 43.30 x 35.00 cm + * UPS_Express_Box ~ 46.00 x 31.50 x 9.50 cm + * UPS_Express_Box_Large ~ 18.00 x 13.00 x 3.00 in + * UPS_Express_Box_Medium ~ 15.00 x 11.00 x 3.00 in + * UPS_Express_Box_Small ~ 13.00 x 11.00 x 2.00 in + * UPS_Express_Envelope ~ 12.50 x 9.50 x 2.00 in + * UPS_Express_Hard_Pak ~ 14.75 x 11.50 x 2.00 in + * UPS_Express_Legal_Envelope ~ 15.00 x 9.50 x 2.00 in + * UPS_Express_Pak ~ 16.00 x 12.75 x 2.00 in + * UPS_Express_Tube ~ 97.00 x 19.00 x 16.50 cm + * UPS_Laboratory_Pak ~ 17.25 x 12.75 x 2.00 in + * UPS_Pad_Pak ~ 14.75 x 11.00 x 2.00 in + * UPS_Pallet ~ 120.00 x 80.00 x 200.00 cm + * USPS_Card ~ 6.00 x 4.25 x 0.01 in + * USPS_Flat ~ 15.00 x 12.00 x 0.75 in + * USPS_FlatRateCardboardEnvelope ~ 12.50 x 9.50 x 4.00 in + * USPS_FlatRateEnvelope ~ 12.50 x 9.50 x 4.00 in + * USPS_FlatRateGiftCardEnvelope ~ 10.00 x 7.00 x 4.00 in + * USPS_FlatRateLegalEnvelope ~ 15.00 x 9.50 x 4.00 in + * USPS_FlatRatePaddedEnvelope ~ 12.50 x 9.50 x 4.00 in + * USPS_FlatRateWindowEnvelope ~ 10.00 x 5.00 x 4.00 in + * USPS_LargeFlatRateBoardGameBox ~ 24.06 x 11.88 x 3.13 in + * USPS_LargeFlatRateBox ~ 12.25 x 12.25 x 6.00 in + * USPS_Letter ~ 11.50 x 6.13 x 0.25 in + * USPS_MediumFlatRateBox1 ~ 11.25 x 8.75 x 6.00 in + * USPS_MediumFlatRateBox2 ~ 14.00 x 12.00 x 3.50 in + * USPS_RegionalRateBoxA1 ~ 10.13 x 7.13 x 5.00 in + * USPS_RegionalRateBoxA2 ~ 13.06 x 11.06 x 2.50 in + * USPS_RegionalRateBoxB1 ~ 16.25 x 14.50 x 3.00 in + * USPS_RegionalRateBoxB2 ~ 12.25 x 10.50 x 5.50 in + * USPS_RegionalRateBoxC ~ 15.00 x 12.00 x 12.00 in + * USPS_SmallFlatRateBox ~ 8.69 x 5.44 x 1.75 in + * USPS_SmallFlatRateEnvelope ~ 10.00 x 6.00 x 4.00 in + */ + } + + /** + * Resets the package dimension options. + * + * Since dimensions are a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetPackageDimensions(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ShipmentRequestDetails.PackageDimensions#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the weight. (Required) + * + * This method sets the shipment weight to be sent in the next request. + * @param string $vDecimal number
+ * @param string $u"oz" for ounces, or "g" for grams, defaults to grams
+ * @return boolean FALSE if improper input + */ + public function setWeight($v, $u = 'g') { + if (!empty($v) && !empty($u) && is_numeric($v) && ($u == 'oz' || $u == 'g')){ + $this->options['ShipmentRequestDetails.Weight.Value'] = $v; + $this->options['ShipmentRequestDetails.Weight.Unit'] = $u; + } else { + return false; + } + } + + /** + * Sets the date by which the package must arrive. (Optional) + * + * This method sets the maximum date to be sent in the next request. + * If this parameter is set, Amazon will only give services which + * will be able to deliver by the given date. + * @param string $dA time string
+ * @return boolean FALSE if improper input + */ + public function setMaxArrivalDate($d) { + try{ + $this->options['ShipmentRequestDetails.MustArriveByDate'] = $this->genTime($d); + } catch (Exception $e){ + unset($this->options['ShipmentRequestDetails.MustArriveByDate']); + $this->log('Error: '.$e->getMessage(), 'Warning'); + return false; + } + } + + /** + * Sets the date on which the package will be shipped. (Optional) + * + * This method sets the ship date to be sent in the next request. + * @param string $dA time string
+ * @return boolean FALSE if improper input + */ + public function setShipDate($d) { + try{ + $this->options['ShipmentRequestDetails.ShipDate'] = $this->genTime($d); + } catch (Exception $e){ + unset($this->options['ShipmentRequestDetails.ShipDate']); + $this->log('Error: '.$e->getMessage(), 'Warning'); + return false; + } + } + + /** + * Sets the Delivery Experience Option. (Required) + * + * This method sets the delivery experience shipping option to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * @param string $s"DeliveryConfirmationWithAdultSignature", + * "DeliveryConfirmationWithSignature", + * "DeliveryConfirmationWithoutSignature", + * or "NoTracking"
+ * @return boolean FALSE if improper input + */ + public function setDeliveryOption($s) { + $options = array( + 'DeliveryConfirmationWithAdultSignature', + 'DeliveryConfirmationWithSignature', + 'DeliveryConfirmationWithoutSignature', + 'NoTracking' + ); + if (in_array($s, $options)){ + $this->options['ShipmentRequestDetails.ShippingServiceOptions.DeliveryExperience'] = $s; + } else { + $this->log("Tried to set DeliveryExperience to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the Declared Value. (Optional) + * + * This method sets the declared value to be sent in the next request. + * If this parameter is set and is higher than the carrier's minimum insurance amount, + * the seller will be charged more for the additional insurance. + * @param string $vMoney amount
+ * @param string $cISO 4217 currency code (ex: USD)
+ * @return boolean FALSE if improper input + */ + public function setDeclaredValue($v, $c) { + if (!empty($v) && !empty($c) && is_numeric($v) && is_string($c) && !is_numeric($c)){ + $this->options['ShipmentRequestDetails.ShippingServiceOptions.DeclaredValue.Amount'] = $v; + $this->options['ShipmentRequestDetails.ShippingServiceOptions.DeclaredValue.CurrencyCode'] = $c; + } else { + return false; + } + } + + /** + * Sets the option for whether or not the carrier will pick up the package. (Required) + * + * This method sets whether or not the carrier will pick up the package to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * @param boolean $b [optional]Defaults to TRUE
+ * @return boolean FALSE if improper input + */ + public function setCarrierWillPickUp($b = true) { + if ($b) { + $v = 'true'; + } else { + $v = 'false'; + } + $this->options['ShipmentRequestDetails.ShippingServiceOptions.CarrierWillPickUp'] = $v; + } + + /** + * Sets the Shipping Service ID. (Required) + * + * This method sets the shipping service ID to be sent in the next request. + * This parameter is required for creating a shipment on Amazon. + * @param string $idService ID
+ * @return boolean FALSE if improper input + */ + public function setService($id) { + if (is_string($id)){ + $this->options['ShippingServiceId'] = $id; + } else { + $this->log("Tried to set ShippingServiceId to invalid value",'Warning'); + return false; + } + } + + /** + * Sets the Shipping Service Offer ID. (Optional) + * + * This method sets the shipping service offer ID to be sent in the next request. + * @param string $idService Offer ID
+ * @return boolean FALSE if improper input + */ + public function setServiceOffer($id) { + if (is_string($id)){ + $this->options['ShippingServiceOfferId'] = $id; + } else { + $this->log("Tried to set ShippingServiceOfferId to invalid value",'Warning'); + return false; + } + } + + /** + * Fetches eligible services for the shipment from Amazon using the current options. + * + * See the AmazonMerchantServiceList class for more information on the returned object. + * The following parameters are required: Amazon order ID, item list, shipping address, + * package dimensions, shipment weight, delivery experience option, and carrier pick-up option. + * @return AmazonMerchantServiceList container for services + */ + public function fetchServices() { + $services = new AmazonMerchantServiceList($this->storeName, $this->mockMode, $this->mockFiles, $this->config); + $services->mockIndex = $this->mockIndex; + $services->setLogPath($this->logpath); + $services->setDetailsByCreator($this); + $services->fetchServices(); + return $services; + } + + /** + * Fetches a list of eligible shipping Services from Amazon. + * + * Submits a CreateShipment request to Amazon. Amazon will send back information + * about the shipment as a response, which can be retrieved using getShipment. + * Other methods are available for fetching specific values from the valid services list. + * The following parameters are required: Amazon order ID, item list, shipping address, + * package dimensions, shipment weight, delivery experience option, carrier pick-up option, + * and service ID. + * @return boolean FALSE if something goes wrong + */ + public function createShipment(){ + if (!array_key_exists('ShipmentRequestDetails.AmazonOrderId',$this->options)){ + $this->log("Amazon Order ID must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ItemList.Item.1.OrderItemId',$this->options)){ + $this->log("Items must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ShipFromAddress.Name',$this->options)){ + $this->log("Shipping Address must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.PackageDimensions.Length',$this->options) && + !array_key_exists('ShipmentRequestDetails.PackageDimensions.PredefinedPackageDimensions',$this->options)){ + $this->log("Package Dimensions must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.Weight.Value',$this->options)){ + $this->log("Weight must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ShippingServiceOptions.DeliveryExperience',$this->options)){ + $this->log("Delivery Experience must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShipmentRequestDetails.ShippingServiceOptions.CarrierWillPickUp',$this->options)){ + $this->log("Carrier Pick-Up Option must be set in order to create a shipment",'Warning'); + return false; + } + if (!array_key_exists('ShippingServiceId',$this->options)){ + $this->log("Shipping Service must be set in order to create a shipment",'Warning'); + return false; + } + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXML($xml); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXML($xml){ + if (!$xml){ + return false; + } + + $this->shipment = new AmazonMerchantShipment($this->storeName, NULL, $xml, $this->mockMode, $this->mockFiles, $this->config); + $this->shipment->setLogPath($this->logpath); + $this->shipment->mockIndex = $this->mockIndex; + } + + /** + * Returns the object containing information about the shipment. + * @return AmazonMerchantShipment|boolean shipment object, or FALSE if the shipment has not been created yet + */ + public function getShipment() { + if (!isset($this->shipment)) { + return false; + } + return $this->shipment; + } +} diff --git a/includes/classes/AmazonOrder.php b/includes/classes/AmazonOrder.php index 28f3ccd6..266c841c 100644 --- a/includes/classes/AmazonOrder.php +++ b/includes/classes/AmazonOrder.php @@ -24,7 +24,7 @@ * Order ID is required. */ class AmazonOrder extends AmazonOrderCore{ - private $data; + protected $data; /** * AmazonOrder object gets the details for a single object from Amazon. @@ -143,7 +143,7 @@ public function fetchItems($token = false){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -216,8 +216,8 @@ protected function parseXML($xml){ if (isset($xml->BuyerEmail)){ $d['BuyerEmail'] = (string)$xml->BuyerEmail; } - if (isset($xml->ShipServiceLevelCategory)){ - $d['ShipServiceLevelCategory'] = (string)$xml->ShipServiceLevelCategory; + if (isset($xml->ShipmentServiceLevelCategory)){ + $d['ShipmentServiceLevelCategory'] = (string)$xml->ShipmentServiceLevelCategory; } if (isset($xml->CbaDisplayableShippingLabel)){ $d['CbaDisplayableShippingLabel'] = (string)$xml->CbaDisplayableShippingLabel; @@ -243,6 +243,18 @@ protected function parseXML($xml){ if (isset($xml->LatestDeliveryDate)){ $d['LatestDeliveryDate'] = (string)$xml->LatestDeliveryDate; } + if (isset($xml->IsBusinessOrder)){ + $d['IsBusinessOrder'] = (string)$xml->IsBusinessOrder; + } + if (isset($xml->PurchaseOrderNumber)){ + $d['PurchaseOrderNumber'] = (string)$xml->PurchaseOrderNumber; + } + if (isset($xml->IsPrime)){ + $d['IsPrime'] = (string)$xml->IsPrime; + } + if (isset($xml->IsPremiumOrder)){ + $d['IsPremiumOrder'] = (string)$xml->IsPremiumOrder; + } $this->data = $d; } @@ -271,7 +283,8 @@ protected function parseXML($xml){ *either string or number
+ * @param string $idAmazon Order ID
* @return boolean FALSE if improper input */ public function setOrderId($id){ @@ -114,7 +115,7 @@ public function setOrderId($id){ * the data back as a response, which can be retrieved using getItems. * Other methods are available for fetching specific values from the order. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchItems($r = true){ @@ -140,8 +141,10 @@ public function fetchItems($r = true){ if (is_null($xml->AmazonOrderId)){ $this->log("You just got throttled.",'Warning'); return false; - } else if (isset($this->options['AmazonOrderId']) && $this->options['AmazonOrderId'] && $this->options['AmazonOrderId'] != $xml->AmazonOrderId){ - $this->log('You grabbed the wrong Order\'s items! - '.$this->options['AmazonOrderId'].' =/= '.$xml->AmazonOrderId,'Urgent'); + } + $this->orderId = (string)$xml->AmazonOrderId; + if (!empty($this->options['AmazonOrderId']) && $this->options['AmazonOrderId'] != $this->orderId){ + $this->log('You grabbed the wrong Order\'s items! - '.$this->options['AmazonOrderId'].' =/= '.$this->orderId,'Urgent'); } $this->parseXML($xml->OrderItems); @@ -181,7 +184,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -200,6 +203,17 @@ protected function parseXML($xml){ if (isset($item->QuantityShipped)){ $this->itemList[$n]['QuantityShipped'] = (string)$item->QuantityShipped; } + if (isset($item->BuyerCustomizedInfo->CustomizedURL)){ + $this->itemList[$n]['BuyerCustomizedInfo'] = (string)$item->BuyerCustomizedInfo->CustomizedURL; + } + if (isset($item->PointsGranted)){ + $this->itemList[$n]['PointsGranted']['PointsNumber'] = (string)$item->PointsGranted->PointsNumber; + $this->itemList[$n]['PointsGranted']['Amount'] = (string)$item->PointsGranted->PointsMonetaryValue->Amount; + $this->itemList[$n]['PointsGranted']['CurrencyCode'] = (string)$item->PointsGranted->PointsMonetaryValue->CurrencyCode; + } + if (isset($item->PriceDesignation)){ + $this->itemList[$n]['PriceDesignation'] = (string)$item->PriceDesignation; + } if (isset($item->GiftMessageText)){ $this->itemList[$n]['GiftMessageText'] = (string)$item->GiftMessageText; } @@ -286,6 +300,20 @@ protected function parseXML($xml){ } } + + /** + * Returns the order ID for the items. + * + * This method will return FALSE if the list has not yet been filled. + * @return string|boolean single value, or FALSE if not set yet + */ + public function getOrderId(){ + if (isset($this->orderId)){ + return $this->orderId; + } else { + return false; + } + } /** * Returns the specified order item, or all of them. @@ -419,6 +447,57 @@ public function getQuantityShipped($i = 0){ return false; } } + + /** + * Returns the URL for the ZIP file containing the customized options for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getCustomizedInfo($i = 0){ + if (isset($this->itemList[$i]['BuyerCustomizedInfo'])){ + return $this->itemList[$i]['BuyerCustomizedInfo']; + } else { + return false; + } + } + + /** + * Returns the number of Amazon Points granted for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * If an array is returned, it will have the fields PointsNumber, Amount and CurrencyCode. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param boolean $only [optional]set to TRUE to get only the number of points
+ * @return array|string|boolean array, single value, or FALSE if Non-numeric index + */ + public function getPointsGranted($i = 0, $only = false){ + if (isset($this->itemList[$i]['PointsGranted'])){ + if ($only){ + return $this->itemList[$i]['PointsGranted']['PointsNumber']; + } else { + return $this->itemList[$i]['PointsGranted']; + } + } else { + return false; + } + } + + /** + * Returns the price designation for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getPriceDesignation($i = 0){ + if (isset($this->itemList[$i]['PriceDesignation'])){ + return $this->itemList[$i]['PriceDesignation']; + } else { + return false; + } + } /** * Returns the seller SKU for the specified entry. diff --git a/includes/classes/AmazonOrderList.php b/includes/classes/AmazonOrderList.php index b498d70d..20e32185 100644 --- a/includes/classes/AmazonOrderList.php +++ b/includes/classes/AmazonOrderList.php @@ -25,11 +25,11 @@ * are required. This object can use tokens when retrieving the list. */ class AmazonOrderList extends AmazonOrderCore implements Iterator{ - private $orderList; - private $i = 0; + protected $orderList; + protected $i = 0; protected $tokenFlag = false; protected $tokenUseFlag = false; - private $index = 0; + protected $index = 0; /** * Amazon Order Lists pull a set of Orders and turn them into an array of AmazonOrder objects. @@ -47,17 +47,7 @@ class AmazonOrderList extends AmazonOrderCore implements Iterator{ public function __construct($s = null, $mock = false, $m = null, $config = null){ parent::__construct($s, $mock, $m, $config); include($this->env); - if (file_exists($this->config)){ - include($this->config); - } else { - throw new Exception('Config file does not exist!'); - } - - if(isset($store[$this->storeName]) && array_key_exists('marketplaceId', $store[$this->storeName])){ - $this->options['MarketplaceId.Id.1'] = $store[$this->storeName]['marketplaceId']; - } else { - $this->log("Marketplace ID is missing",'Urgent'); - } + $this->resetMarketplaceFilter(); if(isset($THROTTLE_LIMIT_ORDERLIST)) { $this->throttleLimit = $THROTTLE_LIMIT_ORDERLIST; @@ -151,7 +141,7 @@ public function setLimits($mode,$lower = null,$upper = null){ * Setting this parameter tells Amazon to only return Orders with statuses that match * those in the list. If this parameter is not set, Amazon will return * Orders of any status. - * @param array|string $sA list of Order Statuses, or a single status string.
+ * @param array|string $listA list of Order Statuses, or a single status string.
* @return boolean FALSE if improper input */ public function setOrderStatusFilter($list){ @@ -185,6 +175,61 @@ public function resetOrderStatusFilter(){ } } } + + /** + * Sets the marketplace(s). (Optional) + * + * This method sets the list of Marketplaces to be sent in the next request. + * Setting this parameter tells Amazon to only return Orders made in marketplaces that match + * those in the list. If this parameter is not set, Amazon will return + * Orders belonging to the current store's default marketplace. + * @param array|string $listA list of Marketplace IDs, or a single Marketplace ID.
+ * @return boolean FALSE if improper input + */ + public function setMarketplaceFilter($list){ + if (is_string($list)){ + //if single string, set as filter + $this->resetMarketplaceFilter(); + $this->options['MarketplaceId.Id.1'] = $list; + } else if (is_array($list)){ + //if array of strings, set all filters + $this->resetMarketplaceFilter(); + $i = 1; + foreach($list as $x){ + $this->options['MarketplaceId.Id.'.$i] = $x; + $i++; + } + } else { + return false; + } + } + + /** + * Removes marketplace ID options and sets the current store's marketplace instead. + * + * Use this in case you change your mind and want to remove the Marketplace ID + * parameters you previously set. + * @throws Exception if config file is missing + */ + public function resetMarketplaceFilter(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#MarketplaceId#",$op)){ + unset($this->options[$op]); + } + } + + //reset to store's default marketplace + if (file_exists($this->config)){ + include($this->config); + } else { + throw new Exception('Config file does not exist!'); + } + if(isset($store[$this->storeName]) && array_key_exists('marketplaceId', $store[$this->storeName])){ + $this->options['MarketplaceId.Id.1'] = $store[$this->storeName]['marketplaceId']; + } else { + $this->log("Marketplace ID is missing",'Urgent'); + } + } /** * Sets (or resets) the Fulfillment Channel Filter @@ -208,7 +253,7 @@ public function setFulfillmentChannelFilter($filter){ * Setting this parameter tells Amazon to only return Orders with payment methods * that match those in the list. If this parameter is not set, Amazon will return * Orders with any payment method. - * @param array|string $sA list of Payment Methods, or a single method string.
+ * @param array|string $listA list of Payment Methods, or a single method string.
* @return boolean FALSE if improper input */ public function setPaymentMethodFilter($list){ @@ -246,10 +291,10 @@ public function resetPaymentMethodFilter(){ * Sets (or resets) the email address. (Optional) * * This method sets the email address to be sent in the next request. - * Setting this parameter tells Amazon to only return Orders with addresses - * that match the address given. If this parameter is set, the following options + * Setting this parameter tells Amazon to only return Orders with email addresses + * that match the email address given. If this parameter is set, the following options * will be removed: SellerOrderId, OrderStatus, PaymentMethod, FulfillmentChannel, LastUpdatedAfter, LastUpdatedBefore. - * @param string $sA single address string. Set to NULL to remove the option.
+ * @param string $filterA single email address string. Set to NULL to remove the option.
* @return boolean FALSE if improper input */ public function setEmailFilter($filter){ @@ -272,11 +317,11 @@ public function setEmailFilter($filter){ /** * Sets (or resets) the seller order ID(s). (Optional) * - * This method sets the list of seller order IDs to be sent in the next request. - * Setting this parameter tells Amazon to only return Orders with addresses - * that match those in the list. If this parameter is set, the following options + * This method sets the list of seller order ID to be sent in the next request. + * Setting this parameter tells Amazon to only return Orders with seller order IDs + * that match the seller order ID given. If this parameter is set, the following options * will be removed: BuyerEmail, OrderStatus, PaymentMethod, FulfillmentChannel, LastUpdatedAfter, LastUpdatedBefore. - * @param array|string $sA list of Payment Methods, or a single type string. Set to NULL to remove the option.
+ * @param array|string $filterA single seller order ID. Set to NULL to remove the option.
* @return boolean FALSE if improper input */ public function setSellerOrderIdFilter($filter){ @@ -301,7 +346,7 @@ public function setSellerOrderIdFilter($filter){ * * This method sets the maximum number of Feed Submissions for Amazon to return per page. * If this parameter is not set, Amazon will send 100 at a time. - * @param array|string $sPositive integer from 1 to 100.
+ * @param array|string $numPositive integer from 1 to 100.
* @return boolean FALSE if improper input */ public function setMaxResultsPerPage($num){ @@ -311,6 +356,48 @@ public function setMaxResultsPerPage($num){ return false; } } + + /** + * Sets the TFM shipment status(es). (Optional) + * + * This method sets the list of TFM Shipment Statuses to be sent in the next request. + * Setting this parameter tells Amazon to only return TFM Orders with statuses that match + * those in the list. If this parameter is not set, Amazon will return + * Orders of any status, including non-TFM orders. + * @param array|string $listA list of TFM Shipment Statuses, or a single status string.
+ * @return boolean FALSE if improper input + */ + public function setTfmShipmentStatusFilter($list){ + if (is_string($list)){ + //if single string, set as filter + $this->resetTfmShipmentStatusFilter(); + $this->options['TFMShipmentStatus.Status.1'] = $list; + } else if (is_array($list)){ + //if array of strings, set all filters + $this->resetTfmShipmentStatusFilter(); + $i = 1; + foreach($list as $x){ + $this->options['TFMShipmentStatus.Status.'.$i] = $x; + $i++; + } + } else { + return false; + } + } + + /** + * Removes order status options. + * + * Use this in case you change your mind and want to remove the TFM Shipment Status + * parameters you previously set. + */ + public function resetTfmShipmentStatusFilter(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#TFMShipmentStatus#",$op)){ + unset($this->options[$op]); + } + } + } /** * Fetches orders from Amazon and puts them in an array of AmazonOrder objects. @@ -318,7 +405,7 @@ public function setMaxResultsPerPage($num){ * Submits a ListOrders request to Amazon. Amazon will send * the list back as a response, which can be retrieved using getList. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchOrders($r = true){ @@ -395,7 +482,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonOrderSet.php b/includes/classes/AmazonOrderSet.php index 569f130e..35f9250f 100644 --- a/includes/classes/AmazonOrderSet.php +++ b/includes/classes/AmazonOrderSet.php @@ -25,9 +25,9 @@ * class instead. */ class AmazonOrderSet extends AmazonOrderCore implements Iterator{ - private $i = 0; - private $index = 0; - private $orderList; + protected $i = 0; + protected $index = 0; + protected $orderList; /** * AmazonOrderSet is a variation of AmazonOrder that pulls multiple specified orders. @@ -70,7 +70,7 @@ public function __construct($s = null, $o = null, $mock = false, $m = null, $con * This method sets the list of Order IDs to be sent in the next request. * If you wish to retrieve information for only one order, please use the * AmazonOrder class instead. - * @param array|string $sA list of Feed Submission IDs, or a single ID string.
+ * @param array|string $oA list of Amazon Order IDs, or a single ID string.
* @return boolean FALSE if improper input */ public function setOrderIds($o){ @@ -98,7 +98,7 @@ public function setOrderIds($o){ * Since order ID is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetOrderIds(){ + protected function resetOrderIds(){ foreach($this->options as $op=>$junk){ if(preg_match("#AmazonOrderId.Id.#",$op)){ unset($this->options[$op]); @@ -145,7 +145,7 @@ public function fetchOrders(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonPackageTracker.php b/includes/classes/AmazonPackageTracker.php index d8734db5..db426511 100644 --- a/includes/classes/AmazonPackageTracker.php +++ b/includes/classes/AmazonPackageTracker.php @@ -23,7 +23,7 @@ * from Amazon. A package number is required for this. */ class AmazonPackageTracker extends AmazonOutboundCore{ - private $details; + protected $details; /** * AmazonPackageTracker fetches package tracking details from Amazon. @@ -105,7 +105,7 @@ public function fetchTrackingDetails(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $dThe XML response from Amazon.
+ * @param SimpleXMLElement $dThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($d) { diff --git a/includes/classes/AmazonParticipationList.php b/includes/classes/AmazonParticipationList.php index 9f2c8b36..e47b4fc8 100644 --- a/includes/classes/AmazonParticipationList.php +++ b/includes/classes/AmazonParticipationList.php @@ -26,10 +26,10 @@ class AmazonParticipationList extends AmazonSellersCore{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $participationList; - private $marketplaceList; - private $indexM = 0; - private $indexP = 0; + protected $participationList; + protected $marketplaceList; + protected $indexM = 0; + protected $indexP = 0; /** * Gets list of marketplaces run by the seller. @@ -91,7 +91,7 @@ public function setUseToken($b = true){ * and getParticipationList. * Other methods are available for fetching specific values from the list. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchParticipationList($r = true){ @@ -137,7 +137,7 @@ public function fetchParticipationList($r = true){ * operation for using tokens does not use any other parameters, all other * parameters will be removed. */ - private function prepareToken(){ + protected function prepareToken(){ if ($this->tokenFlag && $this->tokenUseFlag){ $this->options['Action'] = 'ListMarketplaceParticipationsByNextToken'; } else { @@ -154,7 +154,7 @@ private function prepareToken(){ * Parses XML response into two arrays. * * This is what reads the response XML and converts it into two arrays. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonPreorder.php b/includes/classes/AmazonPreorder.php new file mode 100644 index 00000000..f9942c4c --- /dev/null +++ b/includes/classes/AmazonPreorder.php @@ -0,0 +1,277 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param string $id [optional]The Fulfillment Shipment ID to set for the object.
+ * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $id = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + + if($id){ + $this->setShipmentId($id); + } + } + + /** + * Sets the shipment ID. (Required) + * @param string $sShipment ID
+ * @return boolean FALSE if improper input + */ + public function setShipmentId($s){ + if (is_string($s) && $s){ + $this->options['ShipmentId'] = $s; + } else { + return false; + } + } + + /** + * Sets the maximum arrival date for the shipment. (Required to confirm) + * + * This method sets the max arrival date to be sent in the next request. + * This parameter is required to use confirmPreorder and is removed + * by fetchPreorderInfo. + * @param string $dA time string
+ * @return boolean FALSE if improper input + */ + public function setNeedByDate($d) { + try{ + $this->options['NeedByDate'] = strstr($this->genTime($d), 'T', true); + } catch (Exception $e){ + unset($this->options['NeedByDate']); + $this->log('Error: '.$e->getMessage(), 'Warning'); + return false; + } + } + + /** + * Fetches preorder information from Amazon. + * + * Submits a GetPreorderInfo request to Amazon. In order to do this, + * a fulfillment shipment ID is required. Amazon will send the data back as + * a response, which can be retrieved using getNeedByDate, + * getFulfillableDate, getHasPreorderableItems, + * and getIsConfirmed. + * @return boolean FALSE if something goes wrong + */ + public function fetchPreorderInfo(){ + if (!array_key_exists('ShipmentId',$this->options)) { + $this->log("Shipment ID must be set in order to get preorder info!", 'Warning'); + return false; + } + + $this->prepareGet(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using fetchPreorderInfo. + * + * This changes key options for using fetchPreorderInfo. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * NeedByDate. + */ + protected function prepareGet() { + $this->throttleGroup = 'GetPreorderInfo'; + $this->options['Action'] = 'GetPreorderInfo'; + unset($this->options['NeedByDate']); + } + + /** + * Confirms preorder information for a shipment with Amazon. + * + * Submits a ConfirmPreorder request to Amazon. In order to do this, + * a fulfillment shipment ID and an arrival date are required. + * Amazon will send the data back as a response, which can be retrieved + * using getNeedByDate and getFulfillableDate. + * @return boolean FALSE if something goes wrong + */ + public function confirmPreorder(){ + if (!array_key_exists('ShipmentId',$this->options)) { + $this->log("Shipment ID must be set in order to confirm preorder info!", 'Warning'); + return false; + } + if (!array_key_exists('NeedByDate',$this->options)) { + $this->log("NeedByDate must be set in order to confirm preorder info!", 'Warning'); + return false; + } + + $this->prepareConfirm(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using confirmPreorder. + * + * This changes key options for using confirmPreorder. + */ + protected function prepareConfirm() { + $this->throttleGroup = 'ConfirmPreorder'; + $this->options['Action'] = 'ConfirmPreorder'; + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml){ + return false; + } + + $this->needByDate = null; + if (isset($xml->NeedByDate)) { + $this->needByDate = (string)$xml->NeedByDate; + } + if (isset($xml->ConfirmedNeedByDate)) { + $this->needByDate = (string)$xml->ConfirmedNeedByDate; + } + $this->fulfillableDate = (string)$xml->ConfirmedFulfillableDate; + if (isset($xml->ShipmentContainsPreorderableItems)) { + $this->hasPreorderItems = (string)$xml->ShipmentContainsPreorderableItems; + } + if (isset($xml->ShipmentConfirmedForPreorder)) { + $this->isConfirmed = (string)$xml->ShipmentConfirmedForPreorder; + } + } + + /** + * Returns the date that the shipment must arrive by in order to fulfill preorders. + * + * After confirmPreorder, this date should be the same as + * the NeedByDate option that was sent with the request. + * This method will return FALSE if the date has not been set yet. + * @return string|boolean date in YYYY-MM-DD format, or FALSE if date not set yet + */ + public function getNeedByDate(){ + if (isset($this->needByDate)){ + return $this->needByDate; + } else { + return false; + } + } + + /** + * Returns the date that preorderable items in the shipment can be purchased. + * + * This method will return FALSE if the date has not been set yet. + * @return string|boolean date in YYYY-MM-DD format, or FALSE if date not set yet + */ + public function getFulfillableDate(){ + if (isset($this->fulfillableDate)){ + return $this->fulfillableDate; + } else { + return false; + } + } + + /** + * Indicates whether or not the shipment has items that are preorderable. + * + * Note that this method will return the string "false" if Amazon indicates + * that the shipment does not have preorderable items. + * This method will return boolean FALSE if the date has not been set yet. + * @return string|boolean "true" or "false", or FALSE if date not set yet + */ + public function getHasPreorderableItems(){ + return $this->hasPreorderItems; + } + + /** + * Indicates whether or not the shipment has been confirmed for preorder. + * + * Note that this method will return the string "false" if Amazon indicates + * that the shipment information has not yet been confirmed. + * This method will return boolean FALSE if the date has not been set yet. + * @return string|boolean "true" or "false", or FALSE if date not set yet + */ + public function getIsConfirmed(){ + return $this->isConfirmed; + } + +} diff --git a/includes/classes/AmazonPrepInfo.php b/includes/classes/AmazonPrepInfo.php new file mode 100644 index 00000000..ffbb9690 --- /dev/null +++ b/includes/classes/AmazonPrepInfo.php @@ -0,0 +1,435 @@ +A list of Seller SKUs, or a single SKU string. (max: 20) + * @return boolean FALSE if improper input + */ + public function setSkus($s){ + if (is_string($s)){ + $s = array($s); + } + if (is_array($s)){ + $this->resetASINs(); + $this->resetSKUs(); + $i = 1; + foreach ($s as $x){ + $this->options['SellerSKUList.Id.'.$i] = $x; + $i++; + } + } else { + return false; + } + } + + /** + * Resets the seller SKU options. + * + * Since seller SKU is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + private function resetSkus(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#SellerSKUList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the ASIN(s). (Required*) + * + * This method sets the list of ASINs to be sent in the next request. + * If this parameter is set, Seller SKUs cannot be set. + * @param array|string $sA list of ASINs, or a single ASIN string. (max: 20)
+ * @return boolean FALSE if improper input + */ + public function setAsins($s){ + if (is_string($s)){ + $s = array($s); + } + if (is_array($s)){ + $this->resetSKUs(); + $this->resetASINs(); + $i = 1; + foreach ($s as $x){ + $this->options['ASINList.Id.'.$i] = $x; + $i++; + } + } else { + return false; + } + } + + /** + * Resets the ASIN options. + * + * Since ASIN is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + private function resetAsins(){ + foreach($this->options as $op=>$junk){ + if(preg_match("#ASINList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Fetches item preperation instructions from Amazon. + * + * Submits a GetPrepInstructionsForASIN or + * GetPrepInstructionsForSKU request to Amazon. In order to do this, + * a list of SKUs or ASINs is required. Amazon will send the data back as a + * response, which can be retrieved using getPrepList. + * Other methods are available for fetching specific values from the list. + * A list of items that were deemed invalid can also be retrieved using + * getInvalidItemList. + * @return boolean FALSE if something goes wrong + */ + public function fetchPrepInstructions(){ + if (!array_key_exists('SellerSKUList.Id.1',$this->options) && + !array_key_exists('ASINList.Id.1',$this->options)){ + $this->log("Product IDs must be set in order to get prep instructions!",'Warning'); + return false; + } + + $this->preparePrep(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using fetchPrepInstructions. + * + * This changes key options for using fetchPrepInstructions. + */ + protected function preparePrep(){ + $this->prepList = array(); + $this->invalidList = array(); + $this->rewind(); + if (array_key_exists('SellerSKUList.Id.1',$this->options)){ + $this->options['Action'] = 'GetPrepInstructionsForSKU'; + $this->resetASINs(); + } else if (array_key_exists('ASINList.Id.1',$this->options)){ + $this->options['Action'] = 'GetPrepInstructionsForASIN'; + $this->resetSKUs(); + } + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml){ + return false; + } + + //SKU or ASIN list + $list = false; + if (isset($xml->SKUPrepInstructionsList)) { + $list = $xml->SKUPrepInstructionsList; + } + if (isset($xml->ASINPrepInstructionsList)) { + $list = $xml->ASINPrepInstructionsList; + } + if ($list) { + foreach ($list->children() as $x) { + $temp = array(); + if (isset($x->SellerSKU)) { + $temp['SellerSKU'] = (string)$x->SellerSKU; + } + $temp['ASIN'] = (string)$x->ASIN; + $temp['BarcodeInstruction'] = (string)$x->BarcodeInstruction; + $temp['PrepGuidance'] = (string)$x->PrepGuidance; + foreach ($x->PrepInstructionList->children() as $z) { + $temp['PrepInstructionList'][] = (string)$z; + } + if (isset($x->AmazonPrepFeesDetailsList)) { + foreach ($x->AmazonPrepFeesDetailsList->children() as $z) { + $fee = array(); + $fee['PrepInstruction'] = (string)$z->PrepInstruction; + $fee['Amount']['Value'] = (string)$z->Amount->Value; + $fee['Amount']['CurrencyCode'] = (string)$z->Amount->CurrencyCode; + $temp['AmazonPrepFees'][] = $fee; + } + } + $this->prepList[] = $temp; + } + } + + //invalid item list + $invList = false; + if (isset($xml->InvalidSKUList)) { + $invList = $xml->InvalidSKUList; + } + if (isset($xml->InvalidASINList)) { + $invList = $xml->InvalidASINList; + } + if ($invList) { + foreach ($invList->children() as $x) { + $temp = array(); + $temp['ErrorReason'] = (string)$x->ErrorReason; + if (isset($x->SellerSKU)) { + $temp['SellerSKU'] = (string)$x->SellerSKU; + } + if (isset($x->ASIN)) { + $temp['ASIN'] = (string)$x->ASIN; + } + $this->invalidList[] = $temp; + } + } + } + + /** + * Returns the Seller SKU for the specified item preperation instruction. + * + * Prep instructions will only include this data if SKUs were sent when + * retrieving the list of prep instructions. + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getSku($i = 0){ + if (isset($this->prepList[$i]['SellerSKU'])){ + return $this->prepList[$i]['SellerSKU']; + } else { + return false; + } + } + + /** + * Returns the ASIN for the specified item preperation instruction. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getAsin($i = 0){ + if (isset($this->prepList[$i]['ASIN'])){ + return $this->prepList[$i]['ASIN']; + } else { + return false; + } + } + + /** + * Returns the barcode instruction for the specified item preperation instruction. + * + * Possible values are "RequiresFNSKULabel" and "CanUseOriginalBarcode". + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getBarcodeInstruction($i = 0){ + if (isset($this->prepList[$i]['BarcodeInstruction'])){ + return $this->prepList[$i]['BarcodeInstruction']; + } else { + return false; + } + } + + /** + * Returns the prep guidance message for the specified item preperation instruction. + * + * Possible values are "ConsultHelpDocuments", "NoAdditionalPrepRequired", + * and "SeePrepInstructionsList". + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getPrepGuidance($i = 0){ + if (isset($this->prepList[$i]['PrepGuidance'])){ + return $this->prepList[$i]['PrepGuidance']; + } else { + return false; + } + } + + /** + * Returns the list of instructions for the specified item preperation instruction. + * + * Possible values are "Polybagging", "BubbleWrapping", "Taping", "BlackShrinkWrapping", + * "Labeling", and "HangGarment". + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return array|boolean simple array, or FALSE if Non-numeric index + */ + public function getPrepInstructions($i = 0){ + if (isset($this->prepList[$i]['PrepInstructionList'])){ + return $this->prepList[$i]['PrepInstructionList']; + } else { + return false; + } + } + + /** + * Returns the list of instructions for the specified item preperation instruction. + * + * The array for a single fee will have the following fields: + *List index to retrieve the value from. Defaults to 0.
+ * @return array|boolean multi-dimensional array, or FALSE if Non-numeric index + * @see getPrepInstructions + */ + public function getAmazonPrepFees($i = 0){ + if (isset($this->prepList[$i]['AmazonPrepFees'])){ + return $this->prepList[$i]['AmazonPrepFees']; + } else { + return false; + } + } + + /** + * Returns the full list of preperation instructions. + * + * This method will return FALSE if the list has not yet been filled. + * The array for a single instruction will have the following fields: + *List index of the instruction to return. Defaults to NULL.
+ * @return array|boolean multi-dimensional array, or FALSE if list not filled yet + * @see getPrepInstructionList + * @see getAmazonPrepFees + */ + public function getPrepList($i = null){ + if (!isset($this->prepList)){ + return false; + } + if (is_int($i)){ + return $this->prepList[$i]; + } else { + return $this->prepList; + } + } + + /** + * Returns the full list of invalid items. + * + * This method will return FALSE if the list has not yet been filled. + * The array for a single item will have the following fields: + *List index of the item to return. Defaults to NULL.
+ * @return array|boolean multi-dimensional array, or FALSE if list not filled yet + */ + public function getInvalidItemList($i = null){ + if (!isset($this->invalidList)){ + return false; + } + if (is_int($i)){ + return $this->invalidList[$i]; + } else { + return $this->invalidList; + } + } + + /** + * Iterator function + * @return array + */ + public function current(){ + return $this->prepList[$this->i]; + } + + /** + * Iterator function + */ + public function rewind(){ + $this->i = 0; + } + + /** + * Iterator function + * @return int + */ + public function key() { + return $this->i; + } + + /** + * Iterator function + */ + public function next() { + $this->i++; + } + + /** + * Iterator function + * @return boolean + */ + public function valid() { + return isset($this->prepList[$this->i]); + } +} + diff --git a/includes/classes/AmazonProduct.php b/includes/classes/AmazonProduct.php index 107bcdd4..d58e3da7 100644 --- a/includes/classes/AmazonProduct.php +++ b/includes/classes/AmazonProduct.php @@ -54,7 +54,7 @@ public function __construct($s = null, $data = null, $mock = false, $m = null, $ /** * Takes in XML data and converts it to an array for the object to use. - * @param SimpleXMLObject $xmlXML Product data from Amazon
+ * @param SimpleXMLElement $xmlXML Product data from Amazon
* @return boolean FALSE if no XML data is found */ public function loadXML($xml){ @@ -69,6 +69,11 @@ public function loadXML($xml){ $this->loadCategories($xml); return; } + + //Lowest Price uses different format + if ($xml->getName() == 'GetLowestPricedOffersForSKUResult' || $xml->getName() == 'GetLowestPricedOffersForASINResult'){ + return $this->loadLowestPricedOfferXml($xml); + } if ($xml->getName() != 'Product'){ return; @@ -134,23 +139,33 @@ public function loadXML($xml){ //Relationships if ($xml->Relationships){ foreach($xml->Relationships->children() as $x){ + $temp = array(); foreach($x->children() as $y){ foreach($y->children() as $z){ foreach($z->children() as $zzz){ - $this->data['Relationships'][$x->getName()][$y->getName()][$z->getName()][$zzz->getName()] = (string)$zzz; + $temp[$y->getName()][$z->getName()][$zzz->getName()] = (string)$zzz; } } } + foreach($x->children('ns2',true) as $y){ + $temp[$y->getName()] = (string)$y; + } + $this->data['Relationships'][$x->getName()][] = $temp; } //child relations use namespace but parent does not foreach($xml->Relationships->children('ns2',true) as $x){ + $temp = array(); foreach($x->children() as $y){ foreach($y->children() as $z){ foreach($z->children() as $zzz){ - $this->data['Relationships'][$x->getName()][$y->getName()][$z->getName()][$zzz->getName()] = (string)$zzz; + $temp[$y->getName()][$z->getName()][$zzz->getName()] = (string)$zzz; } } } + foreach($x->children('ns2',true) as $y){ + $temp[$y->getName()] = (string)$y; + } + $this->data['Relationships'][$x->getName()][] = $temp; } } @@ -199,9 +214,11 @@ public function loadXML($xml){ //SalesRankings if ($xml->SalesRankings){ foreach($xml->SalesRankings->children() as $x){ + $temp = array(); foreach($x->children() as $y){ - $this->data['SalesRankings'][$x->getName()][$y->getName()] = (string)$y; + $temp[$y->getName()] = (string)$y; } + $this->data['SalesRankings'][$x->getName()][] = $temp; } } @@ -261,7 +278,7 @@ public function loadXML($xml){ /** * Takes in XML data for Categories and parses it for the object to use - * @param SimpleXMLObject $xmlThe XML data from Amazon.
+ * @param SimpleXMLElement $xmlThe XML data from Amazon.
* @return boolean FALSE if no valid XML data is found */ protected function loadCategories($xml){ @@ -275,6 +292,135 @@ protected function loadCategories($xml){ $cnum++; } } + + /** + * Takes in XML data for lowest-priced offers and parses it for the object to use + * @param SimpleXMLElement $xmlThe XML data from Amazon.
+ * @return boolean FALSE if no valid XML data is found + */ + protected function loadLowestPricedOfferXml($xml) { + if (!$xml->Summary){ + return false; + } + + //Identifier + foreach($xml->Identifier->children() as $x){ + $this->data['Identifiers']['Identifier'][$x->getName()] = (string)$x; + } + + //Summary + $this->data['Summary']['TotalOfferCount'] = (string)$xml->Summary->TotalOfferCount; + //Offer counts + if ($xml->Summary->NumberOfOffers) { + foreach($xml->Summary->NumberOfOffers->children() as $x){ + $att = (array)$x->attributes(); + $tchannel = 'UnknownChannel'; + if (isset($att['@attributes']['fulfillmentChannel'])) { + $tchannel = $att['@attributes']['fulfillmentChannel']; + } + $tcondition = 'UnknownCondition'; + if (isset($att['@attributes']['condition'])) { + $tcondition = $att['@attributes']['condition']; + } + $this->data['Summary']['NumberOfOffers'][$tchannel][$tcondition] = (string)$x; + } + } + //Lowest prices + if ($xml->Summary->LowestPrices) { + foreach($xml->Summary->LowestPrices->children() as $x){ + $temp = array(); + foreach($x->children() as $y) { + foreach($y->children() as $z) { + $temp[$y->getName()][$z->getName()] = (string)$z; + } + } + $att = (array)$x->attributes(); + $tchannel = 'UnknownChannel'; + if (isset($att['@attributes']['fulfillmentChannel'])) { + $tchannel = $att['@attributes']['fulfillmentChannel']; + } + $tcondition = 'UnknownCondition'; + if (isset($att['@attributes']['condition'])) { + $tcondition = $att['@attributes']['condition']; + } + $this->data['Summary']['LowestPrices'][$tchannel][$tcondition] = $temp; + } + } + //BuyBox prices + if ($xml->Summary->BuyBoxPrices) { + foreach($xml->Summary->BuyBoxPrices->children() as $x){ + $temp = array(); + foreach($x->children() as $y) { + foreach($y->children() as $z) { + $temp[$y->getName()][$z->getName()] = (string)$z; + } + } + $att = (array)$x->attributes(); + $tcondition = 'UnknownCondition'; + if (isset($att['@attributes']['condition'])) { + $tcondition = $att['@attributes']['condition']; + } + $this->data['Summary']['BuyBoxPrices'][$tcondition] = $temp; + } + } + //List price + if ($xml->Summary->ListPrice) { + foreach($xml->Summary->ListPrice->children() as $x) { + $this->data['Summary']['ListPrice'][$x->getName()] = (string)$x; + } + } + //Lower price with shipping + if ($xml->Summary->SuggestedLowerPricePlusShipping) { + foreach($xml->Summary->SuggestedLowerPricePlusShipping->children() as $x) { + $this->data['Summary']['SuggestedLowerPricePlusShipping'][$x->getName()] = (string)$x; + } + } + //BuyBox offers + if ($xml->Summary->BuyBoxEligibleOffers) { + foreach($xml->Summary->BuyBoxEligibleOffers->children() as $x) { + $att = (array)$x->attributes(); + $tchannel = 'UnknownChannel'; + if (isset($att['@attributes']['fulfillmentChannel'])) { + $tchannel = $att['@attributes']['fulfillmentChannel']; + } + $tcondition = 'UnknownCondition'; + if (isset($att['@attributes']['condition'])) { + $tcondition = $att['@attributes']['condition']; + } + $this->data['Summary']['BuyBoxEligibleOffers'][$tchannel][$tcondition] = (string)$x; + } + } + //Offers + foreach($xml->Offers->children() as $x){ + $temp = array(); + //Offer + foreach($x->children() as $y){ + if ($y->children()->count() > 0){ + foreach($y->children() as $z){ + if ($z->children()->count() > 0){ + foreach($z->children() as $zzz){ + $temp[$y->getName()][$z->getName()][$zzz->getName()] = (string)$zzz; + } + } else { + $temp[$y->getName()][$z->getName()] = (string)$z; + } + + } + } else { + if ($y->getName() == 'ShippingTime') { + $att = (array)$y->attributes(); + $temp['ShippingTime'] = array(); + foreach ($att['@attributes'] as $zkey => $z) { + $temp['ShippingTime'][$zkey] = $z; + } + } else { + $temp[$y->getName()] = (string)$y; + } + } + } + $this->data['Offers'][] = $temp; + } + } /** * Recursively builds the hierarchy array. @@ -282,7 +428,7 @@ protected function loadCategories($xml){ * The returned array will have the fields ProductCategoryId and * ProductCategoryName, as well as maybe a Parent field with the same * structure as the array containing it. - * @param SimpleXMLObject $xmlThe XML data from Amazon.
+ * @param SimpleXMLElement $xmlThe XML data from Amazon.
* @return array Recursive, multi-dimensional array */ protected function genHierarchy($xml){ diff --git a/includes/classes/AmazonProductInfo.php b/includes/classes/AmazonProductInfo.php index faa16a82..274a2d30 100644 --- a/includes/classes/AmazonProductInfo.php +++ b/includes/classes/AmazonProductInfo.php @@ -78,7 +78,7 @@ public function setSKUs($s){ * Since seller SKU is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetSKUs(){ + protected function resetSKUs(){ foreach($this->options as $op=>$junk){ if(preg_match("#SellerSKUList#",$op)){ unset($this->options[$op]); @@ -121,7 +121,7 @@ public function setASINs($s){ * Since ASIN is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetASINs(){ + protected function resetASINs(){ foreach($this->options as $op=>$junk){ if(preg_match("#ASINList#",$op)){ unset($this->options[$op]); @@ -282,6 +282,63 @@ protected function prepareLowest(){ $this->resetSKUs(); } } + + /** + * Fetches a list of lowest offers on products from Amazon. + * + * Submits a GetLowestPricedOffersForSKU + * or GetLowestPricedOffersForASIN request to Amazon. Amazon will send + * the list back as a response, which can be retrieved using getProduct. + * @return boolean FALSE if something goes wrong + */ + public function fetchLowestPricedOffers(){ + if (!array_key_exists('SellerSKUList.SellerSKU.1',$this->options) && !array_key_exists('ASINList.ASIN.1',$this->options)){ + $this->log("Product IDs must be set in order to look them up!",'Warning'); + return false; + } + + $this->prepareLowestPriced(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXML($xml); + } + + /** + * Sets up options for using fetchLowestPricedOffers. + * + * This changes key options for using fetchLowestPricedOffers. + */ + protected function prepareLowestPriced(){ + include($this->env); + if(isset($THROTTLE_TIME_PRODUCTPRICE)) { + $this->throttleTime = $THROTTLE_TIME_PRODUCTPRICE; + } + $this->throttleGroup = 'GetLowestPricedOfferListings'; + if (array_key_exists('SellerSKUList.SellerSKU.1',$this->options)){ + $this->options['Action'] = 'GetLowestPricedOffersForSKU'; + $this->resetASINs(); + $this->options['SellerSKU'] = $this->options['SellerSKUList.SellerSKU.1']; + } else if (array_key_exists('ASINList.ASIN.1',$this->options)){ + $this->options['Action'] = 'GetLowestPricedOffersForASIN'; + $this->resetSKUs(); + $this->options['ASIN'] = $this->options['ASINList.ASIN.1']; + } + } /** * Fetches a list of your prices on products from Amazon. diff --git a/includes/classes/AmazonProductList.php b/includes/classes/AmazonProductList.php index e1a78b6a..d496f078 100644 --- a/includes/classes/AmazonProductList.php +++ b/includes/classes/AmazonProductList.php @@ -24,7 +24,7 @@ * and product ID(s) must be given. */ class AmazonProductList extends AmazonProductsCore implements Iterator{ - private $i = 0; + protected $i = 0; /** * AmazonProductList fetches a list of products from Amazon. @@ -54,7 +54,7 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) /** * Sets the ID type. (Required) * - * @param string $s"ASIN", "SellerSKU", "UPC", "EAN", "ISBN", or "JAN"
+ * @param string $s"ASIN", "GCID", "SellerSKU", "UPC", "EAN", "ISBN", or "JAN"
* @return boolean FALSE if improper input */ public function setIdType($s){ @@ -94,7 +94,7 @@ public function setProductIds($s){ * Since product ID is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetProductIds(){ + protected function resetProductIds(){ foreach($this->options as $op=>$junk){ if(preg_match("#IdList#",$op)){ unset($this->options[$op]); diff --git a/includes/classes/AmazonProductsCore.php b/includes/classes/AmazonProductsCore.php index 5a6d7af5..08ad18dc 100644 --- a/includes/classes/AmazonProductsCore.php +++ b/includes/classes/AmazonProductsCore.php @@ -54,9 +54,9 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) $this->options['Version'] = $AMAZON_VERSION_PRODUCTS; } - + //set the store's marketplace as the default if(isset($store[$this->storeName]) && array_key_exists('marketplaceId', $store[$this->storeName])){ - $this->options['MarketplaceId'] = $store[$this->storeName]['marketplaceId']; + $this->setMarketplace($store[$this->storeName]['marketplaceId']); } else { $this->log("Marketplace ID is missing",'Urgent'); } @@ -65,12 +65,27 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) $this->throttleLimit = $THROTTLE_LIMIT_PRODUCT; } } + + /** + * Sets the marketplace to search in. (Optional) + * Setting this option tells Amazon to only return products from the given marketplace. + * If this option is not set, the current store's marketplace will be used. + * @param string $mMarketplace ID
+ * @return boolean FALSE if improper input + */ + public function setMarketplace($m){ + if (is_string($m)){ + $this->options['MarketplaceId'] = $m; + } else { + return false; + } + } /** * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -89,9 +104,13 @@ protected function parseXML($xml){ if (isset($x->Products)){ foreach($x->Products->children() as $z){ $this->productList[$this->index] = new AmazonProduct($this->storeName, $z, $this->mockMode, $this->mockFiles,$this->config); + if (isset($temp['@attributes'])) { + $this->productList[$this->index]->data['Identifiers']['Request'] = $temp['@attributes']; + } $this->index++; } - } else if ($x->getName() == 'GetProductCategoriesForSKUResult' || $x->getName() == 'GetProductCategoriesForASINResult'){ + } else if (in_array($x->getName(), array('GetProductCategoriesForSKUResult', 'GetProductCategoriesForASINResult', + 'GetLowestPricedOffersForSKUResult', 'GetLowestPricedOffersForASINResult'))){ $this->productList[$this->index] = new AmazonProduct($this->storeName, $x, $this->mockMode, $this->mockFiles,$this->config); $this->index++; } else { diff --git a/includes/classes/AmazonRecommendationCore.php b/includes/classes/AmazonRecommendationCore.php new file mode 100644 index 00000000..7d8786e4 --- /dev/null +++ b/includes/classes/AmazonRecommendationCore.php @@ -0,0 +1,86 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + include($this->env); + if (file_exists($this->config)){ + include($this->config); + } else { + throw new Exception('Config file does not exist!'); + } + + if (isset($AMAZON_VERSION_RECOMMEND)){ + $this->urlbranch = 'Recommendations/' . $AMAZON_VERSION_RECOMMEND; + $this->options['Version'] = $AMAZON_VERSION_RECOMMEND; + } + + if(isset($THROTTLE_LIMIT_RECOMMEND)) { + $this->throttleLimit = $THROTTLE_LIMIT_RECOMMEND; + } + if(isset($THROTTLE_TIME_RECOMMEND)) { + $this->throttleTime = $THROTTLE_TIME_RECOMMEND; + } + + if (isset($store[$this->storeName]['marketplaceId'])){ + $this->setMarketplace($store[$this->storeName]['marketplaceId']); + } else { + $this->log("Marketplace ID is missing", 'Urgent'); + } + } + + /** + * Sets the marketplace associated with the recommendations. (Optional) + * + * The current store's configured marketplace is used by default. + * @param string $mMarketplace ID
+ * @return boolean FALSE if improper input + */ + public function setMarketplace($m){ + if (is_string($m)){ + $this->options['MarketplaceId'] = $m; + } else { + return false; + } + } + +} + diff --git a/includes/classes/AmazonRecommendationList.php b/includes/classes/AmazonRecommendationList.php new file mode 100644 index 00000000..5787ee48 --- /dev/null +++ b/includes/classes/AmazonRecommendationList.php @@ -0,0 +1,800 @@ +tokenFlag; + } + + /** + * Sets whether or not the object should automatically use tokens if it receives one. + * + * If this option is set to TRUE, the object will automatically perform + * the necessary operations to retrieve the rest of the list using tokens. If + * this option is off, the object will only ever retrieve the first section of + * the list. + * @param boolean $b [optional]Defaults to TRUE
+ * @return boolean FALSE if improper input + */ + public function setUseToken($b = true) { + if (is_bool($b)) { + $this->tokenUseFlag = $b; + } else { + return false; + } + } + + /** + * Sets the category filter. (Optional) + * + * If this parameter is set, Amazon will only return recommendations from + * the specified category. If this parameter is not sent, Amazon will return + * recommendations from all categories. + * Possible category values: "Inventory", "Selection", "Pricing", "Fulfillment", + * "ListingQuality", "GlobalSelling", and "Advertising". + * @param string $sCategory name
+ * @return boolean FALSE if improper input + */ + public function setCategory($s) { + if (is_string($s)) { + $this->options['RecommendationCategory'] = $s; + } else { + return false; + } + } + + /** + * Sets the category filter. (Optional) + * + * If this parameter is set, Amazon will only return recommendations that + * match the given filters. If this parameter is not sent, Amazon will return + * all recommendations for each category. + * The given array should be two-dimensional, with the first level indexed by + * the name of the category, and the second level as a list of key/value pairs + * of filters for that specific category. + * See setCategory for a list of valid categories. + * See the comment inside for a list of valid filters. + * @param array $aSee above.
+ * @return boolean FALSE if improper input + * @see setCategory + */ + public function setFilter($a) { + $this->resetFilters(); + if (is_array($a)) { + $i = 1; + foreach ($a as $c => $r) { + if (empty($r) || !is_array($r)) { + $this->resetFilters(); + return false; + } + $prefix = 'CategoryQueryList.CategoryQuery.'.$i; + $this->options[$prefix.'.RecommendationCategory'] = $c; + $j = 1; + foreach ($r as $k => $x) { + $this->options[$prefix.'.FilterOptions.FilterOption.'.$j] = $k.'='.$x; + $j++; + } + $i++; + } + } else { + return false; + } + /* + * Valid filters for ListingQuality recommendations: + * QualitySet: "Defect" or "Quarantine" + * ListingStatus: "Active" or "Inactive" + * Valid filters for Selection, Fulfillment, GlobalSelling, and Advertising recommendations: + * BrandName: any brand name + * ProductCategory: any product category + * Valid filters for Selection recommendations: + * IncludeCommonRecommendations: "true" or "false" + */ + } + + /** + * Removes filter options. + * + * Use this in case you change your mind and want to remove the filter + * parameters you previously set. + */ + public function resetFilters() { + foreach($this->options as $op=>$junk) { + if(preg_match("#CategoryQueryList#",$op)) { + unset($this->options[$op]); + } + } + } + + /** + * Fetches recommendation update times from Amazon. + * + * Submits a GetLastUpdatedTimeForRecommendations request to Amazon. + * Amazon will send dates back as a response, which can be retrieved using + * getLastUpdateTimes. + * Other methods are available for fetching individual times. + * @return boolean FALSE if something goes wrong + */ + public function fetchLastUpdateTimes() { + if (!array_key_exists('MarketplaceId', $this->options)) { + $this->log("Marketplace ID must be set in order to fetch recommendation times!", 'Warning'); + return false; + } + + $this->prepareTimes(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using fetchLastUpdateTimes. + * + * This changes key options for using fetchLastUpdateTimes. + * Please note: because this operation does not use all of the parameters, + * the following parameters are removed: + * category, filters, and token. + */ + protected function prepareTimes() { + $this->options['Action'] = 'GetLastUpdatedTimeForRecommendations'; + $this->throttleGroup = 'GetLastUpdatedTimeForRecommendations'; + unset($this->options['NextToken']); + unset($this->options['RecommendationCategory']); + $this->resetFilters(); + $this->updated = array(); + } + + /** + * Fetches a list of active recommendations from Amazon. + * + * Submits a ListRecommendations request to Amazon. Amazon will send + * the data back as a response, categorized into seven lists. These lists + * can be retrieved using getLists. + * Other methods are available for fetching individual lists. + * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
+ * @return boolean FALSE if something goes wrong + */ + public function fetchRecommendations($r = true) { + if (!array_key_exists('MarketplaceId', $this->options)) { + $this->log("Marketplace ID must be set in order to fetch recommendations!", 'Warning'); + return false; + } + + $this->prepareToken(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode) { + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + + $this->checkToken($xml); + + if ($this->tokenFlag && $this->tokenUseFlag && $r === true) { + while ($this->tokenFlag) { + $this->log("Recursively fetching more recommendations"); + $this->fetchRecommendations(false); + } + } + } + + /** + * Sets up options for using tokens. + * + * This changes key options for switching between simply fetching a list and + * fetching the rest of a list using a token. Please note: because the + * operation for using tokens does not use any other parameters, all other + * parameters will be removed. + */ + protected function prepareToken() { + $this->throttleGroup = 'ListRecommendations'; + if ($this->tokenFlag && $this->tokenUseFlag) { + $this->options['Action'] = 'ListRecommendationsByNextToken'; + + //When using tokens, only the NextToken option should be used + unset($this->options['RecommendationCategory']); + $this->resetFilters(); + } else { + $this->options['Action'] = 'ListRecommendations'; + unset($this->options['NextToken']); + $this->list = array(); + $this->listkey = null; + if (isset($this->options['RecommendationCategory'])) { + $this->listkey = $this->options['RecommendationCategory']; + } + } + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXML($xml){ + if (!$xml) { + return false; + } + + if ($xml->InventoryRecommendationsLastUpdated) { + $this->updated['Inventory'] = (string)$xml->InventoryRecommendationsLastUpdated; + } + if ($xml->SelectionRecommendationsLastUpdated) { + $this->updated['Selection'] = (string)$xml->SelectionRecommendationsLastUpdated; + } + if ($xml->PricingRecommendationsLastUpdated) { + $this->updated['Pricing'] = (string)$xml->PricingRecommendationsLastUpdated; + } + if ($xml->FulfillmentRecommendationsLastUpdated) { + $this->updated['Fulfillment'] = (string)$xml->FulfillmentRecommendationsLastUpdated; + } + if ($xml->GlobalSellingRecommendationsLastUpdated) { + $this->updated['GlobalSelling'] = (string)$xml->GlobalSellingRecommendationsLastUpdated; + } + if ($xml->AdvertisingRecommendationsLastUpdated) { + $this->updated['Advertising'] = (string)$xml->AdvertisingRecommendationsLastUpdated; + } + + if (isset($xml->InventoryRecommendations)) { + foreach ($xml->InventoryRecommendations->children() as $x) { + $this->list['Inventory'][] = $this->parseRecommendation($x); + } + } + if (isset($xml->SelectionRecommendations)) { + foreach ($xml->SelectionRecommendations->children() as $x) { + $this->list['Selection'][] = $this->parseRecommendation($x); + } + } + if (isset($xml->PricingRecommendations)) { + foreach ($xml->PricingRecommendations->children() as $x) { + $this->list['Pricing'][] = $this->parseRecommendation($x); + } + } + if (isset($xml->FulfillmentRecommendations)) { + foreach ($xml->FulfillmentRecommendations->children() as $x) { + $this->list['Fulfillment'][] = $this->parseRecommendation($x); + } + } + if (isset($xml->ListingQualityRecommendations)) { + foreach ($xml->ListingQualityRecommendations->children() as $x) { + $this->list['ListingQuality'][] = $this->parseRecommendation($x); + } + } + if (isset($xml->GlobalSellingRecommendations)) { + foreach ($xml->GlobalSellingRecommendations->children() as $x) { + $this->list['GlobalSelling'][] = $this->parseRecommendation($x); + } + } + if (isset($xml->AdvertisingRecommendations)) { + foreach ($xml->AdvertisingRecommendations->children() as $x) { + $this->list['Advertising'][] = $this->parseRecommendation($x); + } + } + } + + /** + * Parses XML response for a single recommendation into an array. + * @param SimpleXMLElement $xml + * @return array parsed structure from XML + */ + protected function parseRecommendation($xml) { + $r = array(); + foreach ($xml->children() as $x) { + if (isset($x->Asin)) { + $r[$x->getName()]['ASIN'] = (string)$x->Asin; + $r[$x->getName()]['SKU'] = (string)$x->Sku; + $r[$x->getName()]['UPC'] = (string)$x->Upc; + } else if (isset($x->CurrencyCode)) { + $r[$x->getName()]['Amount'] = (string)$x->Amount; + $r[$x->getName()]['CurrencyCode'] = (string)$x->CurrencyCode; + } else if (isset($x->Height)) { + $r[$x->getName()]['Height']['Value'] = (string)$x->Height->Value; + $r[$x->getName()]['Height']['Unit'] = (string)$x->Height->Unit; + $r[$x->getName()]['Width']['Value'] = (string)$x->Width->Value; + $r[$x->getName()]['Width']['Unit'] = (string)$x->Width->Unit; + $r[$x->getName()]['Length']['Value'] = (string)$x->Length->Value; + $r[$x->getName()]['Length']['Unit'] = (string)$x->Length->Unit; + $r[$x->getName()]['Weight']['Value'] = (string)$x->Weight->Value; + $r[$x->getName()]['Weight']['Unit'] = (string)$x->Weight->Unit; + } else { + $r[$x->getName()] = (string)$x; + } + } + return $r; + } + + /** + * Returns a list of all update times. + * + * The returned array will have keys from any of the categories listed in setCategory. + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean array of timestamps, or FALSE if list not set yet + */ + public function getLastUpdateTimes(){ + if (isset($this->updated)){ + return $this->updated; + } else { + return false; + } + } + + /** + * Returns the last update time for Inventory recommendations. + * + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean date in ISO 8601 date time format, or FALSE if not set yet + */ + public function getInventoryLastUpdateTime(){ + if (isset($this->updated['Inventory'])){ + return $this->updated['Inventory']; + } else { + return false; + } + } + + /** + * Returns the last update time for Selection recommendations. + * + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean date in ISO 8601 date time format, or FALSE if not set yet + */ + public function getSelectionLastUpdateTime(){ + if (isset($this->updated['Selection'])){ + return $this->updated['Selection']; + } else { + return false; + } + } + + /** + * Returns the last update time for Pricing recommendations. + * + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean date in ISO 8601 date time format, or FALSE if not set yet + */ + public function getPricingLastUpdateTime(){ + if (isset($this->updated['Pricing'])){ + return $this->updated['Pricing']; + } else { + return false; + } + } + + /** + * Returns the last update time for Fulfillment recommendations. + * + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean date in ISO 8601 date time format, or FALSE if not set yet + */ + public function getFulfillmentLastUpdateTime(){ + if (isset($this->updated['Fulfillment'])){ + return $this->updated['Fulfillment']; + } else { + return false; + } + } + + /** + * Returns the last update time for Global Selling recommendations. + * + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean date in ISO 8601 date time format, or FALSE if not set yet + */ + public function getGlobalSellingLastUpdateTime(){ + if (isset($this->updated['GlobalSelling'])){ + return $this->updated['GlobalSelling']; + } else { + return false; + } + } + + /** + * Returns the last update time for Advertising recommendations. + * + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean date in ISO 8601 date time format, or FALSE if not set yet + */ + public function getAdvertisingLastUpdateTime(){ + if (isset($this->updated['Advertising'])){ + return $this->updated['Advertising']; + } else { + return false; + } + } + + /** + * Returns all recommendations from all categories. + * + * The returned array will have keys from any of the categories listed in setCategory. + * This method will return FALSE if the list has not yet been filled. + * @return array|boolean multi-dimensional array, or FALSE if list not filled yet + * @see setCategory + */ + public function getLists(){ + if (isset($this->list)){ + return $this->list; + } else { + return false; + } + } + + /** + * Returns recommendations from the Inventory category. + * + * Each recommendation array will have the following keys: + *filename to save the file in
+ * @return string|boolean raw data string, or FALSE if data has not been retrieved yet + */ + public function getRawReport() { + if (!isset($this->rawreport)){ + return false; + } + return $this->rawreport; + } /** * Saves the raw report data to a path you specify * @param string $pathfilename to save the file in
+ * @return boolean FALSE if something goes wrong */ public function saveReport($path){ if (!isset($this->rawreport)){ @@ -121,6 +136,7 @@ public function saveReport($path){ $this->log("Successfully saved report #".$this->options['ReportId']." at $path"); } catch (Exception $e){ $this->log("Unable to save report #".$this->options['ReportId']." at $path: $e",'Urgent'); + return false; } } diff --git a/includes/classes/AmazonReportAcknowledger.php b/includes/classes/AmazonReportAcknowledger.php index 13ca1437..a3f6bd4e 100644 --- a/includes/classes/AmazonReportAcknowledger.php +++ b/includes/classes/AmazonReportAcknowledger.php @@ -24,10 +24,10 @@ * required. A list of the affected reports is returned. */ class AmazonReportAcknowledger extends AmazonReportsCore implements Iterator{ - private $count; - private $index = 0; - private $i = 0; - private $reportList; + protected $count; + protected $index = 0; + protected $i = 0; + protected $reportList; /** * AmazonReportAcknowledger sends a report acknowledgement request to Amazon. @@ -162,7 +162,7 @@ public function acknowledgeReports(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonReportList.php b/includes/classes/AmazonReportList.php index 22bf7e8e..5b9a3075 100644 --- a/includes/classes/AmazonReportList.php +++ b/includes/classes/AmazonReportList.php @@ -27,9 +27,9 @@ class AmazonReportList extends AmazonReportsCore implements Iterator{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $index = 0; - private $i = 0; - private $reportList; + protected $index = 0; + protected $i = 0; + protected $reportList; /** * AmazonReportList gets a list of reports from Amazon. @@ -238,7 +238,7 @@ public function resetTimeLimits(){ * the list back as a response, which can be retrieved using getList. * Other methods are available for fetching specific values from the list. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchReportList($r = true){ @@ -319,7 +319,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -337,6 +337,9 @@ protected function parseXML($xml){ $this->reportList[$i]['ReportRequestId'] = (string)$x->ReportRequestId; $this->reportList[$i]['AvailableDate'] = (string)$x->AvailableDate; $this->reportList[$i]['Acknowledged'] = (string)$x->Acknowledged; + if (isset($x->AcknowledgedDate)) { + $this->reportList[$i]['AcknowledgedDate'] = (string)$x->AcknowledgedDate; + } $this->index++; } @@ -485,6 +488,24 @@ public function getIsAcknowledged($i = 0){ return false; } } + + /** + * Returns the date the specified report was first acknowledged. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index or if the date is not set + */ + public function getAcknowledgedDate($i = 0){ + if (!isset($this->reportList)){ + return false; + } + if (is_int($i) && isset($this->reportList[$i]['AcknowledgedDate'])){ + return $this->reportList[$i]['AcknowledgedDate']; + } else { + return false; + } + } /** * Returns the full list. diff --git a/includes/classes/AmazonReportRequest.php b/includes/classes/AmazonReportRequest.php index c06d1789..b61d1ae3 100644 --- a/includes/classes/AmazonReportRequest.php +++ b/includes/classes/AmazonReportRequest.php @@ -24,7 +24,7 @@ * available to limit the scope of the report. */ class AmazonReportRequest extends AmazonReportsCore{ - private $response; + protected $response; /** * AmazonReportRequest sends a report request to Amazon. @@ -59,7 +59,7 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) * * This method sets the report type to be sent in the next request. * This parameter is required for fetching the report from Amazon. - * @param string|integer $nSee comment inside for a list of valid values.
+ * @param string|integer $sSee comment inside for a list of valid values.
* @return boolean FALSE if improper input */ public function setReportType($s){ @@ -77,10 +77,11 @@ public function setReportType($s){ * Merchant Listings Lite Report ~ _GET_MERCHANT_LISTINGS_DATA_LITE_ * Merchant Listings Liter Report ~ _GET_MERCHANT_LISTINGS_DATA_LITER_ * Canceled Listings Report ~ _GET_MERCHANT_CANCELLED_LISTINGS_DATA_ + * Sold Listings Report ~ _GET_CONVERGED_FLAT_FILE_SOLD_LISTINGS_DATA_ * Quality Listing Report ~ _GET_MERCHANT_LISTINGS_DEFECT_DATA_ * Order Reports: * Unshipped Orders Report ~ _GET_FLAT_FILE_ACTIONABLE_ORDER_DATA_ - * Flat File Order Report ~ _GET_FLAT_FILE_ORDER_REPORT_DATA_ + * Scheduled XML Order Report ~ _GET_ORDERS_DATA_ * Requested Flat File Order Report ~ _GET_FLAT_FILE_ORDERS_DATA_ * Flat File Order Report ~ _GET_CONVERGED_FLAT_FILE_ORDER_REPORT_DATA_ * Order Tracking Reports: @@ -91,40 +92,50 @@ public function setReportType($s){ * Pending Order Reports: * Flat File Pending Orders Report ~ _GET_FLAT_FILE_PENDING_ORDERS_DATA_ * XML Pending Orders Report ~ _GET_PENDING_ORDERS_DATA_ - * Converged Flat File Pending Orders Report ~ GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA_ + * Converged Flat File Pending Orders Report ~ _GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA_ * Performance Reports: * Flat File Feedback Report ~ _GET_SELLER_FEEDBACK_DATA_ - * FBA Reports: + * XML Customer Metrics Report ~ _GET_V1_SELLER_PERFORMANCE_REPORT_ + * Settlement Reports: + * Flat File Settlement Report ~ _GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_ + * XML Settlement Report ~ _GET_V2_SETTLEMENT_REPORT_DATA_XML_ + * Flat File V2 Settlement Report ~ _GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2_ + * FBA Sales Reports: + * FBA Fulfilled Shipments Report ~ _GET_AMAZON_FULFILLED_SHIPMENTS_DATA_ * Flat File All Orders Report by Last Update ~ _GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_ * Flat File All Orders Report by Order Date ~ _GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_ * XML All Orders Report by Last Update ~ _GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE_ * XML All Orders Report by Order Date ~ _GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE_ - * FBA Inventory Report ~ _GET_AFN_INVENTORY_DATA_ - * FBA Fulfilled Shipments Report ~ _GET_AMAZON_FULFILLED_SHIPMENTS_DATA_ - * FBA Returns Report ~ _GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_ * FBA Customer Shipment Sales Report ~ _GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_SALES_DATA_ - * Customer Taxes ~ _GET_FBA_FULFILLMENT_CUSTOMER_TAXES_DATA_ * FBA Promotions Report ~ _GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_PROMOTION_DATA_ - * FBA Inbound Compliance Report ~ _GET_FBA_FULFILLMENT_INBOUND_NONCOMPLIANCE_DATA_ + * Customer Taxes ~ _GET_FBA_FULFILLMENT_CUSTOMER_TAXES_DATA_ + * FBA Inventory Reports: + * FBA Inventory Report ~ _GET_AFN_INVENTORY_DATA_ + * FBA Multi-Country Inventory Report ~ _GET_AFN_INVENTORY_DATA_BY_COUNTRY_ * FBA Daily Inventory History Report ~ _GET_FBA_FULFILLMENT_CURRENT_INVENTORY_DATA_ * FBA Monthly Inventory History Repoty ~ _GET_FBA_FULFILLMENT_MONTHLY_INVENTORY_DATA_ * FBA Received Inventory Report ~ _GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_ + * FBA Reserved Inventory Report ~ _GET_RESERVED_INVENTORY_DATA_ * FBA Inventory Event Detail Report ~ _GET_FBA_FULFILLMENT_INVENTORY_SUMMARY_DATA_ * FBA Inventory Adjustments Report ~ _GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_ * FBA Inventory Health Report ~ _GET_FBA_FULFILLMENT_INVENTORY_HEALTH_DATA_ * FBA Manage Inventory ~ _GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA_ * FBA Manage Inventory - Archived ~ _GET_FBA_MYI_ALL_INVENTORY_DATA_ - * FBA Replacements Report ~ _GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_REPLACEMENT_DATA_ * FBA Cross-Border Inventory Movement Report ~ _GET_FBA_FULFILLMENT_CROSS_BORDER_INVENTORY_MOVEMENT_DATA_ + * FBA Inbound Compliance Report ~ _GET_FBA_FULFILLMENT_INBOUND_NONCOMPLIANCE_DATA_ + * FBA Payments Reports: + * FBA Fee Preview Report ~ _GET_FBA_ESTIMATED_FBA_FEES_TXT_DATA_ + * FBA Reimbursements Report ~ _GET_FBA_REIMBURSEMENTS_DATA_ + * FBA Customer Concessions Reports: + * FBA Returns Report ~ _GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_ + * FBA Replacements Report ~ _GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_REPLACEMENT_DATA_ + * FBA Removals Reports: * FBA Recommended Removal Report ~ _GET_FBA_RECOMMENDED_REMOVAL_DATA_ - * Amazon Product Ads Report: - * Product Ads Listings Report ~ _GET_NEMO_MERCHANT_LISTINGS_DATA_ - * Product Ads Daily Performance by SKU Report, flat file ~ _GET_PADS_PRODUCT_PERFORMANCE_OVER_TIME_DAILY_DATA_TSV_ - * Product Ads Daily Performance by SKU Report, XML ~ _GET_PADS_PRODUCT_PERFORMANCE_OVER_TIME_DAILY_DATA_XML_ - * Product Ads Weekly Performance by SKU Report, flat file ~ _GET_PADS_PRODUCT_PERFORMANCE_OVER_TIME_WEEKLY_DATA_TSV_ - * Product Ads Weekly Performance by SKU Report, XML ~ _GET_PADS_PRODUCT_PERFORMANCE_OVER_TIME_WEEKLY_DATA_XML_ - * Product Ads Monthly Performance by SKU Report, flat file ~ _GET_PADS_PRODUCT_PERFORMANCE_OVER_TIME_MONTHLY_DATA_TSV_ - * Product Ads Monthly Performance by SKU Report, XML ~ _GET_PADS_PRODUCT_PERFORMANCE_OVER_TIME_MONTHLY_DATA_XML_ + * FBA Removal Order Detail Report ~ _GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA_ + * FBA Removal Shipment Detail Report ~ _GET_FBA_FULFILLMENT_REMOVAL_SHIPMENT_DETAIL_DATA_ + * Other: + * Sales Tax Report ~ _GET_FLAT_FILE_SALES_TAX_DATA_ + * Browse Tree Report ~ _GET_XML_BROWSE_TREE_DATA_ */ } @@ -175,9 +186,9 @@ public function resetTimeLimits(){ */ public function setShowSalesChannel($s){ if ($s == 'true' || (is_bool($s) && $s == true)){ - $this->options['ReportOptions=ShowSalesChannel'] = 'true'; + $this->options['ReportOptions'] = 'ShowSalesChannel=true'; } else if ($s == 'false' || (is_bool($s) && $s == false)){ - $this->options['ReportOptions=ShowSalesChannel'] = 'false'; + $this->options['ReportOptions'] = 'ShowSalesChannel=false'; } else { return false; } @@ -262,7 +273,7 @@ public function requestReport(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonReportRequestList.php b/includes/classes/AmazonReportRequestList.php index 52d29201..5f820014 100644 --- a/includes/classes/AmazonReportRequestList.php +++ b/includes/classes/AmazonReportRequestList.php @@ -28,10 +28,10 @@ class AmazonReportRequestList extends AmazonReportsCore implements Iterator{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $index = 0; - private $i = 0; - private $reportList; - private $count; + protected $index = 0; + protected $i = 0; + protected $reportList; + protected $count; /** * AmazonReportRequestList fetches a list of report requests from Amazon. @@ -256,7 +256,7 @@ public function resetTimeLimits(){ * the list back as a response, which can be retrieved using getList. * Other methods are available for fetching specific values from the list. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $rWhen set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchRequestList($r = true){ @@ -359,7 +359,7 @@ protected function prepareCancel(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -386,7 +386,7 @@ protected function parseXML($xml){ $this->reportList[$i]['ReportProcessingStatus'] = (string)$x->ReportProcessingStatus; $this->reportList[$i]['GeneratedReportId'] = (string)$x->GeneratedReportId; $this->reportList[$i]['StartedProcessingDate'] = (string)$x->StartedProcessingDate; - $this->reportList[$i]['CompletedProcessingDate'] = (string)$x->CompletedProcessingDate; + $this->reportList[$i]['CompletedDate'] = (string)$x->CompletedDate; $this->index++; } @@ -649,16 +649,27 @@ public function getDateProcessingStarted($i = 0){ * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
* @return string|boolean single value, or FALSE if Non-numeric index */ - public function getDateProcessingCompleted($i = 0){ + public function getDateCompleted($i = 0){ if (!isset($this->reportList)){ return false; } if (is_int($i)){ - return $this->reportList[$i]['CompletedProcessingDate']; + return $this->reportList[$i]['CompletedDate']; } else { return false; } } + + /** + * Alias of getDateCompleted. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + * @see getDateCompleted + * @deprecated since 1.3.0 + */ + public function getDateProcessingCompleted($i = 0){ + return $this->getDateCompleted($i); + } /** * Returns the full list. @@ -674,7 +685,7 @@ public function getDateProcessingCompleted($i = 0){ *List index to retrieve the value from. Defaults to NULL.
* @return array|boolean multi-dimensional array, or FALSE if list not filled yet diff --git a/includes/classes/AmazonReportScheduleList.php b/includes/classes/AmazonReportScheduleList.php index 751a39ee..2d3a9811 100644 --- a/includes/classes/AmazonReportScheduleList.php +++ b/includes/classes/AmazonReportScheduleList.php @@ -28,10 +28,10 @@ class AmazonReportScheduleList extends AmazonReportsCore implements Iterator{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $index = 0; - private $i = 0; - private $scheduleList; - private $count; + protected $index = 0; + protected $i = 0; + protected $scheduleList; + protected $count; /** * AmazonReportScheduleList sets a list of report schedules from Amazon. @@ -128,7 +128,7 @@ public function resetReportTypes(){ * the list back as a response, which can be retrieved using getList. * Other methods are available for fetching specific values from the list. * This operation can potentially involve tokens. - * @param booleanWhen set to FALSE, the function will not recurse, defaults to TRUE
+ * @param boolean $r [optional]When set to FALSE, the function will not recurse, defaults to TRUE
* @return boolean FALSE if something goes wrong */ public function fetchReportList($r = true){ @@ -205,7 +205,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonReportScheduleManager.php b/includes/classes/AmazonReportScheduleManager.php index c62c896b..ad5df36f 100644 --- a/includes/classes/AmazonReportScheduleManager.php +++ b/includes/classes/AmazonReportScheduleManager.php @@ -26,10 +26,10 @@ * which will usually be 1. */ class AmazonReportScheduleManager extends AmazonReportsCore implements Iterator{ - private $scheduleList; - private $count; - private $i = 0; - private $index = 0; + protected $scheduleList; + protected $count; + protected $i = 0; + protected $index = 0; /** * AmazonReportsScheduleManager manages report schedules. @@ -187,7 +187,7 @@ public function manageReportSchedule(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonReportsCore.php b/includes/classes/AmazonReportsCore.php index 3501998f..9291bade 100644 --- a/includes/classes/AmazonReportsCore.php +++ b/includes/classes/AmazonReportsCore.php @@ -46,23 +46,5 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) $this->options['Version'] = $AMAZON_VERSION_REPORTS; } } - - /** - * Checks for a token and changes the proper options - * @param SimpleXMLObject $xmlresponse data
- * @return boolean FALSE if no XML data - */ - protected function checkToken($xml){ - if (!$xml){ - return false; - } - if ((string)$xml->HasNext == 'true'){ - $this->tokenFlag = true; - $this->options['NextToken'] = (string)$xml->NextToken; - } else { - unset($this->options['NextToken']); - $this->tokenFlag = false; - } - } } ?> diff --git a/includes/classes/AmazonServiceStatus.php b/includes/classes/AmazonServiceStatus.php index 46007753..470fcfdd 100644 --- a/includes/classes/AmazonServiceStatus.php +++ b/includes/classes/AmazonServiceStatus.php @@ -23,11 +23,11 @@ * Please note that it has a 5 minute throttle time. */ class AmazonServiceStatus extends AmazonCore{ - private $lastTimestamp; - private $status; - private $messageId; - private $messageList; - private $ready = false; + protected $lastTimestamp; + protected $status; + protected $messageId; + protected $messageList; + protected $ready = false; /** * AmazonServiceStatus is a simple object that fetches the status of given Amazon service. @@ -187,7 +187,7 @@ public function fetchServiceStatus(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ diff --git a/includes/classes/AmazonShipment.php b/includes/classes/AmazonShipment.php index 9021d3b1..78090079 100644 --- a/includes/classes/AmazonShipment.php +++ b/includes/classes/AmazonShipment.php @@ -25,7 +25,7 @@ * Use the AmazonShipmentPlanner object to retrieve this information. */ class AmazonShipment extends AmazonInboundCore{ - private $shipmentId; + protected $shipmentId; /** * AmazonShipment ubmits a shipment to Amazon or updates it. @@ -49,7 +49,10 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) /** * Automatically fills in the necessary fields using a planner array. * - * This information is required to submit a shipment. + * This is a quick way to set the shipment ID, destination, label prep type, and items. + * Note that the label preperation preference will be set to "AMAZON_LABEL_PREFERRED" if the + * fulfillment preview selects the label type as "AMAZON_LABEL" and "SELLER_LABEL" otherwise. + * This information is required to submit a shipment, but this method is not required. * @param array $xplan array from AmazonShipmentPlanner
* @return boolean FALSE if improper input */ @@ -57,12 +60,15 @@ public function usePlan($x){ if (is_array($x)){ $this->options['ShipmentId'] = $x['ShipmentId']; - //inheriting address - $this->setAddress($x['ShipToAddress']); - - $this->options['InboundShipmentHeader.ShipmentId'] = $x['ShipmentId']; - $this->options['InboundShipmentHeader.DestinationFulfillmentCenterId'] = $x['DestinationFulfillmentCenterId']; - $this->options['InboundShipmentHeader.LabelPrepType'] = $x['LabelPrepType']; + $this->setShipmentId($x['ShipmentId']); + $this->setDestination($x['DestinationFulfillmentCenterId']); + + //label preference is not a direct match to preview results + if ($x['LabelPrepType'] == 'AMAZON_LABEL') { + $this->setLabelPrepPreference('AMAZON_LABEL_PREFERRED'); + } else { + $this->setLabelPrepPreference('SELLER_LABEL'); + } $this->setItems($x['Items']); @@ -71,11 +77,26 @@ public function usePlan($x){ return false; } } + + /** + * Sets the name for the shipment. (Required) + * + * This information is required to create a fulfillment shipment. + * @param string $nname
+ * @return boolean FALSE if improper input + */ + public function setShipmentName($n) { + if (is_string($n)) { + $this->options['InboundShipmentHeader.ShipmentName'] = $n; + } else { + return false; + } + } /** * Sets the address. (Required) * - * This method sets the destination address to be sent in the next request. + * This method sets the shipper's address to be sent in the next request. * This parameter is required for creating a fulfillment order with Amazon. * The array provided should have the following fields: *destination fulfillment center ID
+ * @return boolean FALSE if improper input + */ + public function setDestination($d) { + if (is_string($d)) { + $this->options['InboundShipmentHeader.DestinationFulfillmentCenterId'] = $d; + } else { + return false; + } + } + + /** + * Sets the label prep type preference for the shipment. (Required) + * + * This information is required to create a fulfillment shipment. + * @param string $p"SELLER_LABEL", "AMAZON_LABEL_ONLY", or "AMAZON_LABEL_PREFERRED"
+ * @return boolean FALSE if improper input + */ + public function setLabelPrepPreference($p) { + if (in_array($p, array('SELLER_LABEL', 'AMAZON_LABEL_ONLY', 'AMAZON_LABEL_PREFERRED'))) { + $this->options['InboundShipmentHeader.LabelPrepPreference'] = $p; + } else { + return false; + } + } /** * Sets the items. (Required) @@ -147,6 +198,13 @@ protected function resetAddress(){ *See above.
* @return boolean FALSE if improper input @@ -168,6 +226,21 @@ public function setItems($a){ $this->options['InboundShipmentItems.member.'.$i.'.QuantityInCase'] = $x['QuantityInCase']; $caseflag = true; } + if (array_key_exists('PrepDetailsList', $x) && is_array($x['PrepDetailsList'])){ + $j = 1; + foreach ($x['PrepDetailsList'] as $z) { + if (!isset($z['PrepInstruction']) || !isset($z['PrepOwner'])) { + $this->log("Tried to set invalid prep details for item",'Warning'); + continue; + } + $this->options['InboundShipmentItems.member.'.$i.'.PrepDetailsList.PrepDetails.'.$j.'.PrepInstruction'] = $z['PrepInstruction']; + $this->options['InboundShipmentItems.member.'.$i.'.PrepDetailsList.PrepDetails.'.$j.'.PrepOwner'] = $z['PrepOwner']; + $j++; + } + } + if (array_key_exists('ReleaseDate', $x)){ + $this->options['InboundShipmentItems.member.'.$i.'.ReleaseDate'] = $this->genTime($x['ReleaseDate']); + } $i++; } else { $this->resetItems(); @@ -184,7 +257,7 @@ public function setItems($a){ * Since the list of items is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetItems(){ + protected function resetItems(){ foreach($this->options as $op=>$junk){ if(preg_match("#InboundShipmentItems#",$op)){ unset($this->options[$op]); @@ -248,10 +321,14 @@ public function createShipment(){ $this->log("Shipment ID must be set in order to create it",'Warning'); return false; } - if (!array_key_exists('InboundShipmentHeader.ShipFromAddress.Name',$this->options)){ + if (!array_key_exists('InboundShipmentHeader.ShipmentName',$this->options)){ $this->log("Header must be set in order to make a shipment",'Warning'); return false; } + if (!array_key_exists('InboundShipmentHeader.ShipFromAddress.Name',$this->options)){ + $this->log("Address must be set in order to make a shipment",'Warning'); + return false; + } if (!array_key_exists('InboundShipmentItems.member.1.SellerSKU',$this->options)){ $this->log("Items must be set in order to make a shipment",'Warning'); return false; @@ -298,10 +375,14 @@ public function updateShipment(){ $this->log("Shipment ID must be set in order to update it",'Warning'); return false; } - if (!array_key_exists('InboundShipmentHeader.ShipFromAddress.Name',$this->options)){ + if (!array_key_exists('InboundShipmentHeader.ShipmentName',$this->options)){ $this->log("Header must be set in order to update a shipment",'Warning'); return false; } + if (!array_key_exists('InboundShipmentHeader.ShipFromAddress.Name',$this->options)){ + $this->log("Address must be set in order to update a shipment",'Warning'); + return false; + } if (!array_key_exists('InboundShipmentItems.member.1.SellerSKU',$this->options)){ $this->log("Items must be set in order to update a shipment",'Warning'); return false; diff --git a/includes/classes/AmazonShipmentItemList.php b/includes/classes/AmazonShipmentItemList.php index 348528a1..58f5de37 100644 --- a/includes/classes/AmazonShipmentItemList.php +++ b/includes/classes/AmazonShipmentItemList.php @@ -26,9 +26,9 @@ class AmazonShipmentItemList extends AmazonInboundCore implements Iterator{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $itemList; - private $index = 0; - private $i = 0; + protected $itemList; + protected $index = 0; + protected $i = 0; /** * Fetches a list of items from Amazon. @@ -217,15 +217,15 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ if (!$xml){ return false; } - $a = array(); foreach($xml->ItemData->children() as $x){ + $a = array(); if (isset($x->ShipmentId)){ $a['ShipmentId'] = (string)$x->ShipmentId; @@ -241,6 +241,17 @@ protected function parseXML($xml){ if (isset($x->QuantityInCase)){ $a['QuantityInCase'] = (string)$x->QuantityInCase; } + if (isset($x->PrepDetailsList)) { + foreach ($x->PrepDetailsList->children() as $z) { + $temp = array(); + $temp['PrepInstruction'] = (string)$z->PrepInstruction; + $temp['PrepOwner'] = (string)$z->PrepOwner; + $a['PrepDetailsList'][] = $temp; + } + } + if (isset($x->ReleaseDate)){ + $a['ReleaseDate'] = (string)$x->ReleaseDate; + } $this->itemList[$this->index] = $a; $this->index++; @@ -354,6 +365,48 @@ public function getQuantityInCase($i = 0){ return false; } } + + /** + * Returns the preperation details for the specified entry. + * + * Each individual preperation detail entry is an array with the keys "PrepInstruction" and "PrepOwner". + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param int $j [optional]Detail index to retrieve the value from. Defaults to NULL.
+ * @return array|boolean associative array, array of associative arrays, or FALSE if Non-numeric index + */ + public function getPrepDetails($i = 0, $j = null) { + if (!isset($this->itemList)){ + return false; + } + if (is_int($i) && isset($this->itemList[$i]['PrepDetailsList'])){ + if (is_numeric($j)) { + return $this->itemList[$i]['PrepDetailsList'][$j]; + } else { + return $this->itemList[$i]['PrepDetailsList']; + } + } else { + return false; + } + } + + /** + * Returns the release date for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean Date in YYYY-MM-DD format, or FALSE if Non-numeric index + */ + public function getReleaseDate($i = 0){ + if (!isset($this->itemList)){ + return false; + } + if (is_int($i)){ + return $this->itemList[$i]['ReleaseDate']; + } else { + return false; + } + } /** * Returns the full list. diff --git a/includes/classes/AmazonShipmentList.php b/includes/classes/AmazonShipmentList.php index d49e3a7d..711193b0 100644 --- a/includes/classes/AmazonShipmentList.php +++ b/includes/classes/AmazonShipmentList.php @@ -26,9 +26,9 @@ class AmazonShipmentList extends AmazonInboundCore implements Iterator{ protected $tokenFlag = false; protected $tokenUseFlag = false; - private $shipmentList; - private $index = 0; - private $i = 0; + protected $shipmentList; + protected $index = 0; + protected $i = 0; /** * AmazonShipmentList fetches a list of shipments from Amazon. @@ -117,7 +117,7 @@ public function setStatusFilter($s){ * Since status is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetStatusFilter(){ + protected function resetStatusFilter(){ foreach($this->options as $op=>$junk){ if(preg_match("#ShipmentStatusList#",$op)){ unset($this->options[$op]); @@ -157,7 +157,7 @@ public function setIdFilter($s){ * Since shipment ID is a required parameter, these options should not be removed * without replacing them, so this method is not public. */ - private function resetIdFilter(){ + protected function resetIdFilter(){ foreach($this->options as $op=>$junk){ if(preg_match("#ShipmentIdList#",$op)){ unset($this->options[$op]); @@ -283,7 +283,7 @@ protected function prepareToken(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml){ @@ -329,6 +329,10 @@ protected function parseXML($xml){ } $a['AreCasesRequired'] = (string)$x->AreCasesRequired; + + if (isset($x->ConfirmedNeedByDate)){ + $a['ConfirmedNeedByDate'] = (string)$x->ConfirmedNeedByDate; + } $this->shipmentList[$this->index] = $a; $this->index++; @@ -418,7 +422,7 @@ public function getShipmentName($i = 0){ *List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean Date in YYYY-MM-DD format, or FALSE if Non-numeric index + */ + public function getConfirmedNeedByDate($i = 0){ + if (!isset($this->shipmentList)){ + return false; + } + if (is_int($i)){ + return $this->shipmentList[$i]['ConfirmedNeedByDate']; + } else { + return false; + } + } /** * Returns the full list. diff --git a/includes/classes/AmazonShipmentPlanner.php b/includes/classes/AmazonShipmentPlanner.php index 7945bb56..ba089b79 100644 --- a/includes/classes/AmazonShipmentPlanner.php +++ b/includes/classes/AmazonShipmentPlanner.php @@ -24,8 +24,8 @@ * shipment plan, an address and a list of items are required. */ class AmazonShipmentPlanner extends AmazonInboundCore implements Iterator{ - private $planList; - private $i = 0; + protected $planList; + protected $i = 0; /** * AmazonShipmentPlanner fetches a shipment plan from Amazon. This is how you get a Shipment ID. @@ -49,7 +49,7 @@ public function __construct($s = null, $mock = false, $m = null, $config = null) /** * Sets the address. (Required) * - * This method sets the destination address to be sent in the next request. + * This method sets the shipper's address to be sent in the next request. * This parameter is required for planning a fulfillment order with Amazon. * The array provided should have the following fields: *Country code in ISO 3166-1 alpha-2 format
+ * @return boolean FALSE if improper input + */ + public function setCountry($c) { + if (is_string($c)){ + $this->options['ShipToCountryCode'] = $c; + } else { + return false; + } + } + + /** + * Sets the destination country subdivision code. (Optional) + * @param string $cCountry subdivision code in ISO 3166-2 format
+ * @return boolean FALSE if improper input + */ + public function setCountrySubdivision($c) { + if (is_string($c)){ + $this->options['ShipToCountrySubdivisionCode'] = $c; + } else { + return false; + } + } /** * Sets the labeling preference. (Optional) @@ -159,6 +185,16 @@ public function setLabelPreference($s){ *See above.
* @return boolean FALSE if improper input @@ -174,12 +210,27 @@ public function setItems($a){ if (array_key_exists('SellerSKU', $x) && array_key_exists('Quantity', $x)){ $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.SellerSKU'] = $x['SellerSKU']; $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.Quantity'] = $x['Quantity']; + if (array_key_exists('ASIN', $x)){ + $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.ASIN'] = $x['ASIN']; + } if (array_key_exists('QuantityInCase', $x)){ $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.QuantityInCase'] = $x['QuantityInCase']; } if (array_key_exists('Condition', $x)){ $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.Condition'] = $x['Condition']; } + if (array_key_exists('PrepDetailsList', $x) && is_array($x['PrepDetailsList'])){ + $j = 1; + foreach ($x['PrepDetailsList'] as $z) { + if (!isset($z['PrepInstruction']) || !isset($z['PrepOwner'])) { + $this->log("Tried to set invalid prep details for item",'Warning'); + continue; + } + $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.PrepDetailsList.PrepDetails.'.$j.'.PrepInstruction'] = $z['PrepInstruction']; + $this->options['InboundShipmentPlanRequestItems.member.'.$i.'.PrepDetailsList.PrepDetails.'.$j.'.PrepOwner'] = $z['PrepOwner']; + $j++; + } + } $i++; } else { $this->resetItems(); @@ -246,7 +297,7 @@ public function fetchPlan(){ * Parses XML response into array. * * This is what reads the response XML and converts it into an array. - * @param SimpleXMLObject $xmlThe XML response from Amazon.
+ * @param SimpleXMLElement $xmlThe XML response from Amazon.
* @return boolean FALSE if no XML data is found */ protected function parseXML($xml) { @@ -267,6 +318,14 @@ protected function parseXML($xml) { $this->planList[$i]['Items'][$j]['SellerSKU'] = (string)$z->SellerSKU; $this->planList[$i]['Items'][$j]['Quantity'] = (string)$z->Quantity; $this->planList[$i]['Items'][$j]['FulfillmentNetworkSKU'] = (string)$z->FulfillmentNetworkSKU; + if (isset($z->PrepDetailsList)) { + foreach ($z->PrepDetailsList as $zz) { + $temp = array(); + $temp['PrepInstruction'] = (string)$zz->PrepInstruction; + $temp['PrepOwner'] = (string)$zz->PrepOwner; + $this->planList[$i]['Items'][$j]['PrepDetailsList'][] = $temp; + } + } $j++; } diff --git a/includes/classes/AmazonSubscription.php b/includes/classes/AmazonSubscription.php new file mode 100644 index 00000000..d6e3073c --- /dev/null +++ b/includes/classes/AmazonSubscription.php @@ -0,0 +1,695 @@ +Delivery channel + * @return boolean FALSE if improper input + */ + public function setDeliveryChannel($s) { + if (is_string($s)){ + $this->options['Destination.DeliveryChannel'] = $s; + $this->options['Subscription.Destination.DeliveryChannel'] = $s; + } else { + return false; + } + } + + /** + * Sets the destination attributes. (Required) + * + * This parameter is required for performing any actions with subscription destinations. + * The array provided should be an array of key/value pairs. + * Possible attribute keys: "sqsQueueUrl". + * @param array $aArray of key/value pairs
+ * @return boolean FALSE if improper input + */ + public function setAttributes($a) { + if (empty($a) || !is_array($a)){ + $this->log("Tried to set AttributeList to invalid values", 'Warning'); + return false; + } + $this->resetAttributes(); + $i = 1; + foreach ($a as $k => $v){ + $this->options['Destination.AttributeList.member.'.$i.'.Key'] = $k; + $this->options['Destination.AttributeList.member.'.$i.'.Value'] = $v; + $this->options['Subscription.Destination.AttributeList.member.'.$i.'.Key'] = $k; + $this->options['Subscription.Destination.AttributeList.member.'.$i.'.Value'] = $v; + $i++; + } + } + + /** + * Resets the destination attribute options. + * + * Since the list of attributes is a required parameter, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetAttributes() { + foreach($this->options as $op=>$junk){ + if(preg_match("#Destination.AttributeList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the notification type. (Required for subscriptions) + * + * This parameter is required for performing any actions with subscriptions. + * @param string $sSee the comment inside for a list of valid values.
+ * @return boolean FALSE if improper input + */ + public function setNotificationType($s) { + if (is_string($s)){ + $this->options['Subscription.NotificationType'] = $s; + $this->options['NotificationType'] = $s; + } else { + return false; + } + /* + * List of valid Notification Types: + * AnyOfferChanged + * FulfillmentOrderStatus + */ + } + + /** + * Sets whether or not the subscription is enabled. (Required for subscriptions) + * + * This parameter is required for performing any actions with subscriptions. + * @param boolean $bDefaults to TRUE
+ */ + public function setIsEnabled($b = TRUE) { + if ($b) { + $this->options['Subscription.IsEnabled'] = 'true'; + } else { + $this->options['Subscription.IsEnabled'] = 'false'; + } + } + + /** + * Resets the destination-specific parameters. + * + * Since these are required parameters, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetDestinationParams() { + foreach($this->options as $op=>$junk){ + if(preg_match("#^Destination.#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Resets the subscription-specific parameters. + * + * Since these are required parameters, these options should not be removed + * without replacing them, so this method is not public. + */ + protected function resetSubscriptionParams() { + foreach($this->options as $op=>$junk){ + if(preg_match("#Subscription.#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Registers a subscription destination on Amazon. + * + * Submits a RegisterDestination request to Amazon. Amazon will send + * back an empty response. The following parameters are required: + * marketplace ID, delivery channel, and attributes. + * @return boolean FALSE if something goes wrong + */ + public function registerDestination() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to register a subscription destination!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to register a subscription destination!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to register a subscription destination!", 'Warning'); + return false; + } + + $this->prepareRegister(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using registerDestination. + * + * This changes key options for using registerDestination. + * Please note: because this operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * notification type and enabled status. + */ + protected function prepareRegister() { + $this->options['Action'] = 'RegisterDestination'; + $this->throttleGroup = 'RegisterDestination'; + $this->resetSubscriptionParams(); + unset($this->options['NotificationType']); + } + + /** + * Deregisters a subscription destination on Amazon. + * + * Submits a DeregisterDestination request to Amazon. Amazon will send + * back an empty response. The following parameters are required: + * marketplace ID, delivery channel, and attributes. + * @return boolean FALSE if something goes wrong + */ + public function deregisterDestination() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to deregister a subscription destination!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to deregister a subscription destination!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to deregister a subscription destination!", 'Warning'); + return false; + } + + $this->prepareDeregister(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using deregisterDestination. + * + * This changes key options for using deregisterDestination. + * Please note: because this operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * notification type and enabled status. + */ + protected function prepareDeregister() { + $this->options['Action'] = 'DeregisterDestination'; + $this->throttleGroup = 'DeregisterDestination'; + $this->resetSubscriptionParams(); + unset($this->options['NotificationType']); + } + + /** + * Sends a request to Amazon to send a test notification to a subscription destination. + * + * Submits a SendTestNotificationToDestination request to Amazon. Amazon will send + * back an empty response. The following parameters are required: + * marketplace ID, delivery channel, and attributes. + * @return boolean FALSE if something goes wrong + */ + public function testDestination() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to test a subscription destination!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to test a subscription destination!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to test a subscription destination!", 'Warning'); + return false; + } + + $this->prepareTest(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using testDestination. + * + * This changes key options for using testDestination. + * Please note: because this operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * notification type and enabled status. + */ + protected function prepareTest() { + $this->options['Action'] = 'SendTestNotificationToDestination'; + $this->throttleGroup = 'SendTestNotificationToDestination'; + $this->resetSubscriptionParams(); + unset($this->options['NotificationType']); + } + + /** + * Creates a subscription on Amazon. + * + * Submits a CreateSubscription request to Amazon. Amazon will send + * back an empty response. The following parameters are required: + * marketplace ID, delivery channel, attributes, notification type, and enabled status. + * @return boolean FALSE if something goes wrong + */ + public function createSubscription() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to create a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to create a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to create a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.NotificationType', $this->options)){ + $this->log("Notification type must be set in order to create a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.IsEnabled', $this->options)){ + $this->log("Enabled status must be set in order to create a subscription!", 'Warning'); + return false; + } + + $this->prepareCreate(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using createSubscription. + * + * This changes key options for using createSubscription. + */ + protected function prepareCreate() { + $this->options['Action'] = 'CreateSubscription'; + $this->throttleGroup = 'CreateSubscription'; + $this->resetDestinationParams(); + unset($this->options['NotificationType']); + } + + /** + * Fetches a subscription from Amazon. + * + * Submits a GetSubscription request to Amazon. Amazon will send + * the data back as a response, which can be retrived using getSubscription. + * The following parameters are required: + * marketplace ID, delivery channel, attributes, notification type, and enabled status. + * @return boolean FALSE if something goes wrong + */ + public function fetchSubscription() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to fetch a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to fetch a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to fetch a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('NotificationType', $this->options)){ + $this->log("Notification type must be set in order to fetch a subscription!", 'Warning'); + return false; + } + + $this->prepareGet(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using fetchSubscription. + * + * This changes key options for using fetchSubscription. + * Please note: because this operation does not use all of the parameters, + * the enabled status parameter is removed. + */ + protected function prepareGet() { + $this->options['Action'] = 'GetSubscription'; + $this->throttleGroup = 'GetSubscription'; + $this->resetSubscriptionParams(); + } + + /** + * Updates a subscription on Amazon. + * + * Submits an UpdateSubscription request to Amazon. Amazon will send + * back an empty response. The following parameters are required: + * marketplace ID, delivery channel, attributes, notification type, and enabled status. + * @return boolean FALSE if something goes wrong + */ + public function updateSubscription() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to update a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to update a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to update a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.NotificationType', $this->options)){ + $this->log("Notification type must be set in order to update a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Subscription.IsEnabled', $this->options)){ + $this->log("Enabled status must be set in order to update a subscription!", 'Warning'); + return false; + } + + $this->prepareUpdate(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using updateSubscription. + * + * This changes key options for using updateSubscription. + */ + protected function prepareUpdate() { + $this->options['Action'] = 'UpdateSubscription'; + $this->throttleGroup = 'UpdateSubscription'; + $this->resetDestinationParams(); + unset($this->options['NotificationType']); + } + + /** + * Deletes a subscription on Amazon. + * + * Submits a DeleteSubscription request to Amazon. Amazon will send + * back an empty response. The following parameters are required: + * marketplace ID, delivery channel, attributes, notification type, and enabled status. + * @return boolean FALSE if something goes wrong + */ + public function deleteSubscription() { + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to delete a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.DeliveryChannel', $this->options)){ + $this->log("Delivery channel must be set in order to delete a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('Destination.AttributeList.member.1.Key', $this->options)){ + $this->log("Attributes must be set in order to delete a subscription!", 'Warning'); + return false; + } + if (!array_key_exists('NotificationType', $this->options)){ + $this->log("Notification type must be set in order to delete a subscription!", 'Warning'); + return false; + } + + $this->prepareDelete(); + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXml($xml); + } + + /** + * Sets up options for using deleteSubscription. + * + * This changes key options for using deleteSubscription. + * Please note: because this operation does not use all of the parameters, + * the enabled status parameter is removed. + */ + protected function prepareDelete() { + $this->options['Action'] = 'DeleteSubscription'; + $this->throttleGroup = 'DeleteSubscription'; + $this->resetSubscriptionParams(); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml){ + return false; + } + + if (isset($xml->Subscription)) { + $this->data = array(); + $this->data['NotificationType'] = (string)$xml->Subscription->NotificationType; + $this->data['IsEnabled'] = (string)$xml->Subscription->IsEnabled; + $this->data['Destination']['DeliveryChannel'] = (string)$xml->Subscription->Destination->DeliveryChannel; + foreach ($xml->Subscription->Destination->AttributeList->children() as $x) { + $this->data['Destination']['AttributeList'][(string)$x->Key] = (string)$x->Value; + } + } + } + + /** + * Returns the full array of subscription information. + * + * This method will return FALSE if the response data has not yet been filled. + * The returned array will have the following fields: + *This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + include($this->env); + if (file_exists($this->config)){ + include($this->config); + } else { + throw new Exception('Config file does not exist!'); + } + + if (isset($AMAZON_VERSION_SUBSCRIBE)){ + $this->urlbranch = 'Subscriptions/' . $AMAZON_VERSION_SUBSCRIBE; + $this->options['Version'] = $AMAZON_VERSION_SUBSCRIBE; + } + + if(isset($THROTTLE_LIMIT_SUBSCRIBE)) { + $this->throttleLimit = $THROTTLE_LIMIT_SUBSCRIBE; + } + if(isset($THROTTLE_TIME_SUBSCRIBE)) { + $this->throttleTime = $THROTTLE_TIME_SUBSCRIBE; + } + + if (isset($store[$this->storeName]['marketplaceId'])){ + $this->setMarketplace($store[$this->storeName]['marketplaceId']); + } else { + $this->log("Marketplace ID is missing", 'Urgent'); + } + } + + /** + * Sets the marketplace associated with the subscription or destination. (Optional) + * + * The current store's configured marketplace is used by default. + * @param string $mMarketplace ID
+ * @return boolean FALSE if improper input + */ + public function setMarketplace($m){ + if (is_string($m)){ + $this->options['MarketplaceId'] = $m; + } else { + return false; + } + } + +} diff --git a/includes/classes/AmazonSubscriptionDestinationList.php b/includes/classes/AmazonSubscriptionDestinationList.php new file mode 100644 index 00000000..3b7e1db2 --- /dev/null +++ b/includes/classes/AmazonSubscriptionDestinationList.php @@ -0,0 +1,192 @@ +ListRegisteredDestinations request to Amazon. Amazon will send + * the data back as a response, which can be retrieved using getDestinations. + * Other methods are available for fetching specific values from the order. + * @return boolean FALSE if something goes wrong + */ + public function fetchDestinations(){ + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to fetch subscription destinations!", 'Warning'); + return false; + } + + $this->options['Action'] = 'ListRegisteredDestinations'; + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXML($xml); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXML($xml){ + $this->destinationList = array(); + if (!$xml){ + return false; + } + + $i = 0; + foreach ($xml->DestinationList->children() as $item) { + $this->destinationList[$i]['DeliveryChannel'] = (string)$item->DeliveryChannel; + + foreach ($item->AttributeList->children() as $member) { + $this->destinationList[$i]['AttributeList'][(string)$member->Key] = (string)$member->Value; + } + + $i++; + } + } + + /** + * Returns the specified destination, or all of them. + * + * This method will return FALSE if the list has not yet been filled. + * The array for a single order item will have the following fields: + *List index to retrieve the value from. + * If none is given, the entire list will be returned. Defaults to NULL.
+ * @return array|boolean array, multi-dimensional array, or FALSE if list not filled yet + */ + public function getDestinations($i = null){ + if (isset($this->destinationList)){ + if (is_numeric($i)){ + return $this->destinationList[$i]; + } else { + return $this->destinationList; + } + } else { + return false; + } + } + + /** + * Returns the delivery channel for the specified entry. + * + * Possible values for this field: "SQS". + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if Non-numeric index + */ + public function getDeliveryChannel($i = 0){ + if (isset($this->destinationList[$i]['DeliveryChannel'])){ + return $this->destinationList[$i]['DeliveryChannel']; + } else { + return false; + } + } + + /** + * Returns the specified attribute set for the specified entry. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param string $j [optional]Second list index to retrieve the value from. Defaults to NULL.
+ * @return array|boolean associative array, or FALSE if Non-numeric index + */ + public function getAttributes($i = 0, $j = null){ + if (isset($this->destinationList[$i]['AttributeList'])){ + if (isset($this->destinationList[$i]['AttributeList'][$j])){ + return $this->destinationList[$i]['AttributeList'][$j]; + } else { + return $this->destinationList[$i]['AttributeList']; + } + } else { + return false; + } + } + + /** + * Iterator function + * @return array + */ + public function current(){ + return $this->destinationList[$this->i]; + } + + /** + * Iterator function + */ + public function rewind(){ + $this->i = 0; + } + + /** + * Iterator function + * @return int + */ + public function key(){ + return $this->i; + } + + /** + * Iterator function + */ + public function next(){ + $this->i++; + } + + /** + * Iterator function + * @return boolean + */ + public function valid(){ + return isset($this->destinationList[$this->i]); + } + +} diff --git a/includes/classes/AmazonSubscriptionList.php b/includes/classes/AmazonSubscriptionList.php new file mode 100644 index 00000000..43d9c270 --- /dev/null +++ b/includes/classes/AmazonSubscriptionList.php @@ -0,0 +1,221 @@ +ListSubscriptions request to Amazon. Amazon will send + * the data back as a response, which can be retrieved using getList. + * Other methods are available for fetching specific values from the order. + * @return boolean FALSE if something goes wrong + */ + public function fetchSubscriptions(){ + if (!array_key_exists('MarketplaceId', $this->options)){ + $this->log("Marketplace ID must be set in order to fetch subscriptions!", 'Warning'); + return false; + } + + $this->options['Action'] = 'ListSubscriptions'; + + $url = $this->urlbase . $this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'] . 'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile()->$path; + } else { + $response = $this->sendRequest($url, array('Post' => $query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body'])->$path; + } + + $this->parseXML($xml); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXML($xml){ + $this->list = array(); + if (!$xml){ + return false; + } + + foreach ($xml->SubscriptionList->children() as $x) { + $temp = array(); + $temp['NotificationType'] = (string)$x->NotificationType; + $temp['IsEnabled'] = (string)$x->IsEnabled; + $temp['Destination']['DeliveryChannel'] = (string)$x->Destination->DeliveryChannel; + foreach ($x->Destination->AttributeList->children() as $z) { + $temp['Destination']['AttributeList'][(string)$z->Key] = (string)$z->Value; + } + $this->list[] = $temp; + } + } + + /** + * Returns the specified subscription, or all of them. + * + * This method will return FALSE if the list has not yet been filled. + * @param int $i [optional]List index to retrieve the value from. + * If none is given, the entire list will be returned. Defaults to NULL.
+ * @return array|boolean multi-dimensional array, or FALSE if list not filled yet + */ + public function getList($i = null){ + if (isset($this->list)){ + if (is_numeric($i)){ + return $this->list[$i]; + } else { + return $this->list; + } + } else { + return false; + } + } + + /** + * Returns the notification type for the retrieved subscription. + * + * See setNotificationType for list of possible values. + * This method will return FALSE if the data has not been set yet. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if not set yet or invalid index + * @see setNotificationType + */ + public function getNotificationType($i = 0){ + if (isset($this->list[$i]['NotificationType'])){ + return $this->list[$i]['NotificationType']; + } else { + return false; + } + } + + /** + * Returns the notification type for the retrieved subscription. + * + * Note that this method will return the string "false" if Amazon indicates + * that the subscription is not enabled. + * This method will return boolean FALSE if the date has not been set yet. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean "true" or "false", or FALSE if not set yet or invalid index + */ + public function getIsEnabled($i = 0){ + if (isset($this->list[$i]['IsEnabled'])){ + return $this->list[$i]['IsEnabled']; + } else { + return false; + } + } + + /** + * Returns the delivery channel for the retrieved subscription's destination. + * + * See setDeliveryChannel for list of possible values. + * This method will return FALSE if the data has not been set yet. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @return string|boolean single value, or FALSE if not set yet or invalid index + * @see setDeliveryChannel + */ + public function getDeliveryChannel($i = 0){ + if (isset($this->list[$i]['Destination']['DeliveryChannel'])){ + return $this->list[$i]['Destination']['DeliveryChannel']; + } else { + return false; + } + } + + /** + * Returns the attribute list for the retrieved subscription's destination. + * + * This method will return FALSE if the data has not been set yet. + * @param int $i [optional]List index to retrieve the value from. Defaults to 0.
+ * @param string $j [optional]Second list index to retrieve the value from. Defaults to NULL.
+ * @return array|boolean associative array, or FALSE if not set yet or invalid index + */ + public function getAttributes($i = 0, $j = null){ + if (isset($this->list[$i]['Destination']['AttributeList'])){ + if (isset($this->list[$i]['Destination']['AttributeList'][$j])) { + return $this->list[$i]['Destination']['AttributeList'][$j]; + } else { + return $this->list[$i]['Destination']['AttributeList']; + } + } else { + return false; + } + } + + /** + * Iterator function + * @return array + */ + public function current(){ + return $this->list[$this->i]; + } + + /** + * Iterator function + */ + public function rewind(){ + $this->i = 0; + } + + /** + * Iterator function + * @return int + */ + public function key(){ + return $this->i; + } + + /** + * Iterator function + */ + public function next(){ + $this->i++; + } + + /** + * Iterator function + * @return boolean + */ + public function valid(){ + return isset($this->list[$this->i]); + } + +} diff --git a/includes/classes/AmazonTransport.php b/includes/classes/AmazonTransport.php new file mode 100644 index 00000000..914c64b3 --- /dev/null +++ b/includes/classes/AmazonTransport.php @@ -0,0 +1,1511 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param string $id [optional]The Fulfillment Shipment ID to set for the object.
+ * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $id = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + + if($id){ + $this->setShipmentId($id); + } + } + + /** + * Sets the shipment ID. (Required) + * @param string $sShipment ID
+ * @return boolean FALSE if improper input + */ + public function setShipmentId($s){ + if (is_string($s) && $s){ + $this->options['ShipmentId'] = $s; + } else { + return false; + } + } + + /** + * Sets the parameter for whether or not the shipment is with an Amazon-partnered carrier. (Required for send) + * + * The other parameters that will be required will change depending on this setting. + * This parameter is required for sending transport content information to Amazon. + * This parameter is removed by all other actions. + * @param boolean $bWhether or not the shipment's carrier is partnered
+ */ + public function setIsPartnered($b) { + if ($b) { + $v = 'true'; + } else { + $v = 'false'; + } + $this->options['IsPartnered'] = $v; + } + + /** + * Sets the shipment type. (Required for send) + * + * The other parameters that will be required will change depending on this setting. + * Use "SP" if the shipment is for small parcels and "LTL" when the shipment is for pallets in a truck. + * This parameter is required for sending transport content information to Amazon. + * This parameter is removed by all other actions. + * @param string $s"SP" or "LTL"
+ * @return boolean FALSE if improper input + */ + public function setShipmentType($s) { + $options = array( + 'SP', + 'LTL', + ); + if (in_array($s, $options)){ + $this->options['ShipmentType'] = $s; + } else { + $this->log('Tried to set ShipmentType to invalid value', 'Warning'); + return false; + } + } + + /** + * Determines which of the four possible transport detail parameter prefixes should be used. + * The parameter to use depends on the partnered and shipment type parameters. + * @return string|boolean parameter prefix or FALSE if it could not be determined + */ + protected function determineDetailOption() { + if (!isset($this->options['IsPartnered']) || !isset($this->options['ShipmentType'])) { + $this->log('Cannot set transport details without shipment type and partner parameters!', 'Warning'); + return false; + } + $op = 'TransportDetails.'; + if ($this->options['ShipmentType'] == 'SP') { + if ($this->options['IsPartnered'] == 'true') { + return $op . 'PartneredSmallParcelData'; + } else { + return $op . 'NonPartneredSmallParcelData'; + } + } else if ($this->options['ShipmentType'] == 'LTL') { + if ($this->options['IsPartnered'] == 'true') { + return $op . 'PartneredLtlData'; + } else { + return $op . 'NonPartneredLtlData'; + } + } + $this->log('Unknown shipment type, cannot set transport details!', 'Warning'); + return false; + } + + /** + * Sets the carrier name used for the shipment. (Required for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is required for sending transport content information to Amazon when the + * carrier is not partnered. This parameter is optional when the carrier is partnered and the + * shipment type is set to "SP" for Small Parcel. + * This parameter is removed by all other actions. + * @param string $sSee the comment inside for a list of valid values.
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setCarrier($s){ + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set carrier name because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if (is_string($s) && $s){ + $this->options[$op.'.CarrierName'] = $s; + } else { + return false; + } + /* + * Valid carrier names when shipment type is set to LTL: + * BUSINESS_POST + * DHL_AIRWAYS_INC + * DHL_UK + * PARCELFORCE + * DPD + * TNT_LOGISTICS_CORPORATION + * TNT + * YODEL + * UNITED_PARCEL_SERVICE_INC + * DHL_EXPRESS_USA_INC + * FEDERAL_EXPRESS_CORP + * UNITED_STATES_POSTAL_SERVICE + * OTHER + * + * Valid carrier names when shipment type is set to SP: + * UNITED_PARCEL_SERVICE_INC + * DHL_STANDARD + */ + } + + /** + * Sets the list of packages. (Required for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is required for sending transport content information to Amazon when the + * shipment type is set to "SP" for Small Parcel. + * If the carrier is partnered with Amazon, each package array should have the following keys: + *See above.
+ * @param string $duDimensions unit: "inches" or "centimeters", defaults to centimeters
+ * @param string $wuWeight unit: "pounds" or "kilograms", defaults to kilograms
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setPackages($a, $du = 'centimeters', $wu = 'kilograms'){ + if (empty($a) || !is_array($a)) { + $this->log("Tried to set package list to invalid values",'Warning'); + return false; + } + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set packages because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + $this->resetPackages(); + $i = 1; + foreach ($a as $x) { + $prefix = $op.'.PackageList.member.'.$i; + if (is_array($x)) { + if (isset($x['Length']) && isset($x['Width']) && isset($x['Height'])) { + $this->options[$prefix.'.Dimensions.Length'] = $x['Length']; + $this->options[$prefix.'.Dimensions.Width'] = $x['Width']; + $this->options[$prefix.'.Dimensions.Height'] = $x['Height']; + $this->options[$prefix.'.Dimensions.Unit'] = $du; + } + if (isset($x['Weight'])) { + $this->options[$prefix.'.Weight.Value'] = $x['Weight']; + $this->options[$prefix.'.Weight.Unit'] = $wu; + } + if (isset($x['TrackingId'])) { + $this->options[$prefix.'.TrackingId'] = $x['TrackingId']; + } + $i++; + } else { + $this->resetPackages(); + $this->log("Tried to set packages with invalid array",'Warning'); + return false; + } + } + } + + /** + * Resets the package list parameters. + * + * Since package details are required, these parameters should not be removed + * without replacing them, so this method is not public. + */ + protected function resetPackages() { + foreach($this->options as $op=>$junk){ + if(preg_match("#PackageList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the PRO number for the shipment. (Required for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is required when the carrier is not partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This parameter is removed by all other actions. + * @param string $sPRO number for the shipment given by the carrier
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setProNumber($s){ + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set PRO number because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if (is_string($s) && $s){ + $this->options[$op.'.ProNumber'] = $s; + } else { + return false; + } + } + + /** + * Sets the contact information for the shipment. (Required for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is required when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This parameter is removed by all other actions. + * @param string $nName of the contact person, maximum 50 characters
+ * @param string $pPhone number of the contact person, maximum 20 characters
+ * @param string $eE-mail address of the contact person, maximum 50 characters
+ * @param string $fFax number of the contact person, maximum 20 characters
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setContact($n, $p, $e, $f){ + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set contact info because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if ($n && $p && $e && $f && is_string($n) && is_string($p) && is_string($e) && is_string($f)){ + $this->options[$op.'.Contact.Name'] = $n; + $this->options[$op.'.Contact.Phone'] = $p; + $this->options[$op.'.Contact.Email'] = $e; + $this->options[$op.'.Contact.Fax'] = $f; + } else { + return false; + } + } + + /** + * Sets the box count for the shipment. (Required for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is required when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This parameter is removed by all other actions. + * @param int $nnumber of boxes
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setBoxCount($n){ + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set box count because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if (is_numeric($n) && $n > 1){ + $this->options[$op.'.BoxCount'] = $n; + } else { + return false; + } + } + + /** + * Sets the freight class for the shipment. (Optional for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is optional when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * If this parameter is not sent, Amazon will estimate the freight class on their own. + * This parameter is removed by all other actions. + * @param int $nSee the comment inside for a list of valid values.
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setFreightClass($n){ + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set freight class because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if (is_numeric($n) && $n){ + $this->options[$op.'.SellerFreightClass'] = $n; + } else { + return false; + } + /* + * Valid freight class values: + * 50 + * 55 + * 60 + * 65 + * 70 + * 77.5 + * 85 + * 92.5 + * 100 + * 110 + * 125 + * 150 + * 175 + * 200 + * 250 + * 300 + * 400 + * 500 + */ + } + + /** + * Sets the date that the shipment will be ready for pickup. (Required to send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is required when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This parameter is removed by all other actions. + * @param string $dA time string
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setReadyDate($d) { + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set ready date because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + try{ + $this->options[$op.'.FreightReadyDate'] = strstr($this->genTime($d), 'T', true); + } catch (Exception $e){ + unset($this->options[$op.'.FreightReadyDate']); + $this->log('Error: '.$e->getMessage(), 'Warning'); + return false; + } + } + + /** + * Sets the list of pallets. (Optional for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is optional when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * Each pallet array should have the following keys: + *See above.
+ * @param string $duDimensions unit: "inches" or "centimeters", defaults to centimeters
+ * @param string $wuWeight unit: "pounds" or "kilograms", defaults to kilograms
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setPallets($a, $du = 'centimeters', $wu = 'kilograms'){ + if (empty($a) || !is_array($a)) { + $this->log("Tried to set pallet list to invalid values",'Warning'); + return false; + } + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set pallets because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + $this->resetPallets(); + $i = 1; + foreach ($a as $x) { + $prefix = $op.'.PalletList.member.'.$i; + if (is_array($x)) { + if (isset($x['Length']) && isset($x['Width']) && isset($x['Height'])) { + $this->options[$prefix.'.Dimensions.Length'] = $x['Length']; + $this->options[$prefix.'.Dimensions.Width'] = $x['Width']; + $this->options[$prefix.'.Dimensions.Height'] = $x['Height']; + $this->options[$prefix.'.Dimensions.Unit'] = $du; + } + if (isset($x['Weight'])) { + $this->options[$prefix.'.Weight.Value'] = $x['Weight']; + $this->options[$prefix.'.Weight.Unit'] = $wu; + } + if (isset($x['IsStacked'])) { + if ($x['IsStacked']) { + $this->options[$prefix.'.IsStacked'] = 'true'; + } else { + $this->options[$prefix.'.IsStacked'] = 'false'; + } + } + $i++; + } else { + $this->resetPallets(); + $this->log("Tried to set pallets with invalid array",'Warning'); + return false; + } + } + } + + /** + * Resets the pallet list parameters. + * + * Use this in case you change your mind and want to remove the pallet parameters you previously set. + */ + public function resetPallets() { + foreach($this->options as $op=>$junk){ + if(preg_match("#PalletList#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the total weight for the shipment. (Optional for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is optional when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This parameter is removed by all other actions. + * @param string $vDecimal number
+ * @param string $u"pounds" or "kilograms", defaults to kilograms
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setTotalWeight($v, $u = 'kilograms') { + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set total weight because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if (!empty($v) && !empty($u) && is_numeric($v) && ($u == 'pounds' || $u == 'kilograms')){ + $this->options[$op.'.TotalWeight.Value'] = $v; + $this->options[$op.'.TotalWeight.Unit'] = $u; + } else { + return false; + } + } + + /** + * Sets the declared value for the shipment. (Optional for send*) + * + * The partnered and shipment type parameters must be set before setting this parameter. + * This parameter is optional when the carrier is partnered and the + * shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This parameter is removed by all other actions. + * @param string $vMoney amount
+ * @param string $cISO 4217 currency code (ex: USD)
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setDeclaredValue($v, $c) { + $op = $this->determineDetailOption(); + if (!$op) { + $this->log('Cannot set declared value because of the shipment type and partnered parameters.', 'Warning'); + return false; + } + if (!empty($v) && !empty($c) && is_numeric($v) && is_string($c) && !is_numeric($c)){ + $this->options[$op.'.SellerDeclaredValue.Value'] = $v; + $this->options[$op.'.SellerDeclaredValue.CurrencyCode'] = $c; + } else { + return false; + } + } + + /** + * Resets the transport detail parameters. + * + * Since transport details are required, these parameters should not be removed + * without replacing them, so this method is not public. + */ + protected function resetTransportDetails() { + foreach($this->options as $op=>$junk){ + if(preg_match("#TransportDetails#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Removes all parameters specific to sending transport content info. + * The following parameters are removed: + * IsPartnered, shipment type, and all transport details. + * @see resetTransportDetails + */ + protected function resetSendParams() { + unset($this->options['IsPartnered']); + unset($this->options['ShipmentType']); + $this->resetTransportDetails(); + } + + /** + * Sends transport content information for a shipment with Amazon. + * + * Submits a PutTransportContent request to Amazon. In order to do this, + * a fulfillment shipment ID, shipment type, IsPartnered, and + * various details are required. The exact details required depend on the + * IsPartnered and shipment type parameters set. + * Amazon will send a status back as a response, which can be retrieved + * using getStatus. + * @return boolean FALSE if something goes wrong + * @see verifySendParams + */ + public function sendTransportContents() { + if (!$this->verifySendParams()) { + return false; + } + + $this->prepareSend(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using sendTransportContents. + * + * This changes key options for using sendTransportContents. + */ + protected function prepareSend() { + $this->throttleGroup = 'PutTransportContent'; + $this->options['Action'] = 'PutTransportContent'; + } + + /** + * Checks to see if all of the parameters needed for sendTransportContents are set. + * @return boolean TRUE if everything is good, FALSE if something is missing + */ + protected function verifySendParams() { + $m = ' must be set in order to send transport content!'; + //common requirements + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('Shipment ID'.$m, 'Warning'); + return false; + } + if (!array_key_exists('IsPartnered', $this->options)) { + $this->log('IsPartnered'.$m, 'Warning'); + return false; + } + if (!array_key_exists('ShipmentType', $this->options)) { + $this->log('Shipment type'.$m, 'Warning'); + return false; + } + //requirements based on partnership and type + $p = $this->options['IsPartnered'] == 'true'; + $sp = $this->options['ShipmentType'] == 'SP'; + $ltl = $this->options['ShipmentType'] == 'LTL'; + //options could be in four possible places, so a search is needed + $foundCarrier = false; + $foundPackages = false; + $foundPro = false; + $foundContact = false; + $foundBoxCount = false; + $foundReady = false; + foreach ($this->options as $op=>$junk) { + if(preg_match("#CarrierName#",$op)){ + $foundCarrier = true; + } + if(preg_match("#PackageList\.member\.1#",$op)){ + $foundPackages = true; + } + if(preg_match("#ProNumber#",$op)){ + $foundPro = true; + } + if(preg_match("#Contact\.Name#",$op)){ + $foundContact = true; + } + if(preg_match("#BoxCount#",$op)){ + $foundBoxCount = true; + } + if(preg_match("#FreightReadyDate#",$op)){ + $foundReady = true; + } + } + if (!$p && !$foundCarrier) { + $this->log('Carrier'.$m, 'Warning'); + return false; + } + if ($sp && !$foundPackages) { + $this->log('Packages'.$m, 'Warning'); + return false; + } + if (!$p && $ltl && !$foundPro) { + $this->log('PRO number'.$m, 'Warning'); + return false; + } + if ($p && $ltl && !$foundContact) { + $this->log('Contact info'.$m, 'Warning'); + return false; + } + if ($p && $ltl && !$foundBoxCount) { + $this->log('Box count'.$m, 'Warning'); + return false; + } + if ($p && $ltl && !$foundReady) { + $this->log('Ready date'.$m, 'Warning'); + return false; + } + + //all good + return true; + } + + /** + * Gets transport content information for a shipment from Amazon. + * + * Submits a GetTransportContent request to Amazon. In order to do this, + * a fulfillment shipment ID is required. + * Before this action can be used, information about the transport contents + * must be provided to Amazon using sendTransportContents. + * Amazon will send data back as a response, which can be retrieved using getContentInfo. + * The status of the transport request can be retrieved using getStatus. + * @return boolean FALSE if something goes wrong + */ + public function fetchTransportContent() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('Shipment ID must be set in order to get transport contents!', 'Warning'); + return false; + } + + $this->prepareGetContent(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using fetchTransportContent. + * + * This changes key options for using fetchTransportContent. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. + * @see resetSendParams + */ + protected function prepareGetContent() { + $this->throttleGroup = 'GetTransportContent'; + $this->options['Action'] = 'GetTransportContent'; + $this->resetSendParams(); + } + + /** + * Sends a request to Amazon to start estimating a shipping request. + * + * Submits a EstimateTransportRequest request to Amazon. In order to do this, + * a fulfillment shipment ID is required. + * Before this action can be used, information about the transport contents + * must be provided to Amazon using sendTransportContents. + * Amazon will send a status back as a response, which can be retrieved + * using getStatus. + * @return boolean FALSE if something goes wrong + */ + public function estimateTransport() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('Shipment ID must be set in order to estimate the transport request!', 'Warning'); + return false; + } + + $this->prepareEstimate(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using estimateTransport. + * + * This changes key options for using estimateTransport. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. + * @see resetSendParams + */ + protected function prepareEstimate() { + $this->throttleGroup = 'EstimateTransportRequest'; + $this->options['Action'] = 'EstimateTransportRequest'; + $this->resetSendParams(); + } + + /** + * Confirms an estimated transport request with Amazon. + * + * Submits a ConfirmTransportRequest request to Amazon. In order to do this, + * a fulfillment shipment ID is required. + * Before this action can be used, the transport info must be estimated by Amazon, + * which can be done by using estimateTransport. + * Amazon will send a status back as a response, which can be retrieved + * using getStatus. + * @return boolean FALSE if something goes wrong + */ + public function confirmTransport() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('Shipment ID must be set in order to confirm the transport request!', 'Warning'); + return false; + } + + $this->prepareConfirm(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using confirmTransport. + * + * This changes key options for using confirmTransport. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. + * @see resetSendParams + */ + protected function prepareConfirm() { + $this->throttleGroup = 'ConfirmTransportRequest'; + $this->options['Action'] = 'ConfirmTransportRequest'; + $this->resetSendParams(); + } + + /** + * Voids a previously-confirmed transport request with Amazon. + * + * Submits a VoidTransportRequest request to Amazon. In order to do this, + * a fulfillment shipment ID is required. + * Before this action can be used, the transport info must have been confirmed + * using confirmTransport. + * Amazon will send a status back as a response, which can be retrieved + * using getStatus. + * @return boolean FALSE if something goes wrong + */ + public function voidTransport() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('Shipment ID must be set in order to void the transport request!', 'Warning'); + return false; + } + + $this->prepareVoid(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using voidTransport. + * + * This changes key options for using voidTransport. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. + * @see resetSendParams + */ + protected function prepareVoid() { + $this->throttleGroup = 'VoidTransportRequest'; + $this->options['Action'] = 'VoidTransportRequest'; + $this->resetSendParams(); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml){ + return false; + } + + //response from send, confirm, estimate, void + if (isset($xml->TransportResult->TransportStatus)) { + $this->status = (string)$xml->TransportResult->TransportStatus; + } + //response from get + if (isset($xml->TransportContent)) { + $this->contents = array(); + $this->status = (string)$xml->TransportContent->TransportResult->TransportStatus; + $this->contents['SellerId'] = (string)$xml->TransportContent->TransportHeader->SellerId; + $this->contents['ShipmentId'] = (string)$xml->TransportContent->TransportHeader->ShipmentId; + $this->contents['IsPartnered'] = (string)$xml->TransportContent->TransportHeader->IsPartnered; + $this->contents['ShipmentType'] = (string)$xml->TransportContent->TransportHeader->ShipmentType; + + //one of four possible response structures for details + $this->contents['Details'] = array(); + $d = array(); + if (isset($xml->TransportContent->TransportDetails->PartneredSmallParcelData)) { + //Partnered + SP + $d = $xml->TransportContent->TransportDetails->PartneredSmallParcelData; + } else if (isset($xml->TransportContent->TransportDetails->NonPartneredSmallParcelData)) { + //Non-Partnered + SP + $d = $xml->TransportContent->TransportDetails->NonPartneredSmallParcelData; + } else if (isset($xml->TransportContent->TransportDetails->PartneredLtlData)) { + //Partnered + LTL + $d = $xml->TransportContent->TransportDetails->PartneredLtlData; + $this->contents['Details']['Contact']['Name'] = (string)$d->Contact->Name; + $this->contents['Details']['Contact']['Phone'] = (string)$d->Contact->Phone; + $this->contents['Details']['Contact']['Email'] = (string)$d->Contact->Email; + $this->contents['Details']['Contact']['Fax'] = (string)$d->Contact->Fax; + $this->contents['Details']['BoxCount'] = (string)$d->BoxCount; + if (isset($d->SellerFreightClass)) { + $this->contents['Details']['SellerFreightClass'] = (string)$d->SellerFreightClass; + } + $this->contents['Details']['FreightReadyDate'] = (string)$d->FreightReadyDate; + foreach ($d->PalletList->children() as $x) { + $temp = array(); + $temp['IsStacked'] = (string)$x->IsStacked; + $temp['Dimensions']['Unit'] = (string)$x->Dimensions->Unit; + $temp['Dimensions']['Length'] = (string)$x->Dimensions->Length; + $temp['Dimensions']['Width'] = (string)$x->Dimensions->Width; + $temp['Dimensions']['Height'] = (string)$x->Dimensions->Height; + if (isset($x->Weight)) { + $temp['Weight']['Value'] = (string)$x->Weight->Value; + $temp['Weight']['Unit'] = (string)$x->Weight->Unit; + } + $this->contents['Details']['PalletList'][] = $temp; + } + $this->contents['Details']['TotalWeight']['Value'] = (string)$d->TotalWeight->Value; + $this->contents['Details']['TotalWeight']['Unit'] = (string)$d->TotalWeight->Unit; + if (isset($d->SellerDeclaredValue)) { + $this->contents['Details']['SellerDeclaredValue']['Value'] = (string)$d->SellerDeclaredValue->Value; + $this->contents['Details']['SellerDeclaredValue']['CurrencyCode'] = (string)$d->SellerDeclaredValue->CurrencyCode; + } + if (isset($d->AmazonCalculatedValue)) { + $this->contents['Details']['AmazonCalculatedValue']['Value'] = (string)$d->AmazonCalculatedValue->Value; + $this->contents['Details']['AmazonCalculatedValue']['CurrencyCode'] = (string)$d->AmazonCalculatedValue->CurrencyCode; + } + $this->contents['Details']['PreviewPickupDate'] = (string)$d->PreviewPickupDate; + $this->contents['Details']['PreviewDeliveryDate'] = (string)$d->PreviewDeliveryDate; + $this->contents['Details']['PreviewFreightClass'] = (string)$d->PreviewFreightClass; + $this->contents['Details']['AmazonReferenceId'] = (string)$d->AmazonReferenceId; + $this->contents['Details']['IsBillOfLadingAvailable'] = (string)$d->IsBillOfLadingAvailable; + $this->contents['Details']['CarrierName'] = (string)$d->CarrierName; + } else if (isset($xml->TransportContent->TransportDetails->NonPartneredLtlData)) { + //Non-Partnered + LTL + $d = $xml->TransportContent->TransportDetails->NonPartneredLtlData; + $this->contents['Details']['CarrierName'] = (string)$d->CarrierName; + $this->contents['Details']['ProNumber'] = (string)$d->ProNumber; + } + //shared by both SP structures + if (isset($d->PackageList)) { + foreach ($d->PackageList->children() as $x) { + $temp = array(); + $temp['TrackingId'] = (string)$x->TrackingId; + $temp['PackageStatus'] = (string)$x->PackageStatus; + $temp['CarrierName'] = (string)$x->CarrierName; + if (isset($x->Weight)) { + $temp['Weight']['Value'] = (string)$x->Weight->Value; + $temp['Weight']['Unit'] = (string)$x->Weight->Unit; + } + if (isset($x->Dimensions)) { + $temp['Dimensions']['Unit'] = (string)$x->Dimensions->Unit; + $temp['Dimensions']['Length'] = (string)$x->Dimensions->Length; + $temp['Dimensions']['Width'] = (string)$x->Dimensions->Width; + $temp['Dimensions']['Height'] = (string)$x->Dimensions->Height; + } + $this->contents['Details']['PackageList'][] = $temp; + } + } + //shared by both partnered structures + if (isset($d->PartneredEstimate)) { + $pe = array(); + $pe['Amount']['Value'] = (string)$d->PartneredEstimate->Amount->Value; + $pe['Amount']['CurrencyCode'] = (string)$d->PartneredEstimate->Amount->CurrencyCode; + if (isset($d->PartneredEstimate->ConfirmDeadline)) { + $pe['ConfirmDeadline'] = (string)$d->PartneredEstimate->ConfirmDeadline; + } + if (isset($d->PartneredEstimate->ConfirmDeadline)) { + $pe['VoidDeadline'] = (string)$d->PartneredEstimate->VoidDeadline; + } + $this->contents['Details']['PartneredEstimate'] = $pe; + } + } + } + + /** + * Returns the transport status. + * + * Possible values for the status: + * "WORKING","ERROR_ON_ESTIMATING","ESTIMATING","ESTIMATED","ERROR_ON_CONFIRMING", + * "CONFIRMING","CONFIRMED","VOIDING","VOIDED", and "ERROR_IN_VOIDING". + * This method will return FALSE if the status has not been set yet. + * @return string|boolean status value, or FALSE if value not set yet + */ + public function getStatus(){ + if (isset($this->status)){ + return $this->status; + } else { + return false; + } + } + + /** + * Returns information about transport contents. + * + * The returned array will have the following fields: + *set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if value not set yet + */ + public function getTotalWeight($only = false){ + if (isset($this->contents['Details']['TotalWeight'])){ + if ($only){ + return $this->contents['Details']['TotalWeight']['Value']; + } else { + return $this->contents['Details']['TotalWeight']; + } + } else { + return false; + } + } + + /** + * Returns the seller's declared value for the transport request. + * + * This value will only be set if the shipment is with an Amazon-partnered carrier and + * the shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This should be the same as the data that was sent when creating the transport request. + * If an array is returned, it will have the fields Value and CurrencyCode. + * This method will return FALSE if the value has not been set yet. + * @param boolean $only [optional]set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if value not set yet + */ + public function getDeclaredValue($only = false){ + if (isset($this->contents['Details']['SellerDeclaredValue'])){ + if ($only){ + return $this->contents['Details']['SellerDeclaredValue']['Value']; + } else { + return $this->contents['Details']['SellerDeclaredValue']; + } + } else { + return false; + } + } + + /** + * Returns Amazon's calculated value for the transport request. + * + * This value will only be set if the shipment is with an Amazon-partnered carrier and + * the shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * If an array is returned, it will have the fields Value and CurrencyCode. + * This method will return FALSE if the value has not been set yet. + * @param boolean $only [optional]set to TRUE to get only the value
+ * @return array|string|boolean array, single value, or FALSE if value not set yet + */ + public function getCalculatedValue($only = false){ + if (isset($this->contents['Details']['AmazonCalculatedValue'])){ + if ($only){ + return $this->contents['Details']['AmazonCalculatedValue']['Value']; + } else { + return $this->contents['Details']['AmazonCalculatedValue']; + } + } else { + return false; + } + } + + /** + * Returns the estimated pickup date for the transport request. + * + * This value will only be set if the shipment is with an Amazon-partnered carrier and + * the shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This method will return FALSE if the value has not been set yet. + * @return string|boolean date in ISO 8601 format, or FALSE if value not set yet + */ + public function getPickupDate() { + if (isset($this->contents['Details']['PreviewPickupDate'])){ + return $this->contents['Details']['PreviewPickupDate']; + } else { + return false; + } + } + + /** + * Returns the estimated date for when the shipment will be delivered to an Amazon fulfillment center. + * + * This value will only be set if the shipment is with an Amazon-partnered carrier and + * the shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This method will return FALSE if the value has not been set yet. + * @return string|boolean date in ISO 8601 format, or FALSE if value not set yet + */ + public function getDeliveryDate() { + if (isset($this->contents['Details']['PreviewDeliveryDate'])){ + return $this->contents['Details']['PreviewDeliveryDate']; + } else { + return false; + } + } + + /** + * Returns the Amazon-generated reference ID for the shipment. + * + * This value will only be set if the shipment is with an Amazon-partnered carrier and + * the shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * This method will return FALSE if the value has not been set yet. + * @return string|boolean single value, or FALSE if value not set yet + */ + public function getReferenceId() { + if (isset($this->contents['Details']['AmazonReferenceId'])){ + return $this->contents['Details']['AmazonReferenceId']; + } else { + return false; + } + } + + /** + * Returns whether or not the bill of lading for the shipment is available. + * + * This value will only be set if the shipment is with an Amazon-partnered carrier and + * the shipment type is set to "LTL" for Less Than Truckload/Full Truckload. + * Note that this method will return the string "false" if Amazon indicates + * that the bill of lading is not available. + * This method will return boolean FALSE if the value has not been set yet. + * @return string|boolean "true" or "false", or FALSE if value not set yet + */ + public function getIsBillOfLadingAvailable() { + if (isset($this->contents['Details']['IsBillOfLadingAvailable'])){ + return $this->contents['Details']['IsBillOfLadingAvailable']; + } else { + return false; + } + } + +} + diff --git a/includes/classes/AmazonTransportDocument.php b/includes/classes/AmazonTransportDocument.php new file mode 100644 index 00000000..9733d015 --- /dev/null +++ b/includes/classes/AmazonTransportDocument.php @@ -0,0 +1,372 @@ +Name for the store you want to use. + * This parameter is optional if only one store is defined in the config file. + * @param string $id [optional]The Fulfillment Shipment ID to set for the object.
+ * @param boolean $mock [optional]This is a flag for enabling Mock Mode. + * This defaults to FALSE.
+ * @param array|string $m [optional]The files (or file) to use in Mock Mode.
+ * @param string $config [optional]An alternate config file to set. Used for testing.
+ */ + public function __construct($s = null, $id = null, $mock = false, $m = null, $config = null){ + parent::__construct($s, $mock, $m, $config); + + if($id){ + $this->setShipmentId($id); + } + } + + /** + * Sets the shipment ID. (Required) + * @param string $sShipment ID
+ * @return boolean FALSE if improper input + */ + public function setShipmentId($s){ + if (is_string($s) && $s){ + $this->options['ShipmentId'] = $s; + } else { + return false; + } + } + + /** + * Sets the page type. (Required for labels) + * + * This parameter is required for fetching label documents from Amazon. + * @param string $sSee the comment inside for a list of valid values.
+ * @return boolean FALSE if improper input + */ + public function setPageType($s) { + if (is_string($s) && $s){ + $this->options['PageType'] = $s; + } else { + $this->log('Tried to set PageType to invalid value', 'Warning'); + return false; + } + /* + * Valid page types: + * PackageLabel_Plain_Paper (1 per sheet) + * PackageLabel_Letter_2 (2 per sheet) + * PackageLabel_Letter_6 (6 per sheet) + * PackageLabel_A4_2 (2 per sheet) + * PackageLabel_A4_4 (4 per sheet) + */ + } + + /** + * Sets the package ID(s) to get labels for. (Required for getting package labels) + * + * The package identifiers should match the CartonId values sent in a + * previous FBA Inbound Shipment Carton Information Feed. + * Use the AmazonFeed object to send a feed. + * @param array|string $sA list of package IDs, or a single ID string.
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setPackageIds($s) { + if (is_string($s) || is_numeric($s)) { + $s = array($s); + } + if (is_array($s)){ + $this->resetPackageIds(); + $i = 1; + foreach ($s as $x){ + $this->options['PackageLabelsToPrint.member.'.$i] = $x; + $i++; + } + } else { + return false; + } + } + + /** + * Resets the package ID parameters. + * + * Since package IDs are required, these parameters should not be removed + * without replacing them, so this method is not public. + */ + protected function resetPackageIds() { + foreach($this->options as $op=>$junk){ + if(preg_match("#PackageLabelsToPrint#",$op)){ + unset($this->options[$op]); + } + } + } + + /** + * Sets the number of pallets to get labels for. (Required for getting pallet labels) + * + * @param int $nnumber of boxes
+ * @return boolean FALSE if improper input or needed parameters are not set + */ + public function setPalletCount($n){ + if (is_numeric($n) && $n >= 1){ + $this->options['NumberOfPallets'] = $n; + } else { + return false; + } + } + + /** + * Gets a document containing package labels for a shipment from Amazon. + * + * Submits a GetUniquePackageLabels request to Amazon. In order to do this, + * a fulfillment shipment ID and list of package IDs are required. + * Amazon will send a document back as a response, which can be retrieved using getDocument. + * @return boolean FALSE if something goes wrong + */ + public function fetchPackageLabels() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('ShipmentId must be set in order to get package labels!', 'Warning'); + return false; + } + if (!array_key_exists('PackageLabelsToPrint.member.1', $this->options)) { + $this->log('Package IDs must be set in order to get package labels!', 'Warning'); + return false; + } + + $this->preparePackage(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using fetchPackageLabels. + * + * This changes key options for using fetchPackageLabels. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * number of pallets. + * @see resetSendParams + */ + protected function preparePackage() { + $this->throttleGroup = 'GetUniquePackageLabels'; + $this->options['Action'] = 'GetUniquePackageLabels'; + unset($this->options['NumberOfPallets']); + } + + /** + * Gets a document containing package labels for a shipment from Amazon. + * + * Submits a GetPalletLabels request to Amazon. In order to do this, + * a fulfillment shipment ID and the number of pallets are required. + * Amazon will send a document back as a response, which can be retrieved using getDocument. + * @return boolean FALSE if something goes wrong + */ + public function fetchPalletLabels() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('ShipmentId must be set in order to get pallet labels!', 'Warning'); + return false; + } + if (!array_key_exists('NumberOfPallets', $this->options)) { + $this->log('Number of pallets must be set in order to get pallet labels!', 'Warning'); + return false; + } + + $this->preparePallet(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using fetchPalletLabels. + * + * This changes key options for using fetchPalletLabels. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * package IDs. + * @see resetSendParams + */ + protected function preparePallet() { + $this->throttleGroup = 'GetPalletLabels'; + $this->options['Action'] = 'GetPalletLabels'; + $this->resetPackageIds(); + } + + /** + * Gets a bill of lading document for a shipment from Amazon. + * + * Submits a GetBillOfLading request to Amazon. In order to do this, + * a fulfillment shipment ID for a Less Than Truckload/Full Truckload shipment is required. + * Amazon will send a document back as a response, which can be retrieved using getDocument. + * @return boolean FALSE if something goes wrong + */ + public function fetchBillOfLading() { + if (!array_key_exists('ShipmentId', $this->options)) { + $this->log('ShipmentId must be set in order to get a bill of lading!', 'Warning'); + return false; + } + + $this->prepareBillOfLading(); + + $url = $this->urlbase.$this->urlbranch; + + $query = $this->genQuery(); + + $path = $this->options['Action'].'Result'; + if ($this->mockMode){ + $xml = $this->fetchMockFile(); + } else { + $response = $this->sendRequest($url, array('Post'=>$query)); + + if (!$this->checkResponse($response)){ + return false; + } + + $xml = simplexml_load_string($response['body']); + } + + $this->parseXml($xml->$path); + } + + /** + * Sets up options for using fetchBillOfLading. + * + * This changes key options for using fetchBillOfLading. + * Please note: because the operation does not use all of the parameters, + * some of the parameters will be removed. The following parameters are removed: + * package IDs, number of pallets. + * @see resetSendParams + */ + protected function prepareBillOfLading() { + $this->throttleGroup = 'GetBillOfLading'; + $this->options['Action'] = 'GetBillOfLading'; + $this->resetPackageIds(); + unset($this->options['NumberOfPallets']); + } + + /** + * Parses XML response into array. + * + * This is what reads the response XML and converts it into an array. + * @param SimpleXMLElement $xmlThe XML response from Amazon.
+ * @return boolean FALSE if no XML data is found + */ + protected function parseXml($xml) { + if (!$xml){ + return false; + } + + //response from send, confirm, estimate, void + if (isset($xml->TransportDocument)) { + $this->doc = (string)$xml->TransportDocument->PdfDocument; + $this->checksum = (string)$xml->TransportDocument->Checksum; + } + } + + /** + * Returns the file contents for the transport document. + * + * The contents of the document depends on which action was used to retrieve the document. + * This method will return FALSE if the file has not been fetched yet. + * @param boolean $raw [optional]Set to TRUE to get the raw, base64-encoded file contents.
+ * @return string|boolean file contents, encoded file, or FALSE if file not fetched yet + */ + public function getDocument($raw = FALSE) { + if (isset($this->doc)) { + if ($raw) { + return $this->doc; + } + try { + return base64_decode($this->doc); + } catch (Exception $ex) { + $this->log('Failed to convert transport document file, file might be corrupt: '. + $ex->getMessage(), 'Urgent'); + } + } + return false; + } + + /** + * Returns the checksum the transport document. + * + * This method will return FALSE if the file has not been fetched yet. + * @param boolean $raw [optional]Set to TRUE to get the raw, base64-encoded checksum.
+ * @return string|boolean checksum, or FALSE if file not fetched yet + */ + public function getChecksum($raw = FALSE) { + if (isset($this->checksum)) { + if ($raw) { + return $this->checksum; + } + try { + return base64_decode($this->checksum); + } catch (Exception $ex) { + $this->log('Failed to convert transport document checksum, file might be corrupt: '. + $ex->getMessage(), 'Urgent'); + } + } + return false; + } + +} diff --git a/mock/.gitignore b/mock/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/mock/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/mock/createship.xml b/mock/createship.xml deleted file mode 100644 index 0aebf740..00000000 --- a/mock/createship.xml +++ /dev/null @@ -1,10 +0,0 @@ - -Plan from an AmazonShipmentPlanner object
*/ - public function testCreateShipment($o){ + public function testCreateShipment($plan) { + $o = clone $this->object; + $o->usePlan($plan); resetLog(); $this->object = new AmazonShipment('testStore',true, null, __DIR__.'/../../test-config.php'); $this->assertFalse($this->object->createShipment()); //no ID set @@ -228,9 +254,14 @@ public function testCreateShipment($o){ $a['CountryCode'] = 'CountryCode'; $a['PostalCode'] = 'PostalCode'; $this->object->setAddress($a); + $this->object->setShipmentName('test'); $this->assertFalse($this->object->createShipment()); //no items yet $o->setMock(true,'createShipment.xml'); + $this->assertFalse($o->createShipment()); //no name yet + $o->setShipmentName('test'); + $this->assertFalse($o->createShipment()); //no address yet + $o->setAddress($a); $this->assertTrue($o->createShipment()); //this one is good $op = $o->getOptions(); @@ -241,8 +272,10 @@ public function testCreateShipment($o){ $this->assertEquals('Header must be set in order to make a shipment',$check[2]); $this->assertEquals('Items must be set in order to make a shipment',$check[3]); $this->assertEquals('Single Mock File set: createShipment.xml',$check[5]); - $this->assertEquals('Fetched Mock File: mock/createShipment.xml',$check[6]); - $this->assertEquals('Successfully created Shipment #FBA63JX44',$check[7]); + $this->assertEquals('Header must be set in order to make a shipment',$check[6]); + $this->assertEquals('Address must be set in order to make a shipment',$check[7]); + $this->assertEquals('Fetched Mock File: mock/createShipment.xml',$check[8]); + $this->assertEquals('Successfully created Shipment #FBA63JX44',$check[9]); return $o; } @@ -259,8 +292,11 @@ public function testGetShipmentId($o){ /** * @depends testUsePlan + * @param array $planPlan from an AmazonShipmentPlanner object
*/ - public function testUpdateShipment($o){ + public function testUpdateShipment($plan) { + $o = clone $this->object; + $o->usePlan($plan); resetLog(); $this->object = new AmazonShipment('testStore', true, null, __DIR__.'/../../test-config.php'); $this->assertFalse($this->object->updateShipment()); //no ID set @@ -276,9 +312,14 @@ public function testUpdateShipment($o){ $a['CountryCode'] = 'CountryCode'; $a['PostalCode'] = 'PostalCode'; $this->object->setAddress($a); + $this->object->setShipmentName('test'); $this->assertFalse($this->object->updateShipment()); //no items yet $o->setMock(true,'updateShipment.xml'); + $this->assertFalse($o->updateShipment()); //no name yet + $o->setShipmentName('test'); + $this->assertFalse($o->updateShipment()); //no address yet + $o->setAddress($a); $this->assertTrue($o->updateShipment()); //this one is good $op = $o->getOptions(); @@ -289,8 +330,10 @@ public function testUpdateShipment($o){ $this->assertEquals('Header must be set in order to update a shipment',$check[2]); $this->assertEquals('Items must be set in order to update a shipment',$check[3]); $this->assertEquals('Single Mock File set: updateShipment.xml',$check[5]); - $this->assertEquals('Fetched Mock File: mock/updateShipment.xml',$check[6]); - $this->assertEquals('Successfully updated Shipment #FBA63J76R',$check[7]); + $this->assertEquals('Header must be set in order to update a shipment',$check[6]); + $this->assertEquals('Address must be set in order to update a shipment',$check[7]); + $this->assertEquals('Fetched Mock File: mock/updateShipment.xml',$check[8]); + $this->assertEquals('Successfully updated Shipment #FBA63J76R',$check[9]); } } diff --git a/test-cases/includes/classes/AmazonSubscriptionDestinationListTest.php b/test-cases/includes/classes/AmazonSubscriptionDestinationListTest.php new file mode 100644 index 00000000..6457bdbd --- /dev/null +++ b/test-cases/includes/classes/AmazonSubscriptionDestinationListTest.php @@ -0,0 +1,72 @@ +object = new AmazonSubscriptionDestinationList('testStore', true, null, __DIR__.'/../../test-config.php'); + } + + public function testFetchDestinations() { + resetLog(); + $this->object->setMock(true, 'fetchDestinations.xml'); + $this->assertNull($this->object->fetchDestinations()); + $o = $this->object->getOptions(); + $this->assertEquals('ListRegisteredDestinations', $o['Action']); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchDestinations.xml',$check[1]); + $this->assertEquals('Fetched Mock File: mock/fetchDestinations.xml',$check[2]); + + return $this->object; + } + + /** + * @param AmazonSubscriptionDestinationList $o + * @depends testFetchDestinations + */ + public function testGetDeliveryChannel($o) { + $this->assertEquals('SQS', $o->getDeliveryChannel(0)); + $this->assertEquals('SQS2', $o->getDeliveryChannel(1)); + $this->assertEquals($o->getDeliveryChannel(0), $o->getDeliveryChannel()); + //invalid keys + $this->assertFalse($o->getDeliveryChannel(4)); + $this->assertFalse($o->getDeliveryChannel('no')); + //not fetched yet for this object + $this->assertFalse($this->object->getDeliveryChannel()); + } + + /** + * @param AmazonSubscriptionDestinationList $o + * @depends testFetchDestinations + */ + public function testGetAttributes($o) { + $data1 = array( + 'sqsQueueUrl' => 'https://sqs.us-east-1.amazonaws.com/51471EXAMPLE/mws_notifications', + ); + $data2 = array( + 'url' => 'https://sqs.us-west-1.amazonaws.com/51471EXAMPLE/mws_notifications', + 'something' => '5', + ); + $this->assertEquals($data1, $o->getAttributes(0)); + $this->assertEquals($data2, $o->getAttributes(1)); + $this->assertEquals($o->getAttributes(0), $o->getAttributes()); + //invalid keys + $this->assertFalse($o->getAttributes(4)); + $this->assertFalse($o->getAttributes('no')); + //not fetched yet for this object + $this->assertFalse($this->object->getAttributes()); + } + +} + +require_once('helperFunctions.php'); diff --git a/test-cases/includes/classes/AmazonSubscriptionListTest.php b/test-cases/includes/classes/AmazonSubscriptionListTest.php new file mode 100644 index 00000000..07018a54 --- /dev/null +++ b/test-cases/includes/classes/AmazonSubscriptionListTest.php @@ -0,0 +1,116 @@ +object = new AmazonSubscriptionList('testStore', true, null, __DIR__.'/../../test-config.php'); + } + + public function testFetchSubscriptions() { + resetLog(); + $this->object->setMock(true, 'fetchSubscriptionList.xml'); + $this->assertNull($this->object->fetchSubscriptions()); + $o = $this->object->getOptions(); + $this->assertEquals('ListSubscriptions', $o['Action']); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchSubscriptionList.xml',$check[1]); + $this->assertEquals('Fetched Mock File: mock/fetchSubscriptionList.xml',$check[2]); + + return $this->object; + } + + /** + * @param AmazonSubscriptionList $o + * @depends testFetchSubscriptions + */ + public function testGetList($o) { + $list = $o->getList(); + $this->assertInternalType('array', $list); + $this->assertCount(2, $list); + $this->assertEquals($o->getList(0), $list[0]); + $this->assertEquals($o->getList(1), $list[1]); + $this->assertInternalType('array', $list[0]); + $this->assertInternalType('array', $list[1]); + } + + /** + * @param AmazonSubscriptionList $o + * @depends testFetchSubscriptions + */ + public function testGetNotificationType($o) { + $this->assertEquals('AnyOfferChanged', $o->getNotificationType(0)); + $this->assertEquals('FulfillmentOrderStatus', $o->getNotificationType(1)); + $this->assertEquals($o->getNotificationType(0), $o->getNotificationType()); + //invalid keys + $this->assertFalse($o->getNotificationType(4)); + $this->assertFalse($o->getNotificationType('no')); + //not fetched yet for this object + $this->assertFalse($this->object->getNotificationType()); + } + + /** + * @param AmazonSubscriptionList $o + * @depends testFetchSubscriptions + */ + public function testGetIsEnabled($o) { + $this->assertEquals('true', $o->getIsEnabled(0)); + $this->assertEquals('false', $o->getIsEnabled(1)); + $this->assertEquals($o->getIsEnabled(0), $o->getIsEnabled()); + //invalid keys + $this->assertFalse($o->getIsEnabled(4)); + $this->assertFalse($o->getIsEnabled('no')); + //not fetched yet for this object + $this->assertFalse($this->object->getIsEnabled()); + } + + /** + * @param AmazonSubscriptionList $o + * @depends testFetchSubscriptions + */ + public function testGetDeliveryChannel($o) { + $this->assertEquals('SQS', $o->getDeliveryChannel(0)); + $this->assertEquals('SQS2', $o->getDeliveryChannel(1)); + $this->assertEquals($o->getDeliveryChannel(0), $o->getDeliveryChannel()); + //invalid keys + $this->assertFalse($o->getDeliveryChannel(4)); + $this->assertFalse($o->getDeliveryChannel('no')); + //not fetched yet for this object + $this->assertFalse($this->object->getDeliveryChannel()); + } + + /** + * @param AmazonSubscriptionList $o + * @depends testFetchSubscriptions + */ + public function testGetAttributes($o) { + $data1 = array( + 'sqsQueueUrl' => 'https://sqs.us-east-1.amazonaws.com/51471EXAMPLE/mws_notifications', + ); + $data2 = array( + 'url' => 'https://sqs.us-west-1.amazonaws.com/51471EXAMPLE/mws_notifications', + 'something' => '7', + ); + $this->assertEquals($data1, $o->getAttributes(0)); + $this->assertEquals($data2, $o->getAttributes(1)); + $this->assertEquals($o->getAttributes(0), $o->getAttributes()); + //invalid keys + $this->assertFalse($o->getAttributes(4)); + $this->assertFalse($o->getAttributes('no')); + //not fetched yet for this object + $this->assertFalse($this->object->getAttributes()); + } + +} + +require_once('helperFunctions.php'); diff --git a/test-cases/includes/classes/AmazonSubscriptionTest.php b/test-cases/includes/classes/AmazonSubscriptionTest.php new file mode 100644 index 00000000..b28d66ae --- /dev/null +++ b/test-cases/includes/classes/AmazonSubscriptionTest.php @@ -0,0 +1,335 @@ +object = new AmazonSubscription('testStore', true, null, __DIR__.'/../../test-config.php'); + } + + public function testSetMarketplace() { + $this->assertNull($this->object->setMarketplace('ATVPDKIKX0DER2')); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('MarketplaceId', $o); + $this->assertEquals('ATVPDKIKX0DER2', $o['MarketplaceId']); + $this->assertFalse($this->object->setMarketplace(77)); //won't work for numbers + $this->assertFalse($this->object->setMarketplace(array())); //won't work for this + $this->assertFalse($this->object->setMarketplace(null)); //won't work for other things + } + + public function testSetDeliveryChannel() { + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('Destination.DeliveryChannel', $o); + $this->assertArrayHasKey('Subscription.Destination.DeliveryChannel', $o); + $this->assertEquals('SQS', $o['Destination.DeliveryChannel']); + $this->assertEquals('SQS', $o['Subscription.Destination.DeliveryChannel']); + $this->assertFalse($this->object->setDeliveryChannel(77)); //won't work for numbers + $this->assertFalse($this->object->setDeliveryChannel(array())); //won't work for this + $this->assertFalse($this->object->setDeliveryChannel(null)); //won't work for other things + } + + public function testSetAttributes() { + $this->assertNull($this->object->setAttributes(array( + 'url' => '123', + 'another' => '456', + ))); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('Destination.AttributeList.member.1.Key', $o); + $this->assertEquals('url', $o['Destination.AttributeList.member.1.Key']); + $this->assertArrayHasKey('Destination.AttributeList.member.1.Value', $o); + $this->assertEquals('123', $o['Destination.AttributeList.member.1.Value']); + $this->assertArrayHasKey('Destination.AttributeList.member.2.Key', $o); + $this->assertEquals('another', $o['Destination.AttributeList.member.2.Key']); + $this->assertArrayHasKey('Destination.AttributeList.member.2.Value', $o); + $this->assertEquals('456', $o['Destination.AttributeList.member.2.Value']); + + $this->assertNull($this->object->setAttributes(array('new' => '789'))); //causes reset + $o2 = $this->object->getOptions(); + $this->assertArrayHasKey('Destination.AttributeList.member.1.Key', $o2); + $this->assertEquals('new', $o2['Destination.AttributeList.member.1.Key']); + $this->assertArrayHasKey('Destination.AttributeList.member.1.Value', $o2); + $this->assertEquals('789', $o2['Destination.AttributeList.member.1.Value']); + $this->assertArrayNotHasKey('Destination.AttributeList.member.2.Key', $o2); + + $this->assertFalse($this->object->setAttributes(null)); + $this->assertFalse($this->object->setAttributes('banana')); + $this->assertFalse($this->object->setAttributes(707)); + } + + public function testSetNotificationType() { + $this->assertNull($this->object->setNotificationType('special')); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('Subscription.NotificationType', $o); + $this->assertArrayHasKey('NotificationType', $o); + $this->assertEquals('special', $o['Subscription.NotificationType']); + $this->assertEquals('special', $o['NotificationType']); + $this->assertFalse($this->object->setNotificationType(77)); //won't work for numbers + $this->assertFalse($this->object->setNotificationType(array())); //won't work for this + $this->assertFalse($this->object->setNotificationType(null)); //won't work for other things + } + + public function testSetIsEnabled() { + $this->assertNull($this->object->setIsEnabled()); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('Subscription.IsEnabled', $o); + $this->assertEquals('true', $o['Subscription.IsEnabled']); + $this->assertNull($this->object->setIsEnabled(false)); + $o2 = $this->object->getOptions(); + $this->assertArrayHasKey('Subscription.IsEnabled', $o2); + $this->assertEquals('false', $o2['Subscription.IsEnabled']); + } + + public function testRegisterDestination() { + resetLog(); + $this->object->setMock(true, 'registerDestination.xml'); + $this->assertNull($this->object->setIsEnabled()); + $this->assertNull($this->object->setNotificationType('special')); + $this->assertFalse($this->object->registerDestination()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->registerDestination()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertNull($this->object->registerDestination()); + $o = $this->object->getOptions(); + $this->assertEquals('RegisterDestination', $o['Action']); + $this->assertArrayNotHasKey('Subscription.Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Subscription.Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('Subscription.IsEnabled', $o); + $this->assertArrayNotHasKey('Subscription.NotificationType', $o); + $this->assertArrayNotHasKey('NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: registerDestination.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to register a subscription destination!',$check[2]); + $this->assertEquals('Attributes must be set in order to register a subscription destination!',$check[3]); + $this->assertEquals('Fetched Mock File: mock/registerDestination.xml',$check[4]); + } + + public function testDeregisterDestination() { + resetLog(); + $this->object->setMock(true, 'deregisterDestination.xml'); + $this->assertNull($this->object->setIsEnabled()); + $this->assertNull($this->object->setNotificationType('special')); + $this->assertFalse($this->object->deregisterDestination()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->deregisterDestination()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertNull($this->object->deregisterDestination()); + $o = $this->object->getOptions(); + $this->assertEquals('DeregisterDestination', $o['Action']); + $this->assertArrayNotHasKey('Subscription.Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Subscription.Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('Subscription.IsEnabled', $o); + $this->assertArrayNotHasKey('Subscription.NotificationType', $o); + $this->assertArrayNotHasKey('NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: deregisterDestination.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to deregister a subscription destination!',$check[2]); + $this->assertEquals('Attributes must be set in order to deregister a subscription destination!',$check[3]); + $this->assertEquals('Fetched Mock File: mock/deregisterDestination.xml',$check[4]); + } + + public function testTestDestination() { + resetLog(); + $this->object->setMock(true, 'pingDestination.xml'); + $this->assertNull($this->object->setIsEnabled()); + $this->assertNull($this->object->setNotificationType('special')); + $this->assertFalse($this->object->testDestination()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->testDestination()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertNull($this->object->testDestination()); + $o = $this->object->getOptions(); + $this->assertEquals('SendTestNotificationToDestination', $o['Action']); + $this->assertArrayNotHasKey('Subscription.Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Subscription.Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('Subscription.IsEnabled', $o); + $this->assertArrayNotHasKey('Subscription.NotificationType', $o); + $this->assertArrayNotHasKey('NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: pingDestination.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to test a subscription destination!',$check[2]); + $this->assertEquals('Attributes must be set in order to test a subscription destination!',$check[3]); + $this->assertEquals('Fetched Mock File: mock/pingDestination.xml',$check[4]); + } + + public function testCreateSubscription() { + resetLog(); + $this->object->setMock(true, 'createSubscription.xml'); + $this->assertFalse($this->object->createSubscription()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->createSubscription()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertFalse($this->object->createSubscription()); //no notification type yet + $this->assertNull($this->object->setNotificationType('special')); + $this->assertFalse($this->object->createSubscription()); //no enabled yet + $this->assertNull($this->object->setIsEnabled()); + $this->assertNull($this->object->createSubscription()); + $o = $this->object->getOptions(); + $this->assertEquals('CreateSubscription', $o['Action']); + $this->assertArrayNotHasKey('Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: createSubscription.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to create a subscription!',$check[2]); + $this->assertEquals('Attributes must be set in order to create a subscription!',$check[3]); + $this->assertEquals('Notification type must be set in order to create a subscription!',$check[4]); + $this->assertEquals('Enabled status must be set in order to create a subscription!',$check[5]); + $this->assertEquals('Fetched Mock File: mock/createSubscription.xml',$check[6]); + } + + public function testFetchSubscription() { + resetLog(); + $this->object->setMock(true, 'fetchSubscription.xml'); + $this->object->setIsEnabled(); + $this->assertFalse($this->object->fetchSubscription()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->fetchSubscription()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertFalse($this->object->fetchSubscription()); //no notification type yet + $this->assertNull($this->object->setNotificationType('special')); + $this->assertNull($this->object->fetchSubscription()); + $o = $this->object->getOptions(); + $this->assertEquals('GetSubscription', $o['Action']); + $this->assertArrayNotHasKey('Subscription.Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Subscription.Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('Subscription.IsEnabled', $o); + $this->assertArrayNotHasKey('Subscription.NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchSubscription.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to fetch a subscription!',$check[2]); + $this->assertEquals('Attributes must be set in order to fetch a subscription!',$check[3]); + $this->assertEquals('Notification type must be set in order to fetch a subscription!',$check[4]); + $this->assertEquals('Fetched Mock File: mock/fetchSubscription.xml',$check[5]); + + return $this->object; + } + + public function testUpdateSubscription() { + resetLog(); + $this->object->setMock(true, 'updateSubscription.xml'); + $this->assertFalse($this->object->updateSubscription()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->updateSubscription()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertFalse($this->object->updateSubscription()); //no notification type yet + $this->assertNull($this->object->setNotificationType('special')); + $this->assertFalse($this->object->updateSubscription()); //no enabled yet + $this->assertNull($this->object->setIsEnabled()); + $this->assertNull($this->object->updateSubscription()); + $o = $this->object->getOptions(); + $this->assertEquals('UpdateSubscription', $o['Action']); + $this->assertArrayNotHasKey('Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: updateSubscription.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to update a subscription!',$check[2]); + $this->assertEquals('Attributes must be set in order to update a subscription!',$check[3]); + $this->assertEquals('Notification type must be set in order to update a subscription!',$check[4]); + $this->assertEquals('Enabled status must be set in order to update a subscription!',$check[5]); + $this->assertEquals('Fetched Mock File: mock/updateSubscription.xml',$check[6]); + } + + public function testDeleteSubscription() { + resetLog(); + $this->object->setMock(true, 'deleteSubscription.xml'); + $this->object->setIsEnabled(); + $this->assertFalse($this->object->deleteSubscription()); //no channel yet + $this->assertNull($this->object->setDeliveryChannel('SQS')); + $this->assertFalse($this->object->deleteSubscription()); //no attributes yet + $this->assertNull($this->object->setAttributes(array('url'=>'google'))); + $this->assertFalse($this->object->deleteSubscription()); //no notification type yet + $this->assertNull($this->object->setNotificationType('special')); + $this->assertNull($this->object->deleteSubscription()); + $o = $this->object->getOptions(); + $this->assertEquals('DeleteSubscription', $o['Action']); + $this->assertArrayNotHasKey('Subscription.Destination.DeliveryChannel', $o); + $this->assertArrayNotHasKey('Subscription.Destination.AttributeList.member.1.Key', $o); + $this->assertArrayNotHasKey('Subscription.IsEnabled', $o); + $this->assertArrayNotHasKey('Subscription.NotificationType', $o); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: deleteSubscription.xml',$check[1]); + $this->assertEquals('Delivery channel must be set in order to delete a subscription!',$check[2]); + $this->assertEquals('Attributes must be set in order to delete a subscription!',$check[3]); + $this->assertEquals('Notification type must be set in order to delete a subscription!',$check[4]); + $this->assertEquals('Fetched Mock File: mock/deleteSubscription.xml',$check[5]); + } + + /** + * @param AmazonSubscription $o + * @depends testFetchSubscription + */ + public function testGetSubscription($o) { + $data = array(); + $data['NotificationType'] = $o->getNotificationType(); + $data['IsEnabled'] = $o->getIsEnabled(); + $data['Destination']['DeliveryChannel'] = $o->getDeliveryChannel(); + $data['Destination']['AttributeList'] = $o->getAttributes(); + $this->assertEquals($data, $o->getSubscription()); + //not fetched yet for this object + $this->assertFalse($this->object->getSubscription()); + } + + /** + * @param AmazonSubscription $o + * @depends testFetchSubscription + */ + public function testGetNotificationType($o) { + $this->assertEquals('AnyOfferChanged', $o->getNotificationType()); + //not fetched yet for this object + $this->assertFalse($this->object->getNotificationType()); + } + + /** + * @param AmazonSubscription $o + * @depends testFetchSubscription + */ + public function testGetIsEnabled($o) { + $this->assertEquals('true', $o->getIsEnabled()); + //not fetched yet for this object + $this->assertFalse($this->object->getIsEnabled()); + } + + /** + * @param AmazonSubscription $o + * @depends testFetchSubscription + */ + public function testGetDeliveryChannel($o) { + $this->assertEquals('SQS', $o->getDeliveryChannel()); + //not fetched yet for this object + $this->assertFalse($this->object->getDeliveryChannel()); + } + + /** + * @param AmazonSubscription $o + * @depends testFetchSubscription + */ + public function testGetAttributes($o) { + $data = array( + 'sqsQueueUrl' => 'https://sqs.us-east-1.amazonaws.com/51471EXAMPLE/mws_notifications', + ); + $this->assertEquals($data, $o->getAttributes()); + //not fetched yet for this object + $this->assertFalse($this->object->getAttributes()); + } + +} + +require_once('helperFunctions.php'); diff --git a/test-cases/includes/classes/AmazonTransportDocumentTest.php b/test-cases/includes/classes/AmazonTransportDocumentTest.php new file mode 100644 index 00000000..44258161 --- /dev/null +++ b/test-cases/includes/classes/AmazonTransportDocumentTest.php @@ -0,0 +1,137 @@ +object = new AmazonTransportDocument('testStore', null, true, null, __DIR__.'/../../test-config.php'); + } + + public function testSetUp() { + $obj = new AmazonTransportDocument('testStore', '77', true, null, __DIR__.'/../../test-config.php'); + + $o = $obj->getOptions(); + $this->assertArrayHasKey('ShipmentId',$o); + $this->assertEquals('77', $o['ShipmentId']); + } + + public function testSetShipmentId() { + $this->assertNull($this->object->setShipmentId('777')); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('ShipmentId', $o); + $this->assertEquals('777', $o['ShipmentId']); + $this->assertFalse($this->object->setShipmentId(77)); //won't work for numbers + $this->assertFalse($this->object->setShipmentId(array())); //won't work for this + $this->assertFalse($this->object->setShipmentId(null)); //won't work for other things + } + + public function testSetPackageIds(){ + $ok = $this->object->setPackageIds('string1'); + $this->assertNull($ok); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('PackageLabelsToPrint.member.1', $o); + $this->assertEquals('string1', $o['PackageLabelsToPrint.member.1']); + $ok2 = $this->object->setPackageIds(array('string1', 'string2')); + $this->assertNull($ok2); + $o2 = $this->object->getOptions(); + $this->assertArrayHasKey('PackageLabelsToPrint.member.1', $o2); + $this->assertArrayHasKey('PackageLabelsToPrint.member.2', $o2); + $this->assertEquals('string1', $o2['PackageLabelsToPrint.member.1']); + $this->assertEquals('string2', $o2['PackageLabelsToPrint.member.2']); + $this->object->setPackageIds('stringx'); + $o3 = $this->object->getOptions(); + $this->assertArrayNotHasKey('PackageLabelsToPrint.member.2', $o3); + $this->assertFalse($this->object->setPackageIds(null)); + } + + public function testSetPalletCount(){ + $this->assertFalse($this->object->setPalletCount(null)); //can't be nothing + $this->assertFalse($this->object->setPalletCount('NaN')); //can't be a string + $this->assertFalse($this->object->setPalletCount(-5)); //can't be negative + $this->assertNull($this->object->setPalletCount(5)); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('NumberOfPallets', $o); + $this->assertEquals('5', $o['NumberOfPallets']); + } + + public function testFetchPackageLabels() { + //not fetched for the object yet + $this->assertFalse($this->object->getDocument()); + $this->assertFalse($this->object->getChecksum()); + resetLog(); + $this->object->setMock(true,'fetchPackageLabels.xml'); + $this->assertFalse($this->object->fetchPackageLabels()); //no shipment ID set yet + $this->object->setShipmentId('77'); + $this->assertFalse($this->object->fetchPackageLabels()); //no package IDs set yet + $this->object->setPackageIds('88'); + $this->assertNull($this->object->fetchPackageLabels()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchPackageLabels.xml',$check[1]); + $this->assertEquals('ShipmentId must be set in order to get package labels!',$check[2]); + $this->assertEquals('Package IDs must be set in order to get package labels!',$check[3]); + $this->assertEquals('Fetched Mock File: mock/fetchPackageLabels.xml',$check[4]); + + $this->assertEquals('package test', $this->object->getDocument()); + $this->assertEquals(base64_encode('package test'), $this->object->getDocument(true)); + $this->assertEquals('this is a checksum', $this->object->getChecksum()); + $this->assertEquals(base64_encode('this is a checksum'), $this->object->getChecksum(true)); + } + + public function testFetchPalletLabels() { + //not fetched for the object yet + $this->assertFalse($this->object->getDocument()); + $this->assertFalse($this->object->getChecksum()); + resetLog(); + $this->object->setMock(true,'fetchPalletLabels.xml'); + $this->assertFalse($this->object->fetchPalletLabels()); //no shipment ID set yet + $this->object->setShipmentId('77'); + $this->assertFalse($this->object->fetchPalletLabels()); //no number of pallets set + $this->object->setPalletCount('88'); + $this->assertNull($this->object->fetchPalletLabels()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchPalletLabels.xml',$check[1]); + $this->assertEquals('ShipmentId must be set in order to get pallet labels!',$check[2]); + $this->assertEquals('Number of pallets must be set in order to get pallet labels!',$check[3]); + $this->assertEquals('Fetched Mock File: mock/fetchPalletLabels.xml',$check[4]); + + $this->assertEquals('pallet test', $this->object->getDocument()); + $this->assertEquals(base64_encode('pallet test'), $this->object->getDocument(true)); + $this->assertEquals('this is a checksum', $this->object->getChecksum()); + $this->assertEquals(base64_encode('this is a checksum'), $this->object->getChecksum(true)); + } + + public function testBillOfLading() { + //not fetched for the object yet + $this->assertFalse($this->object->getDocument()); + $this->assertFalse($this->object->getChecksum()); + resetLog(); + $this->object->setMock(true,'fetchBillOfLading.xml'); + $this->assertFalse($this->object->fetchBillOfLading()); //no shipment ID set yet + $this->object->setShipmentId('77'); + $this->assertNull($this->object->fetchBillOfLading()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchBillOfLading.xml',$check[1]); + $this->assertEquals('ShipmentId must be set in order to get a bill of lading!',$check[2]); + $this->assertEquals('Fetched Mock File: mock/fetchBillOfLading.xml',$check[3]); + + $this->assertEquals('bill of lading', $this->object->getDocument()); + $this->assertEquals(base64_encode('bill of lading'), $this->object->getDocument(true)); + $this->assertEquals('this is a checksum', $this->object->getChecksum()); + $this->assertEquals(base64_encode('this is a checksum'), $this->object->getChecksum(true)); + } + +} + +require_once('helperFunctions.php'); diff --git a/test-cases/includes/classes/AmazonTransportTest.php b/test-cases/includes/classes/AmazonTransportTest.php new file mode 100644 index 00000000..1e4dc3a0 --- /dev/null +++ b/test-cases/includes/classes/AmazonTransportTest.php @@ -0,0 +1,1472 @@ +object = new AmazonTransport('testStore', null, true, null, __DIR__.'/../../test-config.php'); + } + + public function testSetUp() { + $obj = new AmazonTransport('testStore', '77', true, null, __DIR__.'/../../test-config.php'); + + $o = $obj->getOptions(); + $this->assertArrayHasKey('ShipmentId', $o); + $this->assertEquals('77', $o['ShipmentId']); + } + + public function testSetShipmentId() { + $this->assertNull($this->object->setShipmentId('777')); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('ShipmentId', $o); + $this->assertEquals('777', $o['ShipmentId']); + $this->assertFalse($this->object->setShipmentId(77)); //won't work for numbers + $this->assertFalse($this->object->setShipmentId(array())); //won't work for this + $this->assertFalse($this->object->setShipmentId(null)); //won't work for other things + } + + public function testSetIsPartnered() { + $o1 = $this->object->getOptions(); + $this->assertArrayNotHasKey('IsPartnered', $o1); + $this->assertNull($this->object->setIsPartnered(true)); + $o2 = $this->object->getOptions(); + $this->assertArrayHasKey('IsPartnered', $o2); + $this->assertEquals('true', $o2['IsPartnered']); + $this->assertNull($this->object->setIsPartnered(false)); + $o3 = $this->object->getOptions(); + $this->assertArrayHasKey('IsPartnered', $o3); + $this->assertEquals('false', $o3['IsPartnered']); + } + + public function testSetShipmentType(){ + $this->assertFalse($this->object->setShipmentType(null)); //can't be nothing + $this->assertFalse($this->object->setShipmentType(5)); //can't be an int + $this->assertFalse($this->object->setShipmentType('wrong')); //not a valid value + $this->assertNull($this->object->setShipmentType('SP')); + $this->assertNull($this->object->setShipmentType('LTL')); + $o = $this->object->getOptions(); + $this->assertArrayHasKey('ShipmentType', $o); + $this->assertEquals('LTL', $o['ShipmentType']); + } + + /** + * @return array + */ + public function comboProvider() { + return array( + array('SP', true), + array('SP', false), + array('LTL', true), + array('LTL', false), + ); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetCarrier($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setCarrier('truck')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setCarrier('truck')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setCarrier('truck')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.CarrierName'; + $this->assertArrayHasKey($op, $o); + $this->assertEquals('truck', $o[$op]); + + //invalid values + $this->assertFalse($this->object->setCarrier('')); + $this->assertFalse($this->object->setCarrier(null)); + $this->assertFalse($this->object->setCarrier(6)); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set carrier name because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetPackages($type, $partnered) { + $op = $this->findOp($type, $partnered); + resetLog(); + + $data1 = array( + array( + 'Length' => '6', + 'Width' => '7', + 'Height' => '8', + 'Weight' => '9.8', + ), + array( + 'Length' => '6', + 'Width' => '7', + 'TrackingId' => 'Z123', + ), + array( + 'TrackingId' => 'Z456', + ), + ); + + $this->assertFalse($this->object->setPackages($data1)); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setPackages($data1)); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setPackages($data1)); + $o = $this->object->getOptions(); + //package 1/3 + $this->assertArrayHasKey($op.'.PackageList.member.1.Dimensions.Length', $o); + $this->assertEquals('6', $o[$op.'.PackageList.member.1.Dimensions.Length']); + $this->assertArrayHasKey($op.'.PackageList.member.1.Dimensions.Width', $o); + $this->assertEquals('7', $o[$op.'.PackageList.member.1.Dimensions.Width']); + $this->assertArrayHasKey($op.'.PackageList.member.1.Dimensions.Height', $o); + $this->assertEquals('8', $o[$op.'.PackageList.member.1.Dimensions.Height']); + $this->assertArrayHasKey($op.'.PackageList.member.1.Dimensions.Unit', $o); + $this->assertEquals('centimeters', $o[$op.'.PackageList.member.1.Dimensions.Unit']); + $this->assertArrayHasKey($op.'.PackageList.member.1.Weight.Value', $o); + $this->assertEquals('9.8', $o[$op.'.PackageList.member.1.Weight.Value']); + $this->assertArrayHasKey($op.'.PackageList.member.1.Weight.Unit', $o); + $this->assertEquals('kilograms', $o[$op.'.PackageList.member.1.Weight.Unit']); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.TrackingId', $o); + //package 2/3 + $this->assertArrayHasKey($op.'.PackageList.member.2.TrackingId', $o); + $this->assertEquals('Z123', $o[$op.'.PackageList.member.2.TrackingId']); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.Dimensions.Length', $o); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.Dimensions.Width', $o); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.Dimensions.Height', $o); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.Dimensions.Unit', $o); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.Weight.Value', $o); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.Weight.Unit', $o); + //package 3/3 + $this->assertArrayHasKey($op.'.PackageList.member.3.TrackingId', $o); + $this->assertEquals('Z456', $o[$op.'.PackageList.member.3.TrackingId']); + + //setting again will cause a reset + $data2 = array( + array( + 'TrackingId' => 'Z789', + ), + array( + 'Length' => '10', + 'Width' => '11', + 'Height' => '12', + 'Weight' => '20', + ), + ); + + $this->assertNull($this->object->setPackages($data2, 'inches', 'pounds')); + $o2 = $this->object->getOptions(); + //package 1/2 + $this->assertArrayHasKey($op.'.PackageList.member.1.TrackingId', $o2); + $this->assertEquals('Z789', $o2[$op.'.PackageList.member.1.TrackingId']); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.Dimensions.Length', $o2); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.Dimensions.Width', $o2); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.Dimensions.Height', $o2); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.Dimensions.Unit', $o2); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.Weight.Value', $o2); + $this->assertArrayNotHasKey($op.'.PackageList.member.1.Weight.Unit', $o2); + //package 2/2 + $this->assertArrayHasKey($op.'.PackageList.member.2.Dimensions.Length', $o2); + $this->assertEquals('10', $o2[$op.'.PackageList.member.2.Dimensions.Length']); + $this->assertArrayHasKey($op.'.PackageList.member.2.Dimensions.Width', $o2); + $this->assertEquals('11', $o2[$op.'.PackageList.member.2.Dimensions.Width']); + $this->assertArrayHasKey($op.'.PackageList.member.2.Dimensions.Height', $o2); + $this->assertEquals('12', $o2[$op.'.PackageList.member.2.Dimensions.Height']); + $this->assertArrayHasKey($op.'.PackageList.member.2.Dimensions.Unit', $o2); + $this->assertEquals('inches', $o2[$op.'.PackageList.member.2.Dimensions.Unit']); + $this->assertArrayHasKey($op.'.PackageList.member.2.Weight.Value', $o2); + $this->assertEquals('20', $o2[$op.'.PackageList.member.2.Weight.Value']); + $this->assertArrayHasKey($op.'.PackageList.member.2.Weight.Unit', $o2); + $this->assertEquals('pounds', $o2[$op.'.PackageList.member.2.Weight.Unit']); + $this->assertArrayNotHasKey($op.'.PackageList.member.2.TrackingId', $o2); + //no package 3 + $this->assertArrayNotHasKey($op.'.PackageList.member.3.TrackingId', $o2); + + + //invalid values + $this->assertFalse($this->object->setPackages(array('banana'))); + $this->assertFalse($this->object->setPackages(array())); + $this->assertFalse($this->object->setPackages('banana')); + $this->assertFalse($this->object->setPackages(6)); + $this->assertFalse($this->object->setPackages(null)); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set packages because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + $this->assertEquals('Tried to set packages with invalid array', $check[4]); + $this->assertEquals('Tried to set package list to invalid values', $check[5]); + $this->assertEquals($check[5], $check[6]); + $this->assertEquals($check[5], $check[7]); + $this->assertEquals($check[5], $check[8]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetProNumber($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setProNumber('123ABC7')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setProNumber('123ABC7')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setProNumber('123ABC7')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.ProNumber'; + $this->assertArrayHasKey($op, $o); + $this->assertEquals('123ABC7', $o[$op]); + + //invalid values + $this->assertFalse($this->object->setProNumber('')); + $this->assertFalse($this->object->setProNumber(null)); + $this->assertFalse($this->object->setProNumber(6)); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set PRO number because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testContact($type, $partnered) { + resetLog(); + + //missing partnered and type + $this->assertFalse($this->object->setContact('Bob', '555-1234', 'test@email.com', '555-6789')); + $this->assertNull($this->object->setIsPartnered($partnered)); + //missing shipment type + $this->assertFalse($this->object->setContact('Bob', '555-1234', 'test@email.com', '555-6789')); + $this->assertNull($this->object->setShipmentType($type)); + //good now + $this->assertNull($this->object->setContact('Bob', '555-1234', 'test@email.com', '555-6789')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.Contact'; + $this->assertArrayHasKey($op.'.Name', $o); + $this->assertEquals('Bob', $o[$op.'.Name']); + $this->assertArrayHasKey($op.'.Phone', $o); + $this->assertEquals('555-1234', $o[$op.'.Phone']); + $this->assertArrayHasKey($op.'.Email', $o); + $this->assertEquals('test@email.com', $o[$op.'.Email']); + $this->assertArrayHasKey($op.'.Fax', $o); + $this->assertEquals('555-6789', $o[$op.'.Fax']); + + //invalid values + $this->assertFalse($this->object->setContact(false, '555-1234', 'test@email.com', '555-6789')); + $this->assertFalse($this->object->setContact('Bob', false, 'test@email.com', '555-6789')); + $this->assertFalse($this->object->setContact('Bob', '555-1234', false, '555-6789')); + $this->assertFalse($this->object->setContact('Bob', '555-1234', 'test@email.com', false)); + $this->assertFalse($this->object->setContact(array(), '555-1234', 'test@email.com', '555-6789')); + $this->assertFalse($this->object->setContact('Bob', array(), 'test@email.com', '555-6789')); + $this->assertFalse($this->object->setContact('Bob', '555-1234', array(), '555-6789')); + $this->assertFalse($this->object->setContact('Bob', '555-1234', 'test@email.com', array())); + $this->assertFalse($this->object->setContact(5, '555-1234', 'test@email.com', '555-6789')); + $this->assertFalse($this->object->setContact('Bob', 5.2, 'test@email.com', '555-6789')); + $this->assertFalse($this->object->setContact('Bob', '555-1234', 5, '555-6789')); + $this->assertFalse($this->object->setContact('Bob', '555-1234', 'test@email.com', 5.2)); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set contact info because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetBoxCount($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setBoxCount('12')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setBoxCount('12')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setBoxCount('12')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.BoxCount'; + $this->assertArrayHasKey($op, $o); + $this->assertEquals('12', $o[$op]); + + //invalid values + $this->assertFalse($this->object->setBoxCount(0)); + $this->assertFalse($this->object->setBoxCount('0')); + $this->assertFalse($this->object->setBoxCount('-3')); + $this->assertFalse($this->object->setBoxCount(null)); + $this->assertFalse($this->object->setBoxCount('banana')); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set box count because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetFreightClass($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setFreightClass('12')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setFreightClass('12')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setFreightClass('12')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.SellerFreightClass'; + $this->assertArrayHasKey($op, $o); + $this->assertEquals('12', $o[$op]); + + //invalid values + $this->assertFalse($this->object->setFreightClass(0)); + $this->assertFalse($this->object->setFreightClass(null)); + $this->assertFalse($this->object->setFreightClass('banana')); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set freight class because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetReadyDate($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setReadyDate('+50 min')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setReadyDate('+50 min')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setReadyDate('+50 min')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.FreightReadyDate'; + $this->assertArrayHasKey($op, $o); + $this->assertRegExp('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $o[$op]); + + //invalid values + $this->assertFalse($this->object->setReadyDate(array(5))); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set ready date because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + $this->assertEquals('Error: Invalid time input given', $check[4]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetPallets($type, $partnered) { + $op = $this->findOp($type, $partnered); + resetLog(); + + $data1 = array( + array( + 'Length' => '6', + 'Width' => '7', + 'Height' => '8', + 'Weight' => '9.8', + ), + array( + 'Length' => '6', + 'Width' => '7', + 'IsStacked' => true, + ), + array( + 'IsStacked' => false, + ), + ); + + $this->assertFalse($this->object->setPallets($data1)); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setPallets($data1)); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setPallets($data1)); + $o = $this->object->getOptions(); + //package 1/3 + $this->assertArrayHasKey($op.'.PalletList.member.1.Dimensions.Length', $o); + $this->assertEquals('6', $o[$op.'.PalletList.member.1.Dimensions.Length']); + $this->assertArrayHasKey($op.'.PalletList.member.1.Dimensions.Width', $o); + $this->assertEquals('7', $o[$op.'.PalletList.member.1.Dimensions.Width']); + $this->assertArrayHasKey($op.'.PalletList.member.1.Dimensions.Height', $o); + $this->assertEquals('8', $o[$op.'.PalletList.member.1.Dimensions.Height']); + $this->assertArrayHasKey($op.'.PalletList.member.1.Dimensions.Unit', $o); + $this->assertEquals('centimeters', $o[$op.'.PalletList.member.1.Dimensions.Unit']); + $this->assertArrayHasKey($op.'.PalletList.member.1.Weight.Value', $o); + $this->assertEquals('9.8', $o[$op.'.PalletList.member.1.Weight.Value']); + $this->assertArrayHasKey($op.'.PalletList.member.1.Weight.Unit', $o); + $this->assertEquals('kilograms', $o[$op.'.PalletList.member.1.Weight.Unit']); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.IsStacked', $o); + //package 2/3 + $this->assertArrayHasKey($op.'.PalletList.member.2.IsStacked', $o); + $this->assertEquals('true', $o[$op.'.PalletList.member.2.IsStacked']); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.Dimensions.Length', $o); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.Dimensions.Width', $o); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.Dimensions.Height', $o); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.Dimensions.Unit', $o); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.Weight.Value', $o); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.Weight.Unit', $o); + //package 3/3 + $this->assertArrayHasKey($op.'.PalletList.member.3.IsStacked', $o); + $this->assertEquals('false', $o[$op.'.PalletList.member.3.IsStacked']); + + //setting again will cause a reset + $data2 = array( + array( + 'IsStacked' => 0, + ), + array( + 'Length' => '10', + 'Width' => '11', + 'Height' => '12', + 'Weight' => '20', + ), + ); + + $this->assertNull($this->object->setPallets($data2, 'inches', 'pounds')); + $o2 = $this->object->getOptions(); + //package 1/2 + $this->assertArrayHasKey($op.'.PalletList.member.1.IsStacked', $o2); + $this->assertEquals('false', $o2[$op.'.PalletList.member.1.IsStacked']); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.Dimensions.Length', $o2); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.Dimensions.Width', $o2); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.Dimensions.Height', $o2); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.Dimensions.Unit', $o2); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.Weight.Value', $o2); + $this->assertArrayNotHasKey($op.'.PalletList.member.1.Weight.Unit', $o2); + //package 2/2 + $this->assertArrayHasKey($op.'.PalletList.member.2.Dimensions.Length', $o2); + $this->assertEquals('10', $o2[$op.'.PalletList.member.2.Dimensions.Length']); + $this->assertArrayHasKey($op.'.PalletList.member.2.Dimensions.Width', $o2); + $this->assertEquals('11', $o2[$op.'.PalletList.member.2.Dimensions.Width']); + $this->assertArrayHasKey($op.'.PalletList.member.2.Dimensions.Height', $o2); + $this->assertEquals('12', $o2[$op.'.PalletList.member.2.Dimensions.Height']); + $this->assertArrayHasKey($op.'.PalletList.member.2.Dimensions.Unit', $o2); + $this->assertEquals('inches', $o2[$op.'.PalletList.member.2.Dimensions.Unit']); + $this->assertArrayHasKey($op.'.PalletList.member.2.Weight.Value', $o2); + $this->assertEquals('20', $o2[$op.'.PalletList.member.2.Weight.Value']); + $this->assertArrayHasKey($op.'.PalletList.member.2.Weight.Unit', $o2); + $this->assertEquals('pounds', $o2[$op.'.PalletList.member.2.Weight.Unit']); + $this->assertArrayNotHasKey($op.'.PalletList.member.2.IsStacked', $o2); + //no package 3 + $this->assertArrayNotHasKey($op.'.PalletList.member.3.IsStacked', $o2); + + + //invalid values + $this->assertFalse($this->object->setPallets(array('banana'))); + $this->assertFalse($this->object->setPallets(array())); + $this->assertFalse($this->object->setPallets('banana')); + $this->assertFalse($this->object->setPallets(6)); + $this->assertFalse($this->object->setPallets(null)); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set pallets because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + $this->assertEquals('Tried to set pallets with invalid array', $check[4]); + $this->assertEquals('Tried to set pallet list to invalid values', $check[5]); + $this->assertEquals($check[5], $check[6]); + $this->assertEquals($check[5], $check[7]); + $this->assertEquals($check[5], $check[8]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetTotalWeight($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setTotalWeight('123')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setTotalWeight('123')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setTotalWeight('123')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.TotalWeight'; + $this->assertArrayHasKey($op.'.Value', $o); + $this->assertEquals('123', $o[$op.'.Value']); + $this->assertArrayHasKey($op.'.Unit', $o); + $this->assertEquals('kilograms', $o[$op.'.Unit']); + + //invalid values + $this->assertFalse($this->object->setTotalWeight(null)); + $this->assertFalse($this->object->setTotalWeight('banana')); + $this->assertFalse($this->object->setTotalWeight('')); + $this->assertFalse($this->object->setTotalWeight(0)); + $this->assertFalse($this->object->setTotalWeight(6, 'bad unit')); + $this->assertFalse($this->object->setTotalWeight(6, '')); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set total weight because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + /** + * @param string $type "SP" or "LTL" + * @param boolean $partnered partnered or not + * @dataProvider comboProvider + */ + public function testSetDeclaredValue($type, $partnered) { + resetLog(); + + $this->assertFalse($this->object->setDeclaredValue('1.23', 'USD')); //missing partnered and type + $this->assertNull($this->object->setIsPartnered($partnered)); + $this->assertFalse($this->object->setDeclaredValue('1.23', 'USD')); //missing shipment type + $this->assertNull($this->object->setShipmentType($type)); + $this->assertNull($this->object->setDeclaredValue('1.23', 'USD')); + $o = $this->object->getOptions(); + $op = $this->findOp($type, $partnered).'.SellerDeclaredValue'; + $this->assertArrayHasKey($op.'.Value', $o); + $this->assertEquals('1.23', $o[$op.'.Value']); + $this->assertArrayHasKey($op.'.CurrencyCode', $o); + $this->assertEquals('USD', $o[$op.'.CurrencyCode']); + + //invalid values + $this->assertFalse($this->object->setDeclaredValue(null, 'USD')); + $this->assertFalse($this->object->setDeclaredValue('banana', 'USD')); + $this->assertFalse($this->object->setDeclaredValue('', 'USD')); + $this->assertFalse($this->object->setDeclaredValue(0, 'USD')); + $this->assertFalse($this->object->setDeclaredValue(6, 6)); + $this->assertFalse($this->object->setDeclaredValue(6, '')); + + $check = parseLog(); + $this->assertEquals($this->getOpError(), $check[0]); + $this->assertEquals('Cannot set declared value because of the shipment type and partnered parameters.', $check[1]); + $this->assertEquals($check[0], $check[2]); + $this->assertEquals($check[1], $check[3]); + } + + public function testSendTransportContentsWithPartneredSp() { + resetLog(); + $this->object->setMock(true, 'sendTransportContents.xml'); + + $this->assertFalse($this->object->sendTransportContents()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertFalse($this->object->sendTransportContents()); //no partnered status yet + $this->assertNull($this->object->setIsPartnered(true)); + $this->assertFalse($this->object->sendTransportContents()); //no shipment type yet + $this->assertNull($this->object->setShipmentType('SP')); + $this->assertFalse($this->object->sendTransportContents()); //no packages yet + $packages = array(array( + 'Length' => '5', + 'Width' => '6', + 'Height' => '7', + 'Weight' => '8', + )); + $this->assertNull($this->object->setPackages($packages)); + //all good now + $this->assertNull($this->object->sendTransportContents()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('WORKING', $this->object->getStatus()); + + $check = parseLog(); + $m = ' must be set in order to send transport content!'; + $this->assertEquals('Single Mock File set: sendTransportContents.xml', $check[1]); + $this->assertEquals('Shipment ID'.$m, $check[2]); + $this->assertEquals('IsPartnered'.$m, $check[3]); + $this->assertEquals('Shipment type'.$m, $check[4]); + $this->assertEquals('Packages'.$m, $check[5]); + $this->assertEquals('Fetched Mock File: mock/sendTransportContents.xml', $check[6]); + } + + public function testSendTransportContentsWithNonPartneredSp() { + resetLog(); + $this->object->setMock(true, 'sendTransportContents.xml'); + + $this->assertFalse($this->object->sendTransportContents()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertFalse($this->object->sendTransportContents()); //no partnered status yet + $this->assertNull($this->object->setIsPartnered(false)); + $this->assertFalse($this->object->sendTransportContents()); //no shipment type yet + $this->assertNull($this->object->setShipmentType('SP')); + $this->assertFalse($this->object->sendTransportContents()); //no carrier yet + $this->assertNull($this->object->setCarrier('truck')); + $this->assertFalse($this->object->sendTransportContents()); //no packages yet + $packages = array(array( + 'Length' => '5', + 'Width' => '6', + 'Height' => '7', + 'Weight' => '8', + )); + $this->assertNull($this->object->setPackages($packages)); + //all good now + $this->assertNull($this->object->sendTransportContents()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('WORKING', $this->object->getStatus()); + + $check = parseLog(); + $m = ' must be set in order to send transport content!'; + $this->assertEquals('Single Mock File set: sendTransportContents.xml', $check[1]); + $this->assertEquals('Shipment ID'.$m, $check[2]); + $this->assertEquals('IsPartnered'.$m, $check[3]); + $this->assertEquals('Shipment type'.$m, $check[4]); + $this->assertEquals('Carrier'.$m, $check[5]); + $this->assertEquals('Packages'.$m, $check[6]); + $this->assertEquals('Fetched Mock File: mock/sendTransportContents.xml', $check[7]); + } + + public function testSendTransportContentsWithPartneredLtl() { + resetLog(); + $this->object->setMock(true, 'sendTransportContents.xml'); + + $this->assertFalse($this->object->sendTransportContents()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertFalse($this->object->sendTransportContents()); //no partnered status yet + $this->assertNull($this->object->setIsPartnered(true)); + $this->assertFalse($this->object->sendTransportContents()); //no shipment type yet + $this->assertNull($this->object->setShipmentType('LTL')); + $this->assertFalse($this->object->sendTransportContents()); //no contact + $this->assertNull($this->object->setContact('Bob', '555-1234', 'test@email.com', '555-6789')); + $this->assertFalse($this->object->sendTransportContents()); //no box count yet + $this->assertNull($this->object->setBoxCount(3)); + $this->assertFalse($this->object->sendTransportContents()); //no ready date yet + $this->assertNull($this->object->setReadyDate('+3 days')); + //all good now + $this->assertNull($this->object->sendTransportContents()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('WORKING', $this->object->getStatus()); + + $check = parseLog(); + $m = ' must be set in order to send transport content!'; + $this->assertEquals('Single Mock File set: sendTransportContents.xml', $check[1]); + $this->assertEquals('Shipment ID'.$m, $check[2]); + $this->assertEquals('IsPartnered'.$m, $check[3]); + $this->assertEquals('Shipment type'.$m, $check[4]); + $this->assertEquals('Contact info'.$m, $check[5]); + $this->assertEquals('Box count'.$m, $check[6]); + $this->assertEquals('Ready date'.$m, $check[7]); + $this->assertEquals('Fetched Mock File: mock/sendTransportContents.xml', $check[8]); + } + + public function testSendTransportContentsWithNonPartneredLtl() { + resetLog(); + $this->object->setMock(true, 'sendTransportContents.xml'); + + $this->assertFalse($this->object->sendTransportContents()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertFalse($this->object->sendTransportContents()); //no partnered status yet + $this->assertNull($this->object->setIsPartnered(false)); + $this->assertFalse($this->object->sendTransportContents()); //no shipment type yet + $this->assertNull($this->object->setShipmentType('LTL')); + $this->assertFalse($this->object->sendTransportContents()); //no carrier yet + $this->assertNull($this->object->setCarrier('truck')); + $this->assertFalse($this->object->sendTransportContents()); //no PRO number + $this->assertNull($this->object->setProNumber('123ABC7')); + //all good now + $this->assertNull($this->object->sendTransportContents()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('WORKING', $this->object->getStatus()); + + $check = parseLog(); + $m = ' must be set in order to send transport content!'; + $this->assertEquals('Single Mock File set: sendTransportContents.xml', $check[1]); + $this->assertEquals('Shipment ID'.$m, $check[2]); + $this->assertEquals('IsPartnered'.$m, $check[3]); + $this->assertEquals('Shipment type'.$m, $check[4]); + $this->assertEquals('Carrier'.$m, $check[5]); + $this->assertEquals('PRO number'.$m, $check[6]); + $this->assertEquals('Fetched Mock File: mock/sendTransportContents.xml', $check[7]); + } + + public function testEstimateTransport() { + resetLog(); + $this->object->setMock(true, 'estimateTransport.xml'); + + $this->assertFalse($this->object->estimateTransport()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->estimateTransport()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('ESTIMATING', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: estimateTransport.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to estimate the transport request!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/estimateTransport.xml', $check[3]); + } + + public function testConfirmTransport() { + resetLog(); + $this->object->setMock(true, 'confirmTransport.xml'); + + $this->assertFalse($this->object->confirmTransport()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->confirmTransport()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('CONFIRMING', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: confirmTransport.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to confirm the transport request!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/confirmTransport.xml', $check[3]); + } + + public function testVoidTransport() { + resetLog(); + $this->object->setMock(true, 'voidTransport.xml'); + + $this->assertFalse($this->object->voidTransport()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->voidTransport()); + + $this->assertFalse($this->object->getContentDetails()); + $this->assertEquals('VOIDING', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: voidTransport.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to void the transport request!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/voidTransport.xml', $check[3]); + } + + public function testFetchTransportSpPartnered() { + resetLog(); + $this->object->setMock(true, 'fetchTransportContentSpPartnered.xml'); + + $this->assertFalse($this->object->fetchTransportContent()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->fetchTransportContent()); + $this->assertEquals('CONFIRMED', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchTransportContentSpPartnered.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to get transport contents!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/fetchTransportContentSpPartnered.xml', $check[3]); + + return $this->object; + } + + public function testFetchTransportSpNonPartnered() { + resetLog(); + $this->object->setMock(true, 'fetchTransportContentSpNonPartnered.xml'); + + $this->assertFalse($this->object->fetchTransportContent()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->fetchTransportContent()); + $this->assertEquals('ESTIMATED', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchTransportContentSpNonPartnered.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to get transport contents!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/fetchTransportContentSpNonPartnered.xml', $check[3]); + + return $this->object; + } + + public function testFetchTransportLtlPartnered() { + resetLog(); + $this->object->setMock(true, 'fetchTransportContentLtlPartnered.xml'); + + $this->assertFalse($this->object->fetchTransportContent()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->fetchTransportContent()); + $this->assertEquals('ERROR_ON_ESTIMATING', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchTransportContentLtlPartnered.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to get transport contents!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/fetchTransportContentLtlPartnered.xml', $check[3]); + + return $this->object; + } + + public function testFetchTransportLtlNonPartnered() { + resetLog(); + $this->object->setMock(true, 'fetchTransportContentLtlNonPartnered.xml'); + + $this->assertFalse($this->object->fetchTransportContent()); //no shipment ID yet + $this->assertNull($this->object->setShipmentId('77')); + $this->assertNull($this->object->fetchTransportContent()); + $this->assertEquals('WORKING', $this->object->getStatus()); + + $check = parseLog(); + $this->assertEquals('Single Mock File set: fetchTransportContentLtlNonPartnered.xml', $check[1]); + $this->assertEquals('Shipment ID must be set in order to get transport contents!', $check[2]); + $this->assertEquals('Fetched Mock File: mock/fetchTransportContentLtlNonPartnered.xml', $check[3]); + + return $this->object; + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetContentInfo($psp, $nsp, $pltl, $nltl) { + foreach (array($psp, $nsp, $pltl, $nltl) as $o) { + $info = $o->getContentInfo(); + $this->assertInternalType('array', $info); + $this->assertNotEmpty($info); + $this->assertArrayHasKey('SellerId', $info); + $this->assertEquals($o->getSellerId(), $info['SellerId']); + $this->assertArrayHasKey('ShipmentId', $info); + $this->assertEquals($o->getShipmentId(), $info['ShipmentId']); + $this->assertArrayHasKey('IsPartnered', $info); + $this->assertEquals($o->getIsPartnered(), $info['IsPartnered']); + $this->assertArrayHasKey('ShipmentType', $info); + $this->assertEquals($o->getShipmentType(), $info['ShipmentType']); + $this->assertArrayHasKey('Details', $info); + $this->assertEquals($o->getContentDetails(), $info['Details']); + } + + $this->assertFalse($this->object->getContentInfo()); //not fetched yet for this object + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetContentDetails($psp, $nsp, $pltl, $nltl) { + $pspDetails = $psp->getContentDetails(); + $nspDetails = $nsp->getContentDetails(); + $pltlDetails = $pltl->getContentDetails(); + $nltlDetails = $nltl->getContentDetails(); + $this->assertInternalType('array', $pspDetails); + $this->assertInternalType('array', $nspDetails); + $this->assertInternalType('array', $pltlDetails); + $this->assertInternalType('array', $nltlDetails); + $this->assertNotEmpty($pspDetails); + $this->assertNotEmpty($nspDetails); + $this->assertNotEmpty($pltlDetails); + $this->assertNotEmpty($nltlDetails); + + //partnered SP + $this->assertArrayHasKey('PartneredEstimate', $pspDetails); + $this->assertEquals($psp->getPartneredEstimate(), $pspDetails['PartneredEstimate']); + $this->assertArrayHasKey('PackageList', $pspDetails); + $this->assertEquals($psp->getPackageList(), $pspDetails['PackageList']); + + //non-partnered SP + $this->assertArrayHasKey('PackageList', $nspDetails); + $this->assertEquals($nsp->getPackageList(), $nspDetails['PackageList']); + + //partnered LTL + $this->assertArrayHasKey('Contact', $pltlDetails); + $this->assertEquals($pltl->getContact(), $pltlDetails['Contact']); + $this->assertArrayHasKey('BoxCount', $pltlDetails); + $this->assertEquals($pltl->getBoxCount(), $pltlDetails['BoxCount']); + $this->assertArrayHasKey('SellerFreightClass', $pltlDetails); + $this->assertEquals('55', $pltlDetails['SellerFreightClass']); + $this->assertArrayHasKey('PreviewFreightClass', $pltlDetails); + $this->assertEquals($pltl->getFreightClass(), $pltlDetails['PreviewFreightClass']); + $this->assertArrayHasKey('FreightReadyDate', $pltlDetails); + $this->assertEquals($pltl->getReadyDate(), $pltlDetails['FreightReadyDate']); + $this->assertArrayHasKey('PalletList', $pltlDetails); + $this->assertEquals($pltl->getPalletList(), $pltlDetails['PalletList']); + $this->assertArrayHasKey('TotalWeight', $pltlDetails); + $this->assertEquals($pltl->getTotalWeight(), $pltlDetails['TotalWeight']); + $this->assertArrayHasKey('SellerDeclaredValue', $pltlDetails); + $this->assertEquals($pltl->getDeclaredValue(), $pltlDetails['SellerDeclaredValue']); + $this->assertArrayHasKey('AmazonCalculatedValue', $pltlDetails); + $this->assertEquals($pltl->getCalculatedValue(), $pltlDetails['AmazonCalculatedValue']); + $this->assertArrayHasKey('PreviewPickupDate', $pltlDetails); + $this->assertEquals($pltl->getPickupDate(), $pltlDetails['PreviewPickupDate']); + $this->assertArrayHasKey('PreviewDeliveryDate', $pltlDetails); + $this->assertEquals($pltl->getDeliveryDate(), $pltlDetails['PreviewDeliveryDate']); + $this->assertArrayHasKey('AmazonReferenceId', $pltlDetails); + $this->assertEquals($pltl->getReferenceId(), $pltlDetails['AmazonReferenceId']); + $this->assertArrayHasKey('IsBillOfLadingAvailable', $pltlDetails); + $this->assertEquals($pltl->getIsBillOfLadingAvailable(), $pltlDetails['IsBillOfLadingAvailable']); + $this->assertArrayHasKey('CarrierName', $pltlDetails); + $this->assertEquals($pltl->getCarrier(), $pltlDetails['CarrierName']); + + //non-partnered LTL + $this->assertArrayHasKey('CarrierName', $nltlDetails); + $this->assertEquals($nltl->getCarrier(), $nltlDetails['CarrierName']); + $this->assertArrayHasKey('ProNumber', $nltlDetails); + $this->assertEquals($nltl->getProNumber(), $nltlDetails['ProNumber']); + + $this->assertFalse($this->object->getContentDetails()); //not fetched yet for this object + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetSellerId($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('A135KKEKWF1J56', $psp->getSellerId()); + $this->assertEquals('A995KKEKWF1J56', $nsp->getSellerId()); + $this->assertEquals('A123KKEKWF1J56', $pltl->getSellerId()); + $this->assertEquals('A170GGEKWF1J56', $nltl->getSellerId()); + + $this->assertFalse($this->object->getSellerId()); //not fetched yet for this object + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetShipmentId($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('FBAQF72K', $psp->getShipmentId()); + $this->assertEquals('FBAQ6QBP', $nsp->getShipmentId()); + $this->assertEquals('FBAQFCQC', $pltl->getShipmentId()); + $this->assertEquals('FBAQFGQZ', $nltl->getShipmentId()); + + $this->assertFalse($this->object->getShipmentId()); //not fetched yet for this object + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetIsPartnered($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('true', $psp->getIsPartnered()); + $this->assertEquals('false', $nsp->getIsPartnered()); + $this->assertEquals('true', $pltl->getIsPartnered()); + $this->assertEquals('false', $nltl->getIsPartnered()); + + $this->assertFalse($this->object->getIsPartnered()); //not fetched yet for this object + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetShipmentType($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('SP', $psp->getShipmentType()); + $this->assertEquals('SP', $nsp->getShipmentType()); + $this->assertEquals('LTL', $pltl->getShipmentType()); + $this->assertEquals('LTL', $nltl->getShipmentType()); + + $this->assertFalse($this->object->getShipmentType()); //not fetched yet for this object + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetPackageList($psp, $nsp, $pltl, $nltl) { + $plist = $psp->getPackageList(); + $nlist = $nsp->getPackageList(); + $this->assertInternalType('array', $plist); + $this->assertInternalType('array', $nlist); + $this->assertCount(3, $plist); + $this->assertCount(1, $nlist); + + //replicas + $x = array(); + $x[0]['Weight']['Value'] = '5.5'; + $x[0]['Weight']['Unit'] = 'pounds'; + $x[0]['TrackingId'] = '1Z8V016A0377769652'; + $x[0]['CarrierName'] = 'UNITED_PARCEL_SERVICE_INC'; + $x[0]['Dimensions']['Height'] = '15'; + $x[0]['Dimensions']['Width'] = '14'; + $x[0]['Dimensions']['Length'] = '13'; + $x[0]['Dimensions']['Unit'] = 'inches'; + $x[0]['PackageStatus'] = 'SHIPPED'; + $x[1]['Weight']['Value'] = '5.6'; + $x[1]['Weight']['Unit'] = 'pounds'; + $x[1]['TrackingId'] = '1Z8V016A0371928464'; + $x[1]['CarrierName'] = 'UNITED_PARCEL_SERVICE_INC'; + $x[1]['PackageStatus'] = 'SHIPPED'; + $x[2]['Weight']['Value'] = '5.7'; + $x[2]['Weight']['Unit'] = 'pounds'; + $x[2]['TrackingId'] = '1Z8V016A0360430477'; + $x[2]['CarrierName'] = 'UNITED_PARCEL_SERVICE_INC'; + $x[2]['PackageStatus'] = 'SHIPPED'; + $z = array(); + $z[0]['TrackingId'] = '1Z6Y68W00342402864'; + $z[0]['CarrierName'] = 'UNITED_PARCEL_SERVICE_INC'; + $z[0]['PackageStatus'] = 'SHIPPED'; + + $this->assertEquals($x, $plist); + $this->assertEquals($z, $nlist); + + //not set for these objects + $this->assertFalse($pltl->getPackageList()); + $this->assertFalse($nltl->getPackageList()); + $this->assertFalse($this->object->getPackageList()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetPartneredEstimate($psp, $nsp, $pltl, $nltl) { + $list = $psp->getPartneredEstimate(); + $this->assertInternalType('array', $list); + + //replica + $x = array(); + $x['Amount']['Value'] = '38.22'; + $x['Amount']['CurrencyCode'] = 'USD'; + $x['ConfirmDeadline'] = '2013-08-09T00:25:05.650Z'; + $x['VoidDeadline'] = '2013-08-10T00:25:05.650Z'; + + $this->assertEquals($x, $list); + + //not set for these objects + $this->assertFalse($nsp->getPartneredEstimate()); + $this->assertFalse($pltl->getPartneredEstimate()); + $this->assertFalse($nltl->getPartneredEstimate()); + $this->assertFalse($this->object->getPartneredEstimate()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetCarrier($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('ABF FREIGHT SYSTEM INC', $pltl->getCarrier()); + $this->assertEquals('ABF FREIGHT SYSTEM INC', $nltl->getCarrier()); + + //not set for these objects + $this->assertFalse($psp->getCarrier()); + $this->assertFalse($nsp->getCarrier()); + $this->assertFalse($this->object->getCarrier()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetProNumber($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('123456', $nltl->getProNumber()); + + //not set for these objects + $this->assertFalse($psp->getProNumber()); + $this->assertFalse($nsp->getProNumber()); + $this->assertFalse($pltl->getProNumber()); + $this->assertFalse($this->object->getProNumber()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetContact($psp, $nsp, $pltl, $nltl) { + $list = $pltl->getContact(); + $this->assertInternalType('array', $list); + + //replicas + $x = array(); + $x['Name'] = 'Bob'; + $x['Phone'] = '555-1234'; + $x['Email'] = 'test@email.com'; + $x['Fax'] = '555-6789'; + + $this->assertEquals($x, $list); + + //not set for these objects + $this->assertFalse($psp->getContact()); + $this->assertFalse($nsp->getContact()); + $this->assertFalse($nltl->getContact()); + $this->assertFalse($this->object->getContact()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetBoxCount($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('12', $pltl->getBoxCount()); + + //not set for these objects + $this->assertFalse($psp->getBoxCount()); + $this->assertFalse($nsp->getBoxCount()); + $this->assertFalse($nltl->getBoxCount()); + $this->assertFalse($this->object->getBoxCount()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetFreightClass($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('50', $pltl->getFreightClass()); + + //not set for these objects + $this->assertFalse($psp->getFreightClass()); + $this->assertFalse($nsp->getFreightClass()); + $this->assertFalse($nltl->getFreightClass()); + $this->assertFalse($this->object->getFreightClass()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetReadyDate($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('2012-12-21', $pltl->getReadyDate()); + + //not set for these objects + $this->assertFalse($psp->getReadyDate()); + $this->assertFalse($nsp->getReadyDate()); + $this->assertFalse($nltl->getReadyDate()); + $this->assertFalse($this->object->getReadyDate()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetPalletList($psp, $nsp, $pltl, $nltl) { + $list = $pltl->getPalletList(); + $this->assertInternalType('array', $list); + $this->assertCount(2, $list); + + //replica + $x = array(); + $x[0]['IsStacked'] = 'true'; + $x[0]['Weight']['Value'] = '500'; + $x[0]['Weight']['Unit'] = 'pounds'; + $x[0]['Dimensions']['Length'] = '40'; + $x[0]['Dimensions']['Width'] = '30'; + $x[0]['Dimensions']['Height'] = '25'; + $x[0]['Dimensions']['Unit'] = 'inches'; + $x[1]['IsStacked'] = 'false'; + $x[1]['Dimensions']['Length'] = '15'; + $x[1]['Dimensions']['Width'] = '12'; + $x[1]['Dimensions']['Height'] = '10'; + $x[1]['Dimensions']['Unit'] = 'inches'; + + $this->assertEquals($x, $list); + + //not set for these objects + $this->assertFalse($psp->getPalletList()); + $this->assertFalse($nsp->getPalletList()); + $this->assertFalse($nltl->getPalletList()); + $this->assertFalse($this->object->getPalletList()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetTotalWeight($psp, $nsp, $pltl, $nltl) { + $weight = $pltl->getTotalWeight(); + $this->assertInternalType('array', $weight); + + //replica + $x = array(); + $x['Value'] = '2000'; + $x['Unit'] = 'pounds'; + + $this->assertEquals($x, $weight); + $this->assertEquals($x['Value'], $pltl->getTotalWeight(true)); + + //not set for these objects + $this->assertFalse($psp->getTotalWeight()); + $this->assertFalse($nsp->getTotalWeight()); + $this->assertFalse($nltl->getTotalWeight()); + $this->assertFalse($this->object->getTotalWeight()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetDeclaredValue($psp, $nsp, $pltl, $nltl) { + $amount = $pltl->getDeclaredValue(); + $this->assertInternalType('array', $amount); + + //replica + $x = array(); + $x['Value'] = '200'; + $x['CurrencyCode'] = 'USD'; + + $this->assertEquals($x, $amount); + $this->assertEquals($x['Value'], $pltl->getDeclaredValue(true)); + + //not set for these objects + $this->assertFalse($psp->getDeclaredValue()); + $this->assertFalse($nsp->getDeclaredValue()); + $this->assertFalse($nltl->getDeclaredValue()); + $this->assertFalse($this->object->getDeclaredValue()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetCalculatedValue($psp, $nsp, $pltl, $nltl) { + $amount = $pltl->getCalculatedValue(); + $this->assertInternalType('array', $amount); + + //replica + $x = array(); + $x['Value'] = '40'; + $x['CurrencyCode'] = 'USD'; + + $this->assertEquals($x, $amount); + $this->assertEquals($x['Value'], $pltl->getCalculatedValue(true)); + + //not set for these objects + $this->assertFalse($psp->getCalculatedValue()); + $this->assertFalse($nsp->getCalculatedValue()); + $this->assertFalse($nltl->getCalculatedValue()); + $this->assertFalse($this->object->getCalculatedValue()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetPickupDate($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('2013-08-10T00:25:05.650Z', $pltl->getPickupDate()); + + //not set for these objects + $this->assertFalse($psp->getPickupDate()); + $this->assertFalse($nsp->getPickupDate()); + $this->assertFalse($nltl->getPickupDate()); + $this->assertFalse($this->object->getPickupDate()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetDeliveryDate($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('2013-08-15T00:25:05.650Z', $pltl->getDeliveryDate()); + + //not set for these objects + $this->assertFalse($psp->getDeliveryDate()); + $this->assertFalse($nsp->getDeliveryDate()); + $this->assertFalse($nltl->getDeliveryDate()); + $this->assertFalse($this->object->getDeliveryDate()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetReferenceId($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('123ABC789', $pltl->getReferenceId()); + + //not set for these objects + $this->assertFalse($psp->getReferenceId()); + $this->assertFalse($nsp->getReferenceId()); + $this->assertFalse($nltl->getReferenceId()); + $this->assertFalse($this->object->getReferenceId()); + } + + /** + * @depends testFetchTransportSpPartnered + * @depends testFetchTransportSpNonPartnered + * @depends testFetchTransportLtlPartnered + * @depends testFetchTransportLtlNonPartnered + * @param AmazonTransport $psp partnered SP + * @param AmazonTransport $nsp non-partnered SP + * @param AmazonTransport $pltl partnered LTL + * @param AmazonTransport $nltl non-partnered LTL + */ + public function testGetIsBillOfLadingAvailable($psp, $nsp, $pltl, $nltl) { + $this->assertEquals('false', $pltl->getIsBillOfLadingAvailable()); + + //not set for these objects + $this->assertFalse($psp->getIsBillOfLadingAvailable()); + $this->assertFalse($nsp->getIsBillOfLadingAvailable()); + $this->assertFalse($nltl->getIsBillOfLadingAvailable()); + $this->assertFalse($this->object->getIsBillOfLadingAvailable()); + } + + /** + * Simplified copy of method determineDetailOption in class + * @param string $tshipment type ("SP" or "LTL")
+ * @param boolean $ppartnered or not
+ * @return string|boolean parameter prefix or FALSE if it could not be determined + */ + private function findOp($t, $p) { + if (!isset($p) || !isset($t)) { + return false; + } + $op = 'TransportDetails.'; + if ($t == 'SP') { + if ($p) { + return $op . 'PartneredSmallParcelData'; + } else { + return $op . 'NonPartneredSmallParcelData'; + } + } else if ($t == 'LTL') { + if ($p) { + return $op . 'PartneredLtlData'; + } else { + return $op . 'NonPartneredLtlData'; + } + } + return false; + } + + /** + * Gives the error message that appears for all parameters that rely on carrier type and partnered. + * @return string + */ + private function getOpError() { + return 'Cannot set transport details without shipment type and partner parameters!'; + } + +} + +require_once('helperFunctions.php'); diff --git a/test-cases/mock/confirmPreorder.xml b/test-cases/mock/confirmPreorder.xml new file mode 100644 index 00000000..4ed12774 --- /dev/null +++ b/test-cases/mock/confirmPreorder.xml @@ -0,0 +1,10 @@ + +