Skip to content
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

[2.x] Adds strict types using Phpstan #44

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open

Conversation

lukeraymonddowning
Copy link
Contributor

For 2.x, I'd like to introduce strict type hinting.

The reasoning is fairly straightforward: better IDE support, a smaller chance of bugs and better integration for other users using PhpStan.

This also gives us a great opportunity to think about next steps as regards Http drivers (#36), unified interfaces and more.

composer.json Outdated Show resolved Hide resolved
src/Header.php Outdated Show resolved Hide resolved
src/Providers/SoapRayServiceProvider.php Outdated Show resolved Hide resolved
src/Request/SoapPhpRequest.php Outdated Show resolved Hide resolved
src/Soap.php Outdated Show resolved Hide resolved
/**
* @param array<string, Closure(Request): Response|Response>|null $callback
*/
public function fake(array $callback = null): void
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need to be ?array?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

According to how it was/is implemented below, yes

Copy link
Contributor

@nedwors nedwors left a comment

Choose a reason for hiding this comment

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

Nice work @lukeraymonddowning 🔥

src/Support/Scopes/IsScoped.php Outdated Show resolved Hide resolved
Copy link

@veewee veewee left a comment

Choose a reason for hiding this comment

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

Looks nice at first sight. I've added some remarks and questions here and there.

/**
* Make a request and return its response.
*/
public function call(string $method, mixed $body): mixed;
Copy link

Choose a reason for hiding this comment

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

maybe better to change mixed $body to array $arguments?
That way it is compatible with how ext-soap works internally and with php-soap/engine:

It allows for multi-params requests (see #45)

$this->registerRay();
$this->app->bind(Request::class, fn (Application $app) => new SoapPhpRequest(
$app->make(Builder::class),
new DecoratedClient()
Copy link

@veewee veewee Oct 11, 2021

Choose a reason for hiding this comment

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

So if I understand this correctly, changing a client would mean overwriting the bind to the request class?
The request class itself should be compatible over different clients?

Did you already have a vision on how you would like people to configure different clients / requests?
Would that be something on the soap facade or rather in service config?

/**
* @param array<string, mixed>|Soapable $body
*/
public function call(string $method, array|Soapable $body = []): Response;
Copy link

Choose a reason for hiding this comment

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

Same as for the Client contract : it is better to make it an array of parameters imo or a variadic


private function client(): Client
{
return $this->client
Copy link

Choose a reason for hiding this comment

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

This structure is a bit strange since you can change options in between requests, but the decorated client itself uses a memoized versionof the client. Only the headers will be changed since the options and endpoint might have been set.

Either way : you want to avoid constructing the internal SoapClient twice, since it will load the wsdl again as well. which canbe a slow task

/**
* @internal
*/
final class DecoratedClient implements Client
Copy link

@veewee veewee Oct 11, 2021

Choose a reason for hiding this comment

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

This name is a bit strange to me : sure, it decorates a built-in SoapClient.
Maybe better to name it after what it decorates? That could make it easier if you want to provide more clients

return $this->client()->__getFunctions();
}

public function __get(string $name): mixed
Copy link

Choose a reason for hiding this comment

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

what is this being used for exactly? There are no public properties on the client IIRC.

}

public function to(string $endpoint)
public function to(string $endpoint): Request
{
return (clone $this->request)
Copy link

@veewee veewee Oct 11, 2021

Choose a reason for hiding this comment

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

since it clones the internal request, what happens if you call Soap::to twice with different wsdls?
Does it incorrectly use the memoized client decorated client from inside the Request class?

Reason why I ask : many coorporations split their soap services into multiple WSDL files for you to implement.


use SoapHeader;

interface Client
Copy link

Choose a reason for hiding this comment

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

Pretty sure it is possible to create a client using phpro/soap-client that implements this interface.

*
* @return array<int, string>
*/
public function getFunctions(): array;
Copy link

Choose a reason for hiding this comment

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

Our php-soap engine returns more information about the functions than a regular string.
https://github.com/php-soap/engine/blob/main/src/Metadata/Metadata.php

We could parse them back to a regular int, string - but it means you will loose some information.
Alternatively we could add a generic for determing what kind of information this function will return?


interface Client
{
public function setEndpoint(string $endpoint): static;
Copy link

Choose a reason for hiding this comment

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

Not sure if the setters in this interface are a good idea though. See further down this code review - it allows for some strange structures.

public function withDigestAuth(string $login, string $password): self;

public function withHeaders(Header ...$headers): self;

Copy link

Choose a reason for hiding this comment

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

This request is a bit shaped around the existing soap client.
Did you already think about how more advanced options could be added to a request? For example http middleware etc, ... - which are not possible with the regular soap client?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants