Skip to content

Commit

Permalink
Merge pull request #7 from koalatiapp/site-client
Browse files Browse the repository at this point in the history
feat: add the SiteClient wrapper class
  • Loading branch information
EmilePerron authored Mar 4, 2023
2 parents 02dfb2a + cd4e66a commit b6ed035
Show file tree
Hide file tree
Showing 7 changed files with 611 additions and 4 deletions.
20 changes: 20 additions & 0 deletions .config/rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

use Koalati\Utils\Rector\MaintainSiteClientParityRector;
use Rector\Config\RectorConfig;


return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/../src',
]);

$rectorConfig->rules([
MaintainSiteClientParityRector::class,
]);
$rectorConfig->importNames();
$rectorConfig->importShortClasses(false);
$rectorConfig->indent("\t", 1);
};
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
tests/ export-ignore
tests/ export-ignore
utils/ export-ignore
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,34 @@ For a complete list of available methods, check out the documentation below:

@TODO: Document all available methods and models

### If you interact with a single website...

If you interact with a single Webflow site, you can use the `SiteClient`
instead of the basic `Client` to make your code a bit cleaner.

Both clients offer the exact same feature (`Client` is actually used internally
by the `SiteClient`), but it saves you from having to pass the site ID with
every call.

Here is an example:

```php
<?php

use Koalati\Webflow\Api\SiteClient;

// Fetch your access token
// @TODO: change this to get the token from where you stored it.
$accessToken = getenv("WEBFLOW_API_ACCESS_TOKEN");

// Instanciate the API client
$client = new SiteClient($accessToken, "your-site-id");

$domains = $client->listDomains();
$collections = $client->listCollections();
// etc...
```


## Contributing

Expand Down
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@
"phpunit/phpunit": "^10.0",
"phpmd/phpmd": "^2.13",
"phpstan/phpstan": "^1.9",
"symplify/easy-coding-standard": "^11.2"
"symplify/easy-coding-standard": "^11.2",
"rector/rector": "^0.15.19"
},
"suggest": {
"koalati/oauth2-webflow": "Provides the Webflow OAuth 2.0 service provider for `league/oauth2-client`."
},
"scripts": {
"test": "phpunit -c .config/phpunit.xml",
"check": "composer ecs:fix && composer phpmd && composer phpstan",
"check": "composer rector && composer ecs:fix && composer phpmd && composer phpstan",
"rector": "rector -c .config/rector.php",
"ecs": "ecs --config=.config/ecs.php",
"ecs:fix": "ecs --config=.config/ecs.php --fix",
"phpstan": "phpstan analyse src --level=8",
Expand All @@ -38,7 +40,8 @@
},
"autoload-dev": {
"psr-4": {
"Koalati\\Tests\\Webflow\\": "tests/"
"Koalati\\Tests\\Webflow\\": "tests/",
"Koalati\\Utils\\Rector\\": "utils/rector/src/"
}
}
}
285 changes: 285 additions & 0 deletions src/Api/SiteClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
<?php

declare(strict_types=1);

namespace Koalati\Webflow\Api;

use Koalati\Webflow\Exception\CannotUpdateNonExistingModelException;
use Koalati\Webflow\Exception\CollectionItemDeletionException;
use Koalati\Webflow\Exception\CollectionItemPublishingException;
use Koalati\Webflow\Exception\InvalidUserUpdateException;
use Koalati\Webflow\Model\Cms\Collection;
use Koalati\Webflow\Model\Cms\CollectionItem;
use Koalati\Webflow\Model\Membership\AccessGroup;
use Koalati\Webflow\Model\Membership\User;
use Koalati\Webflow\Model\Meta\Authorization;
use Koalati\Webflow\Model\Meta\AuthorizedUser;
use Koalati\Webflow\Model\Site\Domain;
use Koalati\Webflow\Model\Site\Site;
use Koalati\Webflow\Model\Site\Webhook;

/**
* A Client that wraps `Koalati\Webflow\Api\Client` to simplify method calls
* when all of your operations are to be performed on the same site.
*
* Instead of providing the site ID to every method call, this wrapper takes
* the site ID when it is created and uses it for all API calls.
*
* @see https://developers.webflow.com/reference
* @see https://developers.webflow.com/docs/api-overview
*
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
*/
class SiteClient
{
/**
* ID of the site to use for all calls with this client
*/
private readonly string $siteId;

/**
* ID of the site to use for all calls with this client
*/
private readonly Client $client;

/**
* @param string $accessToken Webflow Access Token obtained via OAuth 2.0 (recommended) or Site API Token. @see https://github.com/koalatiapp/webflow-api-client#authenticate-with-webflow
*/
public function __construct(
string $accessToken,
string|Site $siteId,
) {
$this->client = new Client($accessToken);
$this->siteId = (string) $siteId;
}

public function getAuthorizedUser(): AuthorizedUser
{
return $this->client->getAuthorizedUser();
}

public function getAuthorizedInfo(): Authorization
{
return $this->client->getAuthorizedInfo();
}

/**
* List of all sites the provided access token is able to access.
*
* @return array<int,Site>
*/
public function listSites(): array
{
return $this->client->listSites();
}

/**
* Get a site by site id.
*/
public function getSite(): Site
{
return $this->client->getSite($this->siteId);
}

/**
* Publish a site.
*
* @param array<mixed,Domain|string> $domains Array of domain names to publish to (e.g. `mysite.webflow.io` or `mysite.com`). If left empty, this will publish to all domains registered for the site.
*/
public function publishSite(array $domains = []): bool
{
return $this->client->publishSite($this->siteId, $domains);
}

/**
* List of all custom domains added to a given site
*
* @return array<int,Domain>
*/
public function listDomains(): array
{
return $this->client->listDomains($this->siteId);
}

/**
* List of all webhooks in a given site
*
* @return array<int,Webhook>
*/
public function listWebhooks(): array
{
return $this->client->listWebhooks($this->siteId);
}

/**
* Get a site webhook
*/
public function getWebhook(string $webhookId): Webhook
{
return $this->client->getWebhook($this->siteId, $webhookId);
}

/**
* Create a new webhook
*/
public function createWebhook(Webhook $webhook): Webhook
{
return $this->client->createWebhook($this->siteId, $webhook);
}

/**
* Remove a webhook
*/
public function removeWebhook(Webhook|string $webhookId): bool
{
return $this->client->removeWebhook($this->siteId, $webhookId);
}

/**
* List of all collections in a given site.
*
* @return array<int,Collection>
*/
public function listCollections(): array
{
return $this->client->listCollections($this->siteId);
}

/**
* Get a collection by collection id.
*/
public function getCollection(string $collectionId): Collection
{
return $this->client->getCollection($collectionId);
}

/**
* Get all items for a collection
*
* @return array<int,CollectionItem>
*/
public function listCollectionItems(Collection|string $collectionId): array
{
return $this->client->listCollectionItems($collectionId);
}

/**
* Get an item in a collection
*/
public function getCollectionItem(Collection|string $collectionId, string $itemId): CollectionItem
{
return $this->client->getCollectionItem($collectionId, $itemId);
}

/**
* Create a new collection item
*/
public function createCollectionItem(Collection|string $collectionId, CollectionItem $item, bool $publishImmediately): CollectionItem
{
return $this->client->createCollectionItem($collectionId, $item, $publishImmediately);
}

/**
* Update an existing collection item.
* To upload a new image set the image URL to the corresponding item's field.
* Collection items that reuse images previously uploaded can just reference their fileId property.
*/
public function updateCollectionItem(Collection|string $collectionId, CollectionItem $item, bool $publishImmediately): CollectionItem
{
return $this->client->updateCollectionItem($collectionId, $item, $publishImmediately);
}

/**
* Remove or unpublish an item in a collection.
*
* @param bool $keepAsDraft When $keepAsDraft is set to `true`, the items will be unpublished and kept as drafts instead of being deleted.
*/
public function removeCollectionItem(Collection|string $collectionId, CollectionItem|string $itemId, bool $keepAsDraft): bool
{
return $this->client->removeCollectionItem($collectionId, $itemId, $keepAsDraft);
}

/**
* Remove or unpublish items in a collection.
*
* @param array<int,string|CollectionItem> $itemIds
* @param bool $keepAsDraft When $keepAsDraft is set to `true`, the items will be unpublished and kept as drafts instead of being deleted.
* @throws CollectionItemDeletionException
*/
public function removeCollectionItems(Collection|string $collectionId, array $itemIds, bool $keepAsDraft): bool
{
return $this->client->removeCollectionItems($collectionId, $itemIds, $keepAsDraft);
}

/**
* Publish items in a Collection.
*
* @param array<int,string|CollectionItem> $itemIds
*
* @throws CollectionItemPublishingException
*/
public function publishCollectionItems(Collection|string $collectionId, array $itemIds): bool
{
return $this->client->publishCollectionItems($collectionId, $itemIds);
}

/**
* Get a list of users for a site
*
* @return array<int,User>
*/
public function listUsers(): array
{
return $this->client->listUsers($this->siteId);
}

/**
* Get a User by id
*/
public function getUser(string $userId): User
{
return $this->client->getUser($this->siteId, $userId);
}

/**
* Update a User by id.
* The `email` and `password` fields cannot be updated using this endpoint.
*
* @return User An updated user instance
*
* @throws CannotUpdateNonExistingModelException
* @throws InvalidUserUpdateException
*/
public function updateUser(User $user): User
{
return $this->client->updateUser($this->siteId, $user);
}

/**
* Delete a User by id.
*/
public function deleteUser(User|string $userId): bool
{
return $this->client->deleteUser($this->siteId, $userId);
}

/**
* Invite a user by email address.
*
* @param array<mixed,string|AccessGroup> $accessGroups
*/
public function inviteUser(string $email, array $accessGroups): User
{
return $this->client->inviteUser($this->siteId, $email, $accessGroups);
}

/**
* Get a list of access groups for a site
*
* @return array<int,AccessGroup>
*/
public function listAccessGroups(): array
{
return $this->client->listAccessGroups($this->siteId);
}
}
Loading

0 comments on commit b6ed035

Please sign in to comment.