diff --git a/src/DataService.php b/src/DataService.php index ff7da36..fb4655a 100644 --- a/src/DataService.php +++ b/src/DataService.php @@ -2,14 +2,14 @@ namespace ActiveCollab\Quickbooks; -use ActiveCollab\Quickbooks\Quickbooks; use ActiveCollab\Quickbooks\Data\Entity; -use Guzzle\Service\Client as GuzzleClient; use ActiveCollab\Quickbooks\Data\QueryResponse; +use ActiveCollab\Quickbooks\Exception\FaultException; +use DateTime; use Guzzle\Http\Exception\BadResponseException; -use League\OAuth1\Client\Credentials\TokenCredentials; +use Guzzle\Service\Client as GuzzleClient; use League\OAuth1\Client\Credentials\ClientCredentials; -use DateTime; +use League\OAuth1\Client\Credentials\TokenCredentials; class DataService { @@ -32,7 +32,7 @@ class DataService /** * Construct data service - * + * * @param string $consumer_key * @param string $consumer_key_secret * @param string $access_token @@ -46,11 +46,11 @@ public function __construct($consumer_key, $consumer_key_secret, $access_token, $this->access_token = $access_token; $this->access_token_secret = $access_token_secret; $this->realmId = $realmId; - } + } /** * Return api url - * + * * @return string */ public function getApiUrl() @@ -60,7 +60,7 @@ public function getApiUrl() /** * Return http client - * + * * @return GuzzleClient */ public function createHttpClient() @@ -70,7 +70,7 @@ public function createHttpClient() /** * Return oauth server - * + * * @return Quickbooks */ public function createServer() @@ -84,7 +84,7 @@ public function createServer() /** * Return token credentials - * + * * @return TokenCredentials */ public function getTokenCredentials() @@ -98,8 +98,10 @@ public function getTokenCredentials() /** * Set user agent - * + * * @param string|null $user_agent + * + * @return static */ public function setUserAgent($user_agent = null) { @@ -110,7 +112,7 @@ public function setUserAgent($user_agent = null) /** * Return user agent - * + * * @return string */ public function getUserAgent() @@ -120,8 +122,10 @@ public function getUserAgent() /** * Set entity - * + * * @param string $entity + * + * @return static */ public function setEntity($entity) { @@ -132,7 +136,9 @@ public function setEntity($entity) /** * Return entity url - * + * + * @param string $slug + * * @return string */ public function getRequestUrl($slug) @@ -142,7 +148,7 @@ public function getRequestUrl($slug) /** * Send create request - * + * * @param array $payload * @return Entity */ @@ -155,7 +161,7 @@ public function create(array $payload) /** * Send read request - * + * * @param int $id * @return Entity */ @@ -170,7 +176,7 @@ public function read($id) /** * Send update request - * + * * @param array $payload * @return Entity */ @@ -185,7 +191,7 @@ public function update(array $payload) /** * Send delete request - * + * * @param array $payload * @return null */ @@ -200,11 +206,13 @@ public function delete(array $payload) /** * Send query request - * - * @param string|null $query + * + * @param string|null $query + * @param int|null $minorVersion + * * @return QueryResponse */ - public function query($query = null) + public function query($query = null, $minorVersion = null) { if ($query === null) { $query = "select * from {$this->entity}"; @@ -212,6 +220,11 @@ public function query($query = null) $uri = $this->getRequestUrl('query') . '?query=' . urlencode($query); + if (null !== $minorVersion) { + $this->validateMinorVersion($minorVersion); + $uri .= '&minorversion=' . $minorVersion; + } + $response = $this->request('GET', $uri); return new QueryResponse($response['QueryResponse']); @@ -219,10 +232,13 @@ public function query($query = null) /** * Send CDC request - * - * @param array $entities - * @param DateTime $changed_since + * + * @param array $entities + * @param DateTime $changed_since + * * @return array + * + * @throws \Exception */ public function cdc(array $entities, DateTime $changed_since) { @@ -254,12 +270,12 @@ public function cdc(array $entities, DateTime $changed_since) /** * Return headers for request - * + * * @param string $method * @param string $uri * @return array */ - public function getHeaders($method, $uri) + public function getHeaders($method, $uri) { $server = $this->createServer(); @@ -277,7 +293,7 @@ public function getHeaders($method, $uri) /** * Request - * + * * @param string $method * @param string $uri * @param string|array $body @@ -285,7 +301,7 @@ public function getHeaders($method, $uri) * @throws \Exception */ public function request($method, $uri, array $body = null) - { + { $client = $this->createHttpClient(); $headers = $this->getHeaders($method, $uri); @@ -298,13 +314,49 @@ public function request($method, $uri, array $body = null) return $client->createRequest($method, $uri, $headers, $body)->send()->json(); } catch (BadResponseException $e) { $response = $e->getResponse(); - $body = $response->getBody(); $statusCode = $response->getStatusCode(); + $body = $response->json(); + if (isset($body['Fault'])) { + throw $this->createFaultException($body, $e); + } + + $body = $response; throw new \Exception( "Received error [$body] with status code [$statusCode] when sending request." ); } } -} \ No newline at end of file + /** + * Validates the type for $minorVersion + * + * @param int $minorVersion + * + * @return self + * + * @throws \InvalidArgumentException + */ + private function validateMinorVersion($minorVersion) + { + if (!is_int($minorVersion)) { + throw new \InvalidArgumentException(sprintf('Invalid type for "$minorVersion" : expected "int", got "%s".', gettype($minorVersion))); + } + return $this; + } + + /** + * @param array $body + * @param \Exception $previous + * + * @return FaultException + */ + private function createFaultException(array $body, \Exception $previous = null) + { + $errors = []; + if (isset($body['Fault']['Error'])) { + $errors = $body['Fault']['Error']; + } + return new FaultException("Fault response : " . json_encode($errors), 0, $previous, $errors); + } +} diff --git a/src/Exception/Error.php b/src/Exception/Error.php new file mode 100644 index 0000000..63f07c6 --- /dev/null +++ b/src/Exception/Error.php @@ -0,0 +1,56 @@ +message = $message; + $this->detail = $detail; + $this->code = (int) $code; + $this->element = $element; + } + + /** + * @return string + */ + public function getDetail() + { + return $this->detail; + } + + /** + * @return int + */ + public function getCode() + { + return $this->code; + } +} diff --git a/src/Exception/FaultException.php b/src/Exception/FaultException.php new file mode 100644 index 0000000..5165566 --- /dev/null +++ b/src/Exception/FaultException.php @@ -0,0 +1,42 @@ +errors = []; + $this->setErrors($errors); + } + + private function setErrors($errors) + { + foreach ($errors as $error) { + $this->errors[] = new Error( + $error['Message'], + $error['Detail'], + $error['code'], + isset($error['element']) ? $error['element'] : null + ); + } + } + + /** + * @return array + */ + public function getErrors() + { + return $this->errors; + } +} diff --git a/src/Quickbooks.php b/src/Quickbooks.php index cc55b65..e134377 100644 --- a/src/Quickbooks.php +++ b/src/Quickbooks.php @@ -9,12 +9,24 @@ use League\OAuth1\Client\Credentials\TokenCredentials; use League\OAuth1\Client\Credentials\CredentialsException; use League\OAuth1\Client\Credentials\CredentialsInterface; +use League\OAuth1\Client\Credentials\TemporaryCredentials; +/** + * This class reflects a QuickBooks oddity : + * QuickBooks expects the oauth_verifier to be located in the header instead of the post body. + */ class Quickbooks extends Server { + /** + * oauth_verifier stored for use with. + * + * @var string + */ + private $verifier; + /** * Return temporary credentials url. - * + * * @return string */ public function urlTemporaryCredentials() @@ -24,7 +36,7 @@ public function urlTemporaryCredentials() /** * Return authorization url. - * + * * @return string */ public function urlAuthorization() @@ -34,7 +46,7 @@ public function urlAuthorization() /** * Return token credentials url. - * + * * @return string */ public function urlTokenCredentials() @@ -44,7 +56,7 @@ public function urlTokenCredentials() /** * Return user details url. - * + * * @return string */ public function urlUserDetails() @@ -54,7 +66,7 @@ public function urlUserDetails() /** * Return connection url. - * + * * @return string */ public function urlConnection() @@ -64,7 +76,7 @@ public function urlConnection() /** * Return user details. - * + * * @param array $data * @param TokenCredentials $tokenCredentials * @return User @@ -87,7 +99,7 @@ public function userDetails($data, TokenCredentials $tokenCredentials) /** * Return user uid. - * + * * @param array $data * @param TokenCredentials $tokenCredentials */ @@ -98,7 +110,7 @@ public function userUid($data, TokenCredentials $tokenCredentials) /** * Return user email. - * + * * @param array $data * @param TokenCredentials $tokenCredentials * @return string @@ -110,7 +122,7 @@ public function userEmail($data, TokenCredentials $tokenCredentials) /** * Retrun user screen name. - * + * * @param array $data * @param TokenCredentials $tokenCredentials */ @@ -121,7 +133,7 @@ public function userScreenName($data, TokenCredentials $tokenCredentials) /** * Return headers. - * + * * @param CredentialsInterface $credentials * @param string $method * @param string $url @@ -140,7 +152,7 @@ public function getHeaders(CredentialsInterface $credentials, $method, $url, arr /** * Reconnect and return new access tokens. - * + * * @param tokenCredentials $tokenCredentials * @return ConnectionResponse */ @@ -162,7 +174,7 @@ public function disconnect(TokenCredentials $tokenCredentials) /** * Send connection request. - * + * * @param TokenCredentials $tokenCredentials * @param string $action * @return ConnectionResponse @@ -182,4 +194,23 @@ public function sendConnectionRequest(TokenCredentials $tokenCredentials, $actio return new ConnectionResponse($response); } + + /** + * {@inheritDoc} + */ + public function getTokenCredentials(TemporaryCredentials $temporaryCredentials, $temporaryIdentifier, $verifier) + { + $this->verifier = $verifier; + return parent::getTokenCredentials($temporaryCredentials, $temporaryIdentifier, $verifier); + } + + /** + * {@inheritDoc} + */ + protected function additionalProtocolParameters() + { + return array( + 'oauth_verifier' => $this->verifier, + ); + } }