Skip to content

[V2 Api] Basic changes required for api v2 to work #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -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

Expand Down
102 changes: 80 additions & 22 deletions src/Webflow/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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');
Expand All @@ -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 = [
Expand All @@ -52,13 +55,15 @@ 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);
}
curl_setopt_array($curl, $options);
$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)
Expand All @@ -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");
Expand All @@ -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) ;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to ensure that implode(PHP_EOL, $json->details) will work when details has info. I didnt get these errors.

}
throw new \Exception($error, $json->code);
throw new \Exception($error);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new json->code is a string not a number, do we want to pick an error code to return?

}
return $json;
}
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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) [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This little bit of code could probably be a little more compact

'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)
Expand Down