diff --git a/src/ApiConnectors/VatCodeApiConnector.php b/src/ApiConnectors/VatCodeApiConnector.php index 17b69251..c584e1c6 100644 --- a/src/ApiConnectors/VatCodeApiConnector.php +++ b/src/ApiConnectors/VatCodeApiConnector.php @@ -2,20 +2,93 @@ namespace PhpTwinfield\ApiConnectors; +use PhpTwinfield\DomDocuments\VatCodesDocument; +use PhpTwinfield\Exception; +use PhpTwinfield\Mappers\VatCodeMapper; +use PhpTwinfield\Office; +use PhpTwinfield\Request as Request; +use PhpTwinfield\Response\MappedResponseCollection; +use PhpTwinfield\Response\Response; use PhpTwinfield\Services\FinderService; use PhpTwinfield\VatCode; +use Webmozart\Assert\Assert; /** * A facade to make interaction with the the Twinfield service easier when trying to retrieve or send information about - * VAT codes. + * VatCodes. * * If you require more complex interactions or a heavier amount of control over the requests to/from then look inside * the methods or see the advanced guide detailing the required usages. * - * @author Emile Bons + * @author Yannick Aerssens , based on ArticleMapper by Willem van de Sande . Original method by Emile Bons */ class VatCodeApiConnector extends BaseApiConnector { + /** + * Requests a specific VatCode based off the passed in code and optionally the office. + * + * @param string $code + * @param Office $office If no office has been passed it will instead take the default office from the + * passed in config class. + * @return VatCode|bool The requested VAT code or false if it can't be found. + * @throws Exception + */ + public function get(string $code, Office $office): VatCode + { + // Make a request to read a single VatCode. Set the required values + $request_vatCode = new Request\Read\VatCode(); + $request_vatCode + ->setOffice($office->getCode()) + ->setCode($code); + + // Send the Request document and set the response to this instance. + $response = $this->sendXmlDocument($request_vatCode); + + return VatCodeMapper::map($response); + } + + /** + * Sends a VatCode instance to Twinfield to update or add. + * + * @param VatCode $vatCode + * @return VatCode + * @throws Exception + */ + public function send(VatCode $vatCode): VatCode + { + foreach($this->sendAll([$vatCode]) as $each) { + return $each->unwrap(); + } + } + + /** + * @param VatCode[] $vatCodes + * @return MappedResponseCollection + * @throws Exception + */ + public function sendAll(array $vatCodes): MappedResponseCollection + { + Assert::allIsInstanceOf($vatCodes, VatCode::class); + + /** @var Response[] $responses */ + $responses = []; + + foreach ($this->getProcessXmlService()->chunk($vatCodes) as $chunk) { + + $vatCodesDocument = new VatCodesDocument(); + + foreach ($chunk as $vatCode) { + $vatCodesDocument->addVatCode($vatCode); + } + + $responses[] = $this->sendXmlDocument($vatCodesDocument); + } + + return $this->getProcessXmlService()->mapAll($responses, "vat", function(Response $response): VatCode { + return VatCodeMapper::map($response); + }); + } + /** * List all VAT codes. * @@ -38,17 +111,31 @@ public function listAll( int $maxRows = 100, array $options = [] ): array { - $response = $this->getFinderService()->searchFinder(FinderService::TYPE_VAT_CODES, $pattern, $field, $firstRow, $maxRows, $options); + $optionsArrayOfString = array('ArrayOfString' => array()); + + foreach ($options as $key => $value) { + $optionsArrayOfString['ArrayOfString'][] = array($key, $value); + } + + $response = $this->getFinderService()->searchFinder(FinderService::TYPE_VAT_CODES, $pattern, $field, $firstRow, $maxRows, $optionsArrayOfString); if ($response->data->TotalRows == 0) { return []; } $vatCodes = []; + foreach ($response->data->Items->ArrayOfString as $vatCodeArray) { $vatCode = new VatCode(); - $vatCode->setCode($vatCodeArray->string[0]); - $vatCode->setName($vatCodeArray->string[1]); + + if (isset($vatCodeArray->string[0])) { + $vatCode->setCode($vatCodeArray->string[0]); + $vatCode->setName($vatCodeArray->string[1]); + } else { + $vatCode->setCode($vatCodeArray[0]); + $vatCode->setName($vatCodeArray[1]); + } + $vatCodes[] = $vatCode; } diff --git a/src/DomDocuments/VatCodesDocument.php b/src/DomDocuments/VatCodesDocument.php new file mode 100644 index 00000000..2f560d52 --- /dev/null +++ b/src/DomDocuments/VatCodesDocument.php @@ -0,0 +1,164 @@ +, based on ArticlesDocument by Willem van de Sande + */ +class VatCodesDocument extends \DOMDocument +{ + /** + * Holds the element + * that all additional elements should be a child of + * @var \DOMElement + */ + private $vatCodeElement; + + /** + * Creates the element and adds it to the property + * vatCodeElement + * + * @access public + */ + public function __construct() + { + parent::__construct(); + + $this->vatCodeElement = $this->createElement('vat'); + $this->appendChild($this->vatCodeElement); + } + + /** + * Turns a passed VatCode class into the required markup for interacting + * with Twinfield. + * + * This method doesn't return anything, instead just adds the VatCode to + * this DOMDOcument instance for submission usage. + * + * @access public + * @param VatCode $vatCode + * @return void | [Adds to this instance] + */ + public function addVatCode(VatCode $vatCode) + { + $rootElement = $this->vatCodeElement; + + $status = $vatCode->getStatus(); + + if (!empty($status)) { + $rootElement->setAttribute('status', $status); + } + + // VatCode elements and their methods + $vatCodeTags = array( + 'code' => 'getCode', + 'name' => 'getName', + 'shortname' => 'getShortName', + 'type' => 'getType', + ); + + // Go through each VatCode element and use the assigned method + foreach ($vatCodeTags as $tag => $method) { + // Make text node for method value + $nodeValue = $vatCode->$method(); + if (is_bool($nodeValue)) { + $nodeValue = ($nodeValue) ? 'true' : 'false'; + } + $node = $this->createTextNode($nodeValue); + + // Make the actual element and assign the node + $element = $this->createElement($tag); + $element->appendChild($node); + + // Add the full element + $rootElement->appendChild($element); + } + + $percentages = $vatCode->getPercentages(); + + if (!empty($percentages)) { + // Make percentages element + $percentagesElement = $this->createElement('percentages'); + $this->vatCodeElement->appendChild($percentagesElement); + + // Element tags and their methods for percentages + $percentageTags = [ + 'date' => 'getDate', + 'name' => 'getName', + 'percentage' => 'getPercentage', + 'shortname' => 'getShortName', + ]; + + // Go through each percentage assigned to the vatCode + foreach ($percentages as $percentage) { + // Makes new VatCodePercentage element + $percentageElement = $this->createElement('percentage'); + $percentagesElement->appendChild($percentageElement); + + // Go through each percentage element and use the assigned method + foreach ($percentageTags as $tag => $method) { + // Make the text node for the method value + $node = $this->createTextNode($percentage->$method()); + + // Make the actual element and assign the text node + $element = $this->createElement($tag); + $element->appendChild($node); + + // Add the completed element + $percentageElement->appendChild($element); + } + + $accounts = $percentage->getAccounts(); + + if (!empty($accounts)) { + // Make addresses element + $accountsElement = $this->createElement('accounts'); + $percentageElement->appendChild($accountsElement); + + // Element tags and their methods for accounts + $accountTags = [ + 'dim1' => 'getDim1', + 'group' => 'getGroup', + 'groupcountry' => 'getGroupCountry', + 'linetype' => 'getLineType', + 'percentage' => 'getPercentage', + ]; + + // Go through each account assigned to the percentage + foreach ($accounts as $account) { + // Makes new VatCodeAccount element + $accountElement = $this->createElement('account'); + $accountsElement->appendChild($accountElement); + + $id = $account->getID(); + + if (!empty($id)) { + $accountElement->setAttribute('id', $id); + } + + // Go through each account element and use the assigned method + foreach ($accountTags as $tag => $method) { + // Make the text node for the method value + $node = $this->createTextNode($account->$method()); + + // Make the actual element and assign the text node + $element = $this->createElement($tag); + $element->appendChild($node); + + // Add the completed element + $accountElement->appendChild($element); + } + } + } + } + } + } +} diff --git a/src/Mappers/VatCodeMapper.php b/src/Mappers/VatCodeMapper.php new file mode 100644 index 00000000..aaaa70e4 --- /dev/null +++ b/src/Mappers/VatCodeMapper.php @@ -0,0 +1,146 @@ +, based on ArticleMapper by Willem van de Sande + */ +class VatCodeMapper extends BaseMapper +{ + + /** + * Maps a Response object to a clean VatCode entity. + * + * @access public + * + * @param \PhpTwinfield\Response\Response $response + * + * @return VatCode + * @throws \PhpTwinfield\Exception + */ + public static function map(Response $response) + { + // Generate new VatCode object + $vatcode = new VatCode(); + + // Gets the raw DOMDocument response. + $responseDOM = $response->getResponseDocument(); + $vatcodeElement = $responseDOM->documentElement; + + // Set the result and status attribute + $vatcode->setResult($vatcodeElement->getAttribute('result')); + $vatcode->setStatus($vatcodeElement->getAttribute('status')); + + // VatCode elements and their methods + $vatcodeTags = array( + 'code' => 'setCode', + 'created' => 'setCreated', + 'modified' => 'setModified', + 'name' => 'setName', + 'shortname' => 'setShortName', + 'touched' => 'setTouched', + 'type' => 'setType', + 'uid' => 'setUID', + 'user' => 'setUser', + ); + + // Loop through all the tags + foreach ($vatcodeTags as $tag => $method) { + self::setFromTagValue($responseDOM, $tag, [$vatcode, $method]); + } + + $percentagesDOMTag = $responseDOM->getElementsByTagName('percentages'); + + if (isset($percentagesDOMTag) && $percentagesDOMTag->length > 0) { + // Element tags and their methods for percentages + $percentageTags = [ + 'date' => 'setDate', + 'name' => 'setName', + 'percentage' => 'setPercentage', + 'shortname' => 'setShortName', + ]; + + $percentagesDOM = $percentagesDOMTag->item(0); + + // Loop through each returned percentage for the vatcode + foreach ($percentagesDOM->childNodes as $percentageDOM) { + if ($percentageDOM->nodeType !== 1) { + continue; + } + + // Make a new tempory VatCodePercentage class + $vatcodePercentage = new VatCodePercentage(); + + // Loop through the element tags. Determine if it exists and set it if it does + foreach ($percentageTags as $tag => $method) { + // Get the dom element + $_tag = $percentageDOM->getElementsByTagName($tag)->item(0); + + // Check if the tag is set, and its content is set, to prevent DOMNode errors + if (isset($_tag) && isset($_tag->textContent)) { + $vatcodePercentage->$method($_tag->textContent); + } + } + + $accountsDOMTag = $percentageDOM->getElementsByTagName('accounts'); + + if (isset($accountsDOMTag) && $accountsDOMTag->length > 0) { + // Element tags and their methods for accounts + $accountTags = [ + 'dim1' => 'setDim1', + 'group' => 'setGroup', + 'groupcountry' => 'setGroupCountry', + 'linetype' => 'setLineType', + 'percentage' => 'setPercentage', + ]; + + $accountsDOM = $accountsDOMTag->item(0); + + // Loop through each returned account for the percentage + foreach ($accountsDOM->childNodes as $accountDOM) { + if ($accountDOM->nodeType !== 1) { + continue; + } + + // Make a new tempory VatCodeAccount class + $vatcodeAccount = new VatCodeAccount(); + $vatcodeAccount->setID($accountDOM->getAttribute('id')); + + // Loop through the element tags. Determine if it exists and set it if it does + foreach ($accountTags as $tag => $method) { + // Get the dom element + $_tag = $accountDOM->getElementsByTagName($tag)->item(0); + + // Check if the tag is set, and its content is set, to prevent DOMNode errors + if (isset($_tag) && isset($_tag->textContent)) { + $vatcodeAccount->$method($_tag->textContent); + } + } + + // Add the account to the percentage + $vatcodePercentage->addAccount($vatcodeAccount); + + // Clean that memory! + unset ($vatcodeAccount); + } + } + + // Add the percentage to the vat code + $vatcode->addPercentage($vatcodePercentage); + + // Clean that memory! + unset ($vatcodePercentage); + } + } + + return $vatcode; + } +} diff --git a/src/Request/Read/VatCode.php b/src/Request/Read/VatCode.php new file mode 100644 index 00000000..4ff15102 --- /dev/null +++ b/src/Request/Read/VatCode.php @@ -0,0 +1,57 @@ +, based on Article by Willem van de Sande + * @version 0.0.1 + */ +class VatCode extends Read +{ + /** + * Sets office and code if they are present. + * + * @access public + */ + public function __construct($office = null, $code = null) + { + parent::__construct(); + + if (null !== $office) { + $this->setOffice($office); + } + + if (null !== $code) { + $this->setCode($code); + } + } + + /** + * Sets the office code for this VatCode request. + * + * @access public + * @param int $office + * @return \PhpTwinfield\Request\Read\VatCode + */ + public function setOffice($office) + { + $this->add('office', $office); + return $this; + } + + /** + * Sets the code for this VatCode request. + * + * @access public + * @param string $code + * @return \PhpTwinfield\Request\Read\VatCode + */ + public function setCode($code) + { + $this->add('code', $code); + return $this; + } +} diff --git a/src/VatCode.php b/src/VatCode.php index 61051d2c..2d3b8eda 100644 --- a/src/VatCode.php +++ b/src/VatCode.php @@ -5,37 +5,144 @@ /** * Class VatCode * - * @author Emile Bons + * @author Emile Bons , extended by Yannick Aerssens */ -class VatCode +class VatCode extends BaseObject { - /** - * @var string The code of the VAT code. - */ - private $code; - /** - * @var string The name of the VAT code. - */ + private $code; + private $created; + private $modified; private $name; + private $shortName; + private $status; + private $touched; + private $type; + private $uid; + private $user; + private $percentages = []; - public function getCode(): string + public function getCode() { return $this->code; } - public function setCode(string $code): void + public function setCode($code) { $this->code = $code; } - public function getName(): string + public function getCreated() + { + return $this->created; + } + + public function setCreated($created) + { + $this->created = $created; + } + + public function getModified() + { + return $this->modified; + } + + public function setModified($modified) + { + $this->modified = $modified; + } + + public function getName() { return $this->name; } - public function setName(string $name): void + public function setName($name) { $this->name = $name; } + + public function getShortName() + { + return $this->shortName; + } + + public function setShortName($shortName) + { + $this->shortName = $shortName; + } + + public function getStatus() + { + return $this->status; + } + + public function setStatus($status) + { + $this->status = $status; + return $this; + } + + public function getTouched() + { + return $this->touched; + } + + public function setTouched($touched) + { + $this->touched = $touched; + return $this; + } + + public function getType() + { + return $this->type; + } + + public function setType($type) + { + $this->type = $type; + return $this; + } + + public function getUID() + { + return $this->uid; + } + + public function setUID($uid) + { + $this->uid = $uid; + } + + public function getUser() + { + return $this->user; + } + + public function setUser($user) + { + $this->user = $user; + } + + public function getPercentages() + { + return $this->percentages; + } + + public function addPercentage(VatCodePercentage $percentage) + { + $this->percentages[] = $percentage; + return $this; + } + + public function removePercentage($index) + { + if (array_key_exists($index, $this->percentages)) { + unset($this->percentages[$index]); + return true; + } else { + return false; + } + } } diff --git a/src/VatCodeAccount.php b/src/VatCodeAccount.php new file mode 100644 index 00000000..22b87258 --- /dev/null +++ b/src/VatCodeAccount.php @@ -0,0 +1,88 @@ +ID = uniqid(); + } + + public function getID() + { + return $this->ID; + } + + public function setID($ID) + { + $this->ID = $ID; + return $this; + } + + public function getDim1() + { + return $this->dim1; + } + + public function setDim1($dim1) + { + $this->dim1 = $dim1; + return $this; + } + + public function getGroupCountry() + { + return $this->groupcountry; + } + + public function setGroupCountry($groupcountry) + { + $this->groupcountry = $groupcountry; + return $this; + } + + public function getGroup() + { + return $this->group; + } + + public function setGroup($group) + { + $this->group = $group; + return $this; + } + + public function getPercentage() + { + return $this->percentage; + } + + public function setPercentage($percentage) + { + $this->percentage = $percentage; + return $this; + } + + public function getLineType() + { + return $this->linetype; + } + + public function setLineType($linetype) + { + $this->linetype = $linetype; + return $this; + } +} diff --git a/src/VatCodePercentage.php b/src/VatCodePercentage.php new file mode 100644 index 00000000..a3a528fb --- /dev/null +++ b/src/VatCodePercentage.php @@ -0,0 +1,81 @@ +date; + } + + public function setDate($date) + { + $this->date = $date; + return $this; + } + + public function getPercentage() + { + return $this->percentage; + } + + public function setPercentage($percentage) + { + $this->percentage = $percentage; + return $this; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = $name; + return $this; + } + + public function getShortName() + { + return $this->shortName; + } + + public function setShortName($shortName) + { + $this->shortName = $shortName; + return $this; + } + + public function getAccounts() + { + return $this->accounts; + } + + public function addAccount(VatCodeAccount $account) + { + $this->accounts[$account->getID()] = $account; + return $this; + } + + public function removeAccount($index) + { + if (array_key_exists($index, $this->accounts)) { + unset($this->accounts[$index]); + return true; + } else { + return false; + } + } +}