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

Base modifications #144

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open

Conversation

iranl
Copy link
Contributor

@iranl iranl commented Jun 10, 2019

Comprises part of the changes in #142

  • Add additions to current base files (e.g. BaseApiConnector, BaseDocuments, BaseMapper)
  • Other small modifications that have no effect on existing functionality

BaseApiConnector

  • Adds getConnection function which is used to call other ApiConnectors from within an ApiConnector
  • Adds convertOptionsToArrayOfString function to convert a simple $options array to a Twinfield acceptable ArrayOfString when using the Finder
  • Adds mapListAll function to allow easy mapping of listAll results to objects

BaseDocument

  • Extends CreateNodeWithTextContent function to optionally add attributes to a node

BaseMapper

  • Extends getField function to optionally allow checking for (error) messages on the field
  • Adds getAttribute function to read attributes of a node
  • Adds parse functions for Boolean, Date, DateTime, Enum Money and Object fields

Read

  • Adds some child functionality to Read, so these common functions can later be removed from the children

OpenIdConnectAuthentication

  • Extends __construct function with the optional ability to connect using a known access token and access cluster for quicker connections

BaseService

Other

  • Removal of unnecessary whitespaces and typos

Copy link
Contributor

@willemstuursma willemstuursma left a comment

Choose a reason for hiding this comment

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

Thank you so much @iranl for taking the time to create this PR.

Some generic feedback:

  • [] can be the default argument for array typed parameters, this allows you to remove the isset check
  • The usage of some method parameters is not clear to me, can you update the relevant phpdocs.
  • Please do not treat EUR currency special, always have it be made explicit
  • Full class names are superior to shortened classnames: they can be autocompleted by the IDE, type checked and their usages can easily be found
  • The Office type has been removed in some places, I think this is a merge error?

In my company we use PhpStorm and we rely heavily on type hints to prevent bugs, hence the focus on types. Basically, any method call that you cannot click in the IDE is frowned upon.

Please let me know if you have any questions or would like to discuss.

@@ -47,6 +47,11 @@ public function __construct(AuthenticatedConnection $connection)
$this->connection = $connection;
}

public function getConnection()
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a typehint for the return type? Why is this method needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The modified InvoicesDocument addInvoice function uses the InvoiceTypeApiConnector and ArticleApiConnector to request additional information on the selected InvoiceType and Articles in the Invoice, which means it needs access to the current connection. The InvoiceApiConnector sendAll function calls the parent BaseApiConnector getConnection function and passes the connection as an argument to addInvoice.

Typehint added

src/ApiConnectors/BaseApiConnector.php Outdated Show resolved Hide resolved
src/ApiConnectors/BaseApiConnector.php Outdated Show resolved Hide resolved
src/ApiConnectors/BaseApiConnector.php Outdated Show resolved Hide resolved
src/ApiConnectors/BaseApiConnector.php Outdated Show resolved Hide resolved
src/Mappers/BaseMapper.php Outdated Show resolved Hide resolved
src/Mappers/BaseMapper.php Outdated Show resolved Hide resolved
src/Mappers/BaseMapper.php Outdated Show resolved Hide resolved
src/Request/Read/BrowseDefinition.php Show resolved Hide resolved
src/Request/Read/Transaction.php Outdated Show resolved Hide resolved
Copy link
Contributor

@willemstuursma willemstuursma left a comment

Choose a reason for hiding this comment

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

Thanks @iranl! We're making good progress.

{
if ($className == "DimensionGroupDimension" || $className == "UnknownDimension") {
if ($className == "DimensionGroupDimension") {
if ($objectClass == "DimensionGroupDimension" || $objectClass == "UnknownDimension") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should these strings be updated to class references (::class)?

Copy link
Contributor Author

@iranl iranl Jun 11, 2019

Choose a reason for hiding this comment

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

No, they cannot, as they are non existent stubs that tell this function to determine the real class from an argument contained in the XML element or sibling XML element.

parseObjectAttribute is usually used when the Twinfield entity contained in the XML is static (such as the <user> element which will always contain a user (or nothing)). In this case ::class is used when calling parseObjectAttribute

In DimensionGroupDimension, CustomerFinancials, FixedAssetTransactionLine and SupplierFinancials there are fields that can contain multiple or any of the 7 dimensionTypes. In these cases $className == "DimensionGroupDimension" or $className == "UnknownDimension" is used to tell the function to change $objectClass to the real class name in the following switch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this part of the parseObjectAttribute function to a different function, seems like a cleaner solution

if ($fieldElement->textContent === "") {
return null;
}

return $fieldElement->textContent;
}

protected static function checkForMessage($object, \DOMElement $element): void
Copy link
Contributor

Choose a reason for hiding this comment

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

Well, this method calls addMessage() on the object, so it cannot take any object right. It has to take an object that supports messages and the required method call.

So ideally, these objects would have an interface HasMessage that defines the method addMessage(Message $message): void so that you can use this typehint in the method parameter list.

You can read a bit about interfaces here: https://www.zentut.com/php-tutorial/php-interface/ Please ignore the crappy naming in the article, interfaces should have names like SupportFoo, CanBar or even IsBazable to indicate the class supports some functionality.

return $fieldElement->getAttribute($attributeName);
}

protected static function parseBooleanAttribute(?string $value): ?bool
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not entirely convinced - I think that it for new functionality it would be hard to decide which boolean parsing function should be used. The existence of two is confusing if there is no clear guideline to pick one over the other.

Please consolidate into one method, its fine to change the one in Util, that's why we have tests.

@iranl
Copy link
Contributor Author

iranl commented Jun 11, 2019

@willemstuursma Moving along quite nicely. Thanks for all the reviewing!

@iranl
Copy link
Contributor Author

iranl commented Jun 27, 2019

@willemstuursma Do you have any unsolved requests concerning the current PR?

If not, I would like to continue with the next part of #142

@willemstuursma
Copy link
Contributor

Sorry @iranl, I noticed some changes but it is really super busy in my day job, so I didn't have time to do any further reviewing yet.

@iranl
Copy link
Contributor Author

iranl commented Jun 28, 2019

@willemstuursma no problem. Just thought I'd check you weren't waiting on more changes from me. Will continue the conversation when you have the time.

@iranl
Copy link
Contributor Author

iranl commented Aug 22, 2019

@willemstuursma I see you're actively reviewing PR's again. Will you be able to help this PR along? I am still willing and able to break up #142 as previously agreed.

@ericclaeren
Copy link
Contributor

Hi,

I'm new to this package, running into the access token issue where it's logging in for each request while I already have a valid token, which results in quite some additional requests.

I could help you with the access token part, although it would be breaking for current implementations, we could use AccessTokenInterface to pass the access + refresh token + expires to let this package check if it's valid and requesting a new access token when it's invalid. Or use a setter for it,

Or possible add a tokenRefresh callback method to call when token is refreshed so it can be stored externally. Because there's no way to get the access token from the current connection.

Don't mean to barge in, but would love have this feature :) and can get some time from my company to help with this.

Cheers, Eric

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