diff --git a/.gitignore b/.gitignore index dd55f33..5c371a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ composer.phar /vendor/ +/.idea # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file diff --git a/README.md b/README.md index 9c5cfa3..3157cb8 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ Implementation based on [Webflow CMS API Reference](https://developers.webflow.c - Patch Collection Item - Remove Collection Item +## Version 2 + +This package is now using Version 2 of the Webflow Api. + ## Usage Check https://university.webflow.com/article/using-the-webflow-cms-api on how to generate `YOUR_WEBFLOW_API_TOKEN` @@ -68,6 +72,24 @@ $webflow->updateItem($collectionId, $itemId, $fields); $webflow->removeItem($collectionId, $itemId); ``` +## Publising + +### Publishing Items +Publishing an item or items can be done instead of publishing the entire site. +```php +$webflow->publishItem($collectionId, $itemIds); +``` + +### Publishing a Site + +```php +$domains = [$domainID]; +// if you wish to publish to your mydomain.webflow.io subdomain you should specify +// true. If true $domains **must** be an empty array +$publishWebflowSubdomain = true; +$webflow->publishSite($siteId,$domains, $publishWebflowSubdomain) +``` +**nb:** Webflow has very strict limits on publishing your site. Currently 1 per minute. ## Installation diff --git a/src/Webflow/Api.php b/src/Webflow/Api.php index b9d8e78..e2296dc 100644 --- a/src/Webflow/Api.php +++ b/src/Webflow/Api.php @@ -6,7 +6,10 @@ class Api { - const WEBFLOW_API_ENDPOINT = 'https://api.webflow.com'; + // changed api endpoints + // https://docs.developers.webflow.com/data/changelog/webflow-api-changed-endpoints + // https://docs.developers.webflow.com/data/reference/ + const WEBFLOW_API_ENDPOINT = 'https://api.webflow.com/v2'; const WEBFLOW_API_USERAGENT = 'Expertlead Webflow PHP SDK (https://github.com/expertlead/webflow-php-sdk)'; private $client; @@ -20,7 +23,7 @@ class Api public function __construct( $token, - $version = '1.0.0' + $version = '2.0.0' ) { if (empty($token)) { throw new WebflowException('token'); @@ -34,7 +37,7 @@ public function __construct( return $this; } - private function request(string $path, string $method, array $data = []) + private function request(string $path, string $method, $data = []) { $curl = curl_init(); $options = [ @@ -52,6 +55,7 @@ private function request(string $path, string $method, array $data = []) ]; if (!empty($data)) { $json = json_encode($data); + $options[CURLOPT_POSTFIELDS] = $json; $options[CURLOPT_HTTPHEADER][] = "Content-Length: " . strlen($json); } @@ -59,6 +63,7 @@ private function request(string $path, string $method, array $data = []) $response = curl_exec($curl); curl_close($curl); list($headers, $body) = explode("\r\n\r\n", $response, 2); + return $this->parse($body); } private function get($path) @@ -76,6 +81,12 @@ private function put($path, $data) return $this->request($path, "PUT", $data); } + + private function patch($path, $data) + { + return $this->request($path, "PATCH", $data); + } + private function delete($path) { return $this->request($path, "DELETE"); @@ -84,12 +95,12 @@ private function delete($path) private function parse($response) { $json = json_decode($response); - if (isset($json->code) && isset($json->msg)) { - $error = $json->msg; - if (isset($json->problems)) { - $error .= PHP_EOL . implode(PHP_EOL, $json->problems); + if (isset($json->code) && isset($json->message)) { + $error = $json->message; + if (isset($json->details)) { + $error .= PHP_EOL . $json->code . ': ' . implode(PHP_EOL, $json->details) ; } - throw new \Exception($error, $json->code); + throw new \Exception($error); } return $json; } @@ -115,9 +126,40 @@ public function domains(string $siteId) return $this->get("/sites/{$siteId}/domains"); } - public function publishSite(string $siteId, array $domains) + /** + * Publish site must take an array list of customdomains to be published to + * and a boolean indicating if your webflow.io subdomain should be published to + * @param string $siteId + * @param array $domains + * @param $publishWebflowSubdomain + * @return mixed + */ + public function publishSite(string $siteId, array $domains, $publishWebflowSubdomain = false) { - return $this->post("/sites/${siteId}/publish", $domains); + // if domains empty array then + if (!$domains){ + $data = []; + } else { + $data = ['customDomains' => $domains]; + } + + + $data['publishToWebflowSubdomain'] = $publishWebflowSubdomain; + + return $this->post("/sites/${siteId}/publish", $data); + } + + /** + * Publish just the items specified, rather than the entire site + * @param string $collection_id + * @param array $itemIds + * @return mixed + */ + public function publishItem(string $collection_id, array $itemIds) + { + return $this->post("/collections/{$collection_id}/items/publish", [ + 'itemIds' => $itemIds, + ]); } // Collections @@ -145,11 +187,11 @@ public function itemsAll(string $collectionId): array { $response = $this->items($collectionId); $items = $response->items; - $limit = $response->limit; - $total = $response->total; + $limit = $response->pagination->limit; + $total = $response->pagination->total; $pages = ceil($total / $limit); for ($page = 1; $page < $pages; $page++) { - $offset = $response->limit * $page; + $offset = $response->pagination->limit * $page; $items = array_merge($items, $this->items($collectionId, $offset, $limit)->items); } return $items; @@ -160,23 +202,39 @@ public function item(string $collectionId, string $itemId) return $this->get("/collections/{$collectionId}/items/{$itemId}"); } - public function createItem(string $collectionId, array $fields, bool $live = false) + public function createItem(string $collectionId, $fields, bool $live = false) { $defaults = [ - "_archived" => false, - "_draft" => false, + "isArchived" => false, + "isDraft" => false, ]; + $data = (object) [ + 'fieldData' => [], + ]; + // must be an object property + $data->fieldData = $fields; + return $this->post("/collections/{$collectionId}/items" . ($live ? "?live=true" : ""), + $data + ); - return $this->post("/collections/{$collectionId}/items" . ($live ? "?live=true" : ""), [ - 'fields' => array_merge($defaults, $fields), - ]); } + /** + * Version 2 update item patches the item so you do not need to provide all details. + * @param string $collectionId + * @param string $itemId + * @param array $fields + * @param bool $live + * @return mixed + */ public function updateItem(string $collectionId, string $itemId, array $fields, bool $live = false) { - return $this->put("/collections/{$collectionId}/items/{$itemId}" . ($live ? "?live=true" : ""), [ - 'fields' => $fields, - ]); + $data = (object) [ + 'fieldData' => [], + ]; + // must be an object property + $data->fieldData = $fields; + return $this->patch("/collections/{$collectionId}/items/{$itemId}" . ($live ? "?live=true" : ""), $data); } public function removeItem(string $collectionId, $itemId)