diff --git a/docs/sample/code/test.php b/docs/sample/code/test.php new file mode 100644 index 0000000..07e302d --- /dev/null +++ b/docs/sample/code/test.php @@ -0,0 +1,98 @@ +setClientId('1000.51C3ETBOWTOA03UL19U5EMV0F74VQR') + ->setClientSecret('4086937c603d0e174ee58d5b6d9b21fb6b93802fd8') + ->setRedirectUrl('') + ->setCurrentUserEmail('thomas.klein@mpbio.com') + ->setApiBaseUrl(Metadata::API_ENDPOINT_EU) + ->setApiVersion(Metadata::API_VERSION) + ->setOrgId(20076919967) + ->setIsSandbox(false) + ->setAccountsUrl(Metadata::API_ACCOUNTS_EU) + ->setTokenPersistencePath(__DIR__); + +$config = $configBuilder->create(); +$gateway = new Gateway($config); + +// Optional: if you need to register the token first +// ZohoOAuth::initialize($config->get()); +// ZohoOAuth::getClientInstance()->generateAccessToken('1000.125d9d14ca4c42d8c3be5164d19433a8.c6c3be950b0290639f5126f5d9ff810b'); + + +try { + $criteriaBuilder = new ListCriteriaBuilder(); + $criteriaBuilder->setFields(['id','subject', 'email', 'description','webUrl']); + // $criteriaBuilder->setFields()->setFilters()... + $ticketList = $gateway->getOperationPool()->getListOperation('tickets')->getList($criteriaBuilder->create()); + //$ticketList = $gateway->getOperationPool()->getListOperation('tickets')->getByIds([1,2,3]); +} catch (CouldNotReadException $e) { + echo $e->getMessage(); + echo "
"; + echo $e->getPrevious()->getMessage(); +} + +echo '
';
+foreach ($ticketList as $ticket) {
+    echo '
'; + print_r($ticket->toArray()); +} + + die; + +/** CRUD Operations **/ + +$ticketDataObject = $gateway->getDataObjectFactory()->create('tickets', /* Entity values */); + +try { + $ticketDataObject = $gateway->getOperationPool()->getCreateOperation('tickets')->create($ticketDataObject); +} catch (CouldNotSaveException $e) { + // Handle the exception... +} + +try { + $ticketDataObject = $gateway->getOperationPool()->getReadOperation('tickets')->get(1234); +} catch (CouldNotReadException $e) { + // Handle the exception... +} + +try { + $criteriaBuilder = new ListCriteriaBuilder(); + // $criteriaBuilder->setFields()->setFilters()... + $ticketList = $gateway->getOperationPool()->getListOperation('tickets')->getList($criteriaBuilder->create()); + $ticketList = $gateway->getOperationPool()->getListOperation('tickets')->getByIds([1,2,3]); +} catch (CouldNotReadException $e) { + // Handle the exception... +} + +try { + $ticketDataObject = $gateway->getOperationPool()->getUpdateOperation('tickets')->update($ticketDataObject); +} catch (CouldNotSaveException $e) { + // Handle the exception... +} + +try { + $gateway->getOperationPool()->getDeleteOperation('tickets', ['resolution'])->delete(1234); +} catch (CouldNotDeleteException $e) { + // Handle the exception... +} diff --git a/docs/sample/code/zcrm_oauthtokens.txt b/docs/sample/code/zcrm_oauthtokens.txt new file mode 100644 index 0000000..2e59250 Binary files /dev/null and b/docs/sample/code/zcrm_oauthtokens.txt differ diff --git a/docs/sample/code/zoho_oauth.log b/docs/sample/code/zoho_oauth.log new file mode 100644 index 0000000..297e733 --- /dev/null +++ b/docs/sample/code/zoho_oauth.log @@ -0,0 +1 @@ +2021-03-24 09:14:01 INFO: Access Token has expired. Hence refreshing. diff --git a/src/Client/RequestBuilder.php b/src/Client/RequestBuilder.php index 85c3a65..7b88407 100644 --- a/src/Client/RequestBuilder.php +++ b/src/Client/RequestBuilder.php @@ -12,7 +12,11 @@ use Zoho\Desk\Exception\Exception; use Zoho\Desk\Exception\InvalidArgumentException; use Zoho\Desk\OAuth\ClientInterface; + +use function array_keys; +use function array_map; use function array_merge; +use function array_values; use function curl_init; use function curl_setopt; use function http_build_query; @@ -20,6 +24,8 @@ use function is_numeric; use function json_encode; use function sprintf; +use function str_replace; + use const CURLOPT_CUSTOMREQUEST; use const CURLOPT_HEADER; use const CURLOPT_HTTPHEADER; @@ -61,6 +67,9 @@ public function __construct(ClientInterface $client, array $mandatoryData = []) $this->data = []; } + /** + * @deprecated + */ public function setEntityType(string $entityType): self { $this->data['entityType'] = $entityType; @@ -68,6 +77,15 @@ public function setEntityType(string $entityType): self return $this; } + public function setPath(string $path, array $bind = []): self + { + $search = array_map(static function (string $variable): string { + return '{' . $variable . '}'; + }, array_keys($bind)); + + return $this->setEntityType(str_replace($search, array_values($bind), $path)); + } + public function setMethod(string $method): self { $this->data['method'] = $method; diff --git a/src/Model/Operation/CreateOperationInterface.php b/src/Model/Operation/CreateOperationInterface.php index 5bc093b..56d5867 100644 --- a/src/Model/Operation/CreateOperationInterface.php +++ b/src/Model/Operation/CreateOperationInterface.php @@ -12,6 +12,7 @@ /** * @api + * @deprecated */ interface CreateOperationInterface { diff --git a/src/Model/Operation/DeleteOperationInterface.php b/src/Model/Operation/DeleteOperationInterface.php index 509fe6a..bc5c7eb 100644 --- a/src/Model/Operation/DeleteOperationInterface.php +++ b/src/Model/Operation/DeleteOperationInterface.php @@ -11,6 +11,7 @@ /** * @api + * @deprecated */ interface DeleteOperationInterface { diff --git a/src/Model/Operation/ListOperationInterface.php b/src/Model/Operation/ListOperationInterface.php index 641c7b4..24b1d0b 100644 --- a/src/Model/Operation/ListOperationInterface.php +++ b/src/Model/Operation/ListOperationInterface.php @@ -13,6 +13,7 @@ /** * @api + * @deprecated */ interface ListOperationInterface { diff --git a/src/Model/Operation/ReadOperationInterface.php b/src/Model/Operation/ReadOperationInterface.php index db60fc4..55f38c4 100644 --- a/src/Model/Operation/ReadOperationInterface.php +++ b/src/Model/Operation/ReadOperationInterface.php @@ -12,6 +12,7 @@ /** * @api + * @deprecated */ interface ReadOperationInterface { diff --git a/src/Model/Operation/UpdateOperationInterface.php b/src/Model/Operation/UpdateOperationInterface.php index 6ad7f18..4c2b2af 100644 --- a/src/Model/Operation/UpdateOperationInterface.php +++ b/src/Model/Operation/UpdateOperationInterface.php @@ -12,6 +12,7 @@ /** * @api + * @deprecated */ interface UpdateOperationInterface { diff --git a/src/Model/OperationPool.php b/src/Model/OperationPool.php index 2545f65..421b62b 100644 --- a/src/Model/OperationPool.php +++ b/src/Model/OperationPool.php @@ -21,6 +21,9 @@ use function implode; use function md5; +/** + * @deprecated + */ final class OperationPool { private RequestBuilder $requestBuilder; diff --git a/src/Service/CreateOperation.php b/src/Service/CreateOperation.php new file mode 100644 index 0000000..81fca09 --- /dev/null +++ b/src/Service/CreateOperation.php @@ -0,0 +1,76 @@ +requestBuilder = $requestBuilder; + $this->dataObjectFactory = $dataObjectFactory; + $this->entityType = $entityType; + $this->path = $path; + $this->arguments = $arguments; + } + + public function create(DataObjectInterface $dataObject, array $bind = []): DataObjectInterface + { + try { + return $this->dataObjectFactory->create($this->entityType, $this->saveEntity($dataObject)->getResult()); + } catch (InvalidArgumentException $e) { + throw new CouldNotSaveException($e->getMessage(), $e->getCode(), $e); + } catch (InvalidRequestException $e) { + throw new CouldNotSaveException($e->getMessage(), $e->getCode(), $e); + } catch (Exception $e) { + throw new CouldNotSaveException('Could not create the entity.', $e->getCode(), $e); + } + } + + /** + * @throws Exception + * @throws InvalidArgumentException + * @throws InvalidRequestException + */ + private function saveEntity(DataObjectInterface $dataObject, array $bind = []): ResponseInterface + { + return $this->requestBuilder + ->setPath($this->path ?? $this->entityType, $bind) + ->setMethod(RequestBuilder::HTTP_POST) + ->setArguments($this->arguments) + ->setFields($dataObject->toArray()) + ->create() + ->execute(); + } +} diff --git a/src/Service/CreateOperationInterface.php b/src/Service/CreateOperationInterface.php new file mode 100644 index 0000000..adcf8f9 --- /dev/null +++ b/src/Service/CreateOperationInterface.php @@ -0,0 +1,22 @@ +requestBuilder = $requestBuilder; + $this->entityType = $entityType; + $this->path = $path; + $this->arguments = $arguments; + } + + public function delete(array $bind): void + { + try { + $this->requestBuilder + ->setPath($this->path ?? $this->entityType, $bind) + ->setMethod(RequestBuilder::HTTP_DELETE) + ->setArguments($this->path ? $this->arguments : array_merge([reset($bind)], $this->arguments)) + ->create() + ->execute(); + } catch (InvalidArgumentException $e) { + throw new CouldNotDeleteException($e->getMessage(), $e->getCode(), $e); + } catch (InvalidRequestException $e) { + throw new CouldNotDeleteException($e->getMessage(), $e->getCode(), $e); + } catch (Exception $e) { + $flatten = ''; + foreach ($bind as $key => $value) { + $flatten .= sprintf('%s: %s ', $key, $value); + } + throw new CouldNotDeleteException( + sprintf('Could not delete the entity with %s.', rtrim($flatten)), + $e->getCode(), + $e + ); + } + } +} diff --git a/src/Service/DeleteOperationInterface.php b/src/Service/DeleteOperationInterface.php new file mode 100644 index 0000000..efef99b --- /dev/null +++ b/src/Service/DeleteOperationInterface.php @@ -0,0 +1,21 @@ +requestBuilder = $requestBuilder; + $this->dataObjectFactory = $dataObjectFactory; + $this->entityType = $entityType; + $this->path = $path; + $this->arguments = $arguments; + } + + public function getList(ListCriteriaInterface $listCriteria, array $bind = []): array + { + $arguments = $listCriteria->getFilters() ? array_merge(['search'], $this->arguments) : $this->arguments; + + try { + $response = $this->fetchResult($arguments, $listCriteria->getQueryParams(), $bind); + } catch (InvalidArgumentException $e) { + throw new CouldNotReadException($e->getMessage(), $e->getCode(), $e); + } catch (InvalidRequestException $e) { + throw new CouldNotReadException($e->getMessage(), $e->getCode(), $e); + } catch (Exception $e) { + throw new CouldNotReadException('Could not fetch the entities.', $e->getCode(), $e); + } + + return $this->buildEntities($response); + } + + /** + * @return DataObjectInterface[] + */ + private function buildEntities(ResponseInterface $response): array + { + $entities = []; + $result = $response->getResult(); + if (isset($result['data']) && is_array($result['data'])) { + foreach ($result['data'] as $entity) { + $entities[] = $this->dataObjectFactory->create($this->entityType, $entity); + } + } + + return $entities; + } + + /** + * @throws Exception + * @throws InvalidArgumentException + * @throws InvalidRequestException + */ + private function fetchResult(array $arguments, array $params = [], array $bind = []): ResponseInterface + { + return $this->requestBuilder + ->setPath($this->path ?? $this->entityType, $bind) + ->setMethod(RequestBuilder::HTTP_GET) + ->setArguments($arguments) + ->setQueryParameters($params) + ->create() + ->execute(); + } +} diff --git a/src/Service/ListOperationInterface.php b/src/Service/ListOperationInterface.php new file mode 100644 index 0000000..04ce385 --- /dev/null +++ b/src/Service/ListOperationInterface.php @@ -0,0 +1,23 @@ +requestBuilder = $requestBuilder; + $this->dataObjectFactory = $dataObjectFactory; + $this->entityType = $entityType; + $this->path = $path; + $this->arguments = $arguments; + } + + public function get(array $bind): DataObjectInterface + { + try { + return $this->dataObjectFactory->create($this->entityType, $this->fetchEntity($bind)->getResult()); + } catch (InvalidArgumentException $e) { + throw new CouldNotReadException($e->getMessage(), $e->getCode(), $e); + } catch (InvalidRequestException $e) { + throw new CouldNotReadException($e->getMessage(), $e->getCode(), $e); + } catch (Exception $e) { + throw new CouldNotReadException('Could not fetch the entity.', $e->getCode(), $e); + } + } + + /** + * @throws Exception + * @throws InvalidArgumentException + * @throws InvalidRequestException + */ + private function fetchEntity(array $bind = []): ResponseInterface + { + return $this->requestBuilder + ->setPath($this->path ?? $this->entityType, $bind) + ->setMethod(RequestBuilder::HTTP_GET) + ->setArguments($this->path ? $this->arguments : array_merge([reset($bind)], $this->arguments)) + ->create() + ->execute(); + } +} diff --git a/src/Service/ReadOperationInterface.php b/src/Service/ReadOperationInterface.php new file mode 100644 index 0000000..00954f0 --- /dev/null +++ b/src/Service/ReadOperationInterface.php @@ -0,0 +1,22 @@ +requestBuilder = $requestBuilder; + $this->dataObjectFactory = $dataObjectFactory; + $this->entityType = $entityType; + $this->path = $path; + $this->arguments = $arguments; + } + + public function update(DataObjectInterface $dataObject, array $bind = []): DataObjectInterface + { + if (!$dataObject->getEntityId()) { + throw new CouldNotSaveException('Could not update an entity without ID.'); + } + + try { + return $this->dataObjectFactory->create($this->entityType, $this->saveEntity($dataObject, $bind)->getResult()); + } catch (InvalidArgumentException $e) { + throw new CouldNotSaveException($e->getMessage(), $e->getCode(), $e); + } catch (InvalidRequestException $e) { + throw new CouldNotSaveException($e->getMessage(), $e->getCode(), $e); + } catch (Exception $e) { + throw new CouldNotSaveException( + sprintf('Could not update the entity with ID "%u".', $dataObject->getEntityId()), + $e->getCode(), + $e + ); + } + } + + /** + * @throws Exception + * @throws InvalidArgumentException + * @throws InvalidRequestException + */ + private function saveEntity(DataObjectInterface $dataObject, array $bind = []): ResponseInterface + { + return $this->requestBuilder + ->setPath($this->path ?? $this->entityType, $bind) + ->setMethod(RequestBuilder::HTTP_PATCH) + ->setArguments($this->path ? $this->arguments : array_merge([reset($bind)], $this->arguments)) + ->setFields($dataObject->toArray()) + ->create() + ->execute(); + } +} diff --git a/src/Service/UpdateOperationInterface.php b/src/Service/UpdateOperationInterface.php new file mode 100644 index 0000000..bcd60b3 --- /dev/null +++ b/src/Service/UpdateOperationInterface.php @@ -0,0 +1,22 @@ +