helpscout / helpscout-api-php

PHP Wrapper for the Help Scout API
MIT License
98 stars 62 forks source link

Bug in paged collection counts? #170

Closed lancedockins closed 5 years ago

lancedockins commented 5 years ago

Following some of the code examples in the library, I crafted a request to retrieve customers based on a search for their email. In the code, we are currently testing with a known existent customer in HelpScout that was created via this exact PHP API moments before our query testing began.

When we request the search, it returns a complete zero result set but then if we try to create the same customer with the same data that was used to create the customer initially and submit that to the API, we get a "conflict" error back from the API via a Guzzle exception. So the API endpoint seems to be aware that this Customer object exists, but the PHP API query to search for that user by it's identifiable data (namely a unique email) is returning an empty set.

Code for example:

    $data['email'] = 'lance@someemail.test';
    $filters = (new CustomerFilters())->withQuery('email:"' . $data['email'] . '"');
    $customers = $client->customers()->list($filters);
    $count = $customers->getPageSize();
    $count2 = $customers->getPageElementCount();
    $count3 = $customers->getPageNumber();
    $count4 = $customers->getTotalPageCount();
    $count5 = count($customers);
    $count6 = $customers->getTotalElementCount();
    var_dump($count, $count2, $count3, $count4, $count5, $count6);`

This produces this output: int(50) int(0) int(1) int(0) int(0) int(0)

So based on the PHP object results, there are no customer accounts. But then if we follow through with the same code used to produce the Customer we are querying for like this (or any variation on counting the returned result set from the above): ` if(count($customers) == 0) { // Create Customer $customer = new Customer(); $customer->setFirstName($data['firstName']); $customer->setLastName($data['lastName']);

        if(!empty($data['email'])) {
            $email = new Email();
            $email->hydrate([
                'value' => $data['email'],
                'type' => 'work',
            ]);             
            $customer->addEmail($email);
        }

        if(!empty($data['phone'])) {
                $phone = new Phone();
                $phone->hydrate([
                    'value' => $data['phone'],
                    'type' => 'work',
                ]);
                $customer->addPhone($phone);
        }

        $id = $client->customers()->create($customer);
    }
    elseif(count($customers) == 1) {
        var_dump($customers[0]->getId());
    }`

It then produces this error (note that the paths below have been intentionally sanitized): <b>Fatal error</b>: Uncaught GuzzleHttp\Exception\ClientException: Client error:POST https://api.helpscout.net/v2/customersresulted in a409 Conflict` response: {"logRef":"ec159308-58f3-42b7-827a-2788227a7d8c#46682360","message":"Conflict - entity cannot be created","_embedded":{" (truncated...) in /path/to/code/includes/helpscout/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113 Stack trace:

0 /path/to/code/includes/helpscout/vendor/helpscout/api/src/Http/Handlers/ClientErrorHandler.php(19): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response))

1 /path/to/code/includes/helpscout/vendor/guzzlehttp/promises/src/Promise.php(203): HelpScout\Api\Http\Handlers\ClientErrorHandler->HelpScout\Api\Http\Handlers{closure}(Object(GuzzleHttp\Psr7\Response))

2 /path/to/code/includes/helpscout/vendor/guzzlehttp/promises/src/Promise.php(156): Gu in /path/to/code/includes/helpscout/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php on line 113
`

While I suppose it's possible that the initial PagedCollection object is simply getting bad info from the HelpScout API, it seemed more likely that the PHP object was simply parsing the collection metadata incorrectly or failing to populate with correct pagination/total values.

Any thoughts?

bkuhl commented 5 years ago

Hey Lance,

I appreciate all of the detail, that's helpful.

A 409 response in this scenario makes sense since you mentioned you had previously created that Customer. A 409 indicates another Customer is associated with this email.

That leaves the question of why it isn't available in the search results. I've looked into this and I it's not clear to me why this endpoint wouldn't have supplied that Customer. I'm going to follow up with some other folks here in-house and I'll get back with you on this.

In the mean time, I was able to create a Customer using that same email address on the same company where you experienced the conflict and then fetch that Customer from the search list a few seconds later, so I suspect whatever the issue was has cleared up, though we'll continue to investigate on our end.

lancedockins commented 5 years ago

I was actually testing this with some other email address than the one that I provided in my report, but you are correct that whatever it was that was happening is gone now. I realized that the Conflict/409 error should have been occurring in situations where there was, in fact, a contact conflict. It was more that the API was returning data that caused an incorrect list count that was the "bug" I was reporting since the customer creation code shouldn't have been running in a context where there were returned customers from the list query in the first place.

All seems to have resolved itself now, though.

Thank you.