diff --git a/src/AbstractApi.php b/src/AbstractApi.php index 47bd7a2..d36f640 100644 --- a/src/AbstractApi.php +++ b/src/AbstractApi.php @@ -8,7 +8,7 @@ abstract class AbstractApi implements ApiInterface { - const DEFAULT_API_VERSION = '2019-04'; + const DEFAULT_API_VERSION = '2020-07'; /** * Domain of the Shopify store diff --git a/src/Enum/Fields/CollectionListingFields.php b/src/Enum/Fields/CollectionListingFields.php index 5537887..72cf833 100644 --- a/src/Enum/Fields/CollectionListingFields.php +++ b/src/Enum/Fields/CollectionListingFields.php @@ -2,7 +2,7 @@ namespace Shopify\Enum\Fields; -class CollectionListingFields extends AbstractObject +class CollectionListingFields extends AbstractObjectEnum { const COLLECTION_ID = 'collection_id'; const BODY_HTML = 'body_html'; diff --git a/src/Enum/Fields/InventoryItemFields.php b/src/Enum/Fields/InventoryItemFields.php new file mode 100644 index 0000000..2456808 --- /dev/null +++ b/src/Enum/Fields/InventoryItemFields.php @@ -0,0 +1,30 @@ + 'integer', + 'country_code_of_origin' => 'string', + 'country_harmonized_system_codes' => 'array', + 'harmonized_system_code' => 'integer', + 'id' => 'integer', + 'province_code_of_origin' => 'string', + 'sku' => 'string', + 'tracked' => 'boolean', + ); + } +} \ No newline at end of file diff --git a/src/Enum/Fields/InventoryLevelFields.php b/src/Enum/Fields/InventoryLevelFields.php new file mode 100644 index 0000000..79a22db --- /dev/null +++ b/src/Enum/Fields/InventoryLevelFields.php @@ -0,0 +1,23 @@ + 'integer', + 'location_id' => 'integer', + 'available' => 'integer', + 'available_adjustment' => 'integer', + 'disconnect_if_necessary' => 'boolean', + ); + } +} \ No newline at end of file diff --git a/src/Object/AbstractObject.php b/src/Object/AbstractObject.php index 5cf3b79..8e63eae 100644 --- a/src/Object/AbstractObject.php +++ b/src/Object/AbstractObject.php @@ -51,7 +51,7 @@ public function __construct() $this->data = array_fill_keys($enum->getFields(), null); } - public function __get($key) + public function &__get($key) { if (!array_key_exists($key, $this->data)) { throw new \InvalidArgumentException( @@ -61,7 +61,7 @@ public function __get($key) return $this->data[$key]; } - public function __set($key, $value) + public function &__set($key, $value) { if (!array_key_exists($key, $this->data)) { return $this; @@ -73,7 +73,7 @@ public function __set($key, $value) } if (!is_null($value) && !$this->isValidValue($key, $value)) { throw new \InvalidArgumentException( - "Invalid type for property '{$key}'" + "Invalid type for property '{$key}', should be a ".$this->types[$key]." received ".print_r($value,1) ); } $this->data[$key] = $value; diff --git a/src/Object/InventoryItem.php b/src/Object/InventoryItem.php new file mode 100644 index 0000000..49edc07 --- /dev/null +++ b/src/Object/InventoryItem.php @@ -0,0 +1,44 @@ + + * @license MIT + */ + +namespace Shopify\Object; + +use Shopify\Enum\Fields\InventoryItemFields; + +class InventoryItem extends AbstractObject +{ + public static function getFieldsEnum() + { + return InventoryItemFields::getInstance(); + } +} diff --git a/src/Object/InventoryLevel.php b/src/Object/InventoryLevel.php new file mode 100644 index 0000000..840d591 --- /dev/null +++ b/src/Object/InventoryLevel.php @@ -0,0 +1,44 @@ + + * @license MIT + */ + +namespace Shopify\Object; + +use Shopify\Enum\Fields\InventoryLevelFields; + +class InventoryLevel extends AbstractObject +{ + public static function getFieldsEnum() + { + return InventoryLevelFields::getInstance(); + } +} \ No newline at end of file diff --git a/src/Service/AbstractService.php b/src/Service/AbstractService.php index 6efe4e5..6770aad 100644 --- a/src/Service/AbstractService.php +++ b/src/Service/AbstractService.php @@ -2,6 +2,7 @@ namespace Shopify\Service; +use Exception; use GuzzleHttp\Client; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; @@ -21,9 +22,9 @@ abstract class AbstractService */ private $lastResponse; - const REQUEST_METHOD_GET = 'GET'; - const REQUEST_METHOD_POST = 'POST'; - const REQUEST_METHOD_PUT = 'PUT'; + const REQUEST_METHOD_GET = 'GET'; + const REQUEST_METHOD_POST = 'POST'; + const REQUEST_METHOD_PUT = 'PUT'; const REQUEST_METHOD_DELETE = 'DELETE'; public static function factory(ApiInterface $api) @@ -78,17 +79,37 @@ public function getLastResponse() public function send(Request $request, array $params = array()) { - $args = array(); + //Set the empty args array + $args = []; + + //If the method is get we need to send the args as a query other wise the args need to be send as json if ($request->getMethod() === 'GET') { $args['query'] = $params; - } else { - $args['json'] = $params; } + else { + $args['json'] = $params; + } + + //Load the response in a variable $this->lastResponse = $this->client->send($request, $args); - return json_decode( + + //Decode the json string and save to a varibale. + //We do need return this derict so we can check for an json error. + $return = json_decode( $this->lastResponse->getBody()->getContents(), true ); + + //Check if there are any json error. + //if there is an error throw an exeption + //TOD: make costum exeption. + $json_error = json_last_error(); + if($json_error === JSON_ERROR_NONE){ + return $return; + } + else{ + throw new Exception($json_error); + } } public function createObject($className, $data) @@ -106,4 +127,4 @@ function ($object) use ($className) { }, $data ); } -} +} \ No newline at end of file diff --git a/src/Service/CustomCollectionService.php b/src/Service/CustomCollectionService.php index 36580ad..1beaba8 100644 --- a/src/Service/CustomCollectionService.php +++ b/src/Service/CustomCollectionService.php @@ -100,7 +100,7 @@ public function update(CustomCollection &$customCollection) */ public function delete(CustomCollection &$customCollection) { - $endpoint = 'custom_collections/'.$customCollection->getId().'.json'; + $endpoint = 'custom_collections/'.$customCollection->id.'.json'; $this->request($endpoint, static::REQUEST_METHOD_DELETE); return; } diff --git a/src/Service/InventoryItemService.php b/src/Service/InventoryItemService.php new file mode 100644 index 0000000..b24623b --- /dev/null +++ b/src/Service/InventoryItemService.php @@ -0,0 +1,60 @@ +request($endpoint, 'GET', $params); + return $this->createCollection(InventoryItem::class, $response['inventory_item']); + } + + /** + * Retrieves a single inventory item by ID + * + * @link https://shopify.dev/docs/admin-api/rest/reference/inventory/inventoryitem#show-2020-07 + * @param int $inventroyItemId + * @param array $fields + * @return InventoryItem[] + */ + public function get(int $inventroyItemId, array $fields = []){ + $params = []; + if (!empty($fields)) { + $params['fields'] = $fields; + } + $endpoint = 'inventory_items/'.$inventroyItemId.'.json'; + $response = $this->request($endpoint, 'GET', $params); + return $this->createObject(InventoryItem::class, $response['inventory_item']); + } + + /** + * Updates an existing inventory item + * + * @link https://shopify.dev/docs/admin-api/rest/reference/inventory/inventoryitem#update-2020-07 + * @param InventoryItem $inventoryItem + * @return void + */ + public function update(InventoryItem &$inventoryItem){ + $data = $inventoryItem->exportData(); + $endpoint = 'inventory_items/'.$inventoryItem->id.'.json'; + $response = $this->request( + $endpoint, 'PUT', array( + 'inventory_item' => $data + ) + ); + $inventoryItem->setData($response['inventory_item']); + } +} \ No newline at end of file diff --git a/src/Service/InventoryLevelService.php b/src/Service/InventoryLevelService.php new file mode 100644 index 0000000..ae14253 --- /dev/null +++ b/src/Service/InventoryLevelService.php @@ -0,0 +1,120 @@ +request($endpoint); + + return $$this->createCollection(InventoryLevel::class, $response['inventory_levels']); + } + + /** + * Adjusts the inventory level of an inventory item at a single location + * + * @link https://shopify.dev/docs/admin-api/rest/reference/inventory/inventorylevel#adjust-2020-07 + * @param InventoryLevel $inventoryLevel + * @return void + */ + public function adjust(InventoryLevel &$inventoryLevel){ + $data = $inventoryLevel->exportData(); + $endpoint = 'inventory_levels/adjust.json'; + $response = $this->request( + $endpoint, 'POST', $data + ); + $inventoryLevel->setData($response['inventory_level']); + } + + /** + * Deletes an inventory level of an inventory item at a location. + * Deleting an inventory level for an inventory item removes that item from the specified location. + * Every inventory item must have at least one inventory level. + * To move inventory to another location, first connect the inventory item to another location, and then delete the previous inventory level. + * + * @link https://shopify.dev/docs/admin-api/rest/reference/inventory/inventorylevel#destroy-2020-07 + * @param InventoryLevel $inventoryLevel + * @return void + */ + public function delete(InventoryLevel &$inventoryLevel){ + $endpoint = 'inventory_levels.json?inventory_item_id='.$inventoryLevel->inventory_item_id.'&location_id='.$inventoryLevel->location_id; + $this->request($endpoint, 'DELETE'); + return; + } + + /** + * Connects an inventory item to a location by creating an inventory level at that location. + * When connecting inventory items to locations, it's important to understand the rules around fulfillment service locations. + * + * @link https://shopify.dev/docs/admin-api/rest/reference/inventory/inventorylevel#connect-2020-07 + * @param InventoryLevel $inventoryLevel + * @return void + */ + public function connect(InventoryLevel &$inventoryLevel){ + $data = $inventoryLevel->exportData(); + $endpoint = 'inventory_levels/connect.json'; + $response = $this->request( + $endpoint, 'POST', $data + ); + $inventoryLevel->setData($response['inventory_level']); + } + + /** + * Sets the inventory level for an inventory item at a location. + * If the specified location is not connected, it will be automatically connected first. + * When connecting inventory items to locations, it's important to understand the rules around fulfillment service locations. + * + * @link https://shopify.dev/docs/admin-api/rest/reference/inventory/inventorylevel#set-2020-07 + * @param InventoryLevel $inventoryLevel + * @return void + */ + public function set(InventoryLevel &$inventoryLevel){ + $data = $inventoryLevel->exportData(); + $endpoint = 'inventory_levels/set.json'; + $response = $this->request( + $endpoint, 'POST', $data + ); + $inventoryLevel->setData($response['inventory_level']); + } +} \ No newline at end of file