toutpratique/_install/dev/update_eu_taxrulegroups.php
Thibault GUILLAUME 58a8203ae2 prestashop v1
2015-07-06 16:58:50 +02:00

217 lines
5.6 KiB
PHP

<?php
/**
* This script will update the tax rule groups for virtual products from all EU localization packs.
* All it needs is that the correct tax in each localization pack is marked with `eu-tax-group="virtual"`.
*
* Usage: just execute this script.
*
*
* 1)
* Parse all files under /localization,
* looking for <tax> elements that have the attribute eu-tax-group="virtual".
*
* Store the list of files (`$euLocalizationFiles`) where such taxes have been found,
* in a next step we'll store the new tax group in each of them.
*
* 2)
* Remove all taxRulesGroup's that have the attribute eu-tax-group="virtual".
*
* 3)
* Build a new taxRulesGroup containing all the taxes found in the first step.
*
* 4)
* Inject the new taxRulesGroup into all packs of `$euLocalizationFiles`, not forgetting
* to also inject the required taxes.
*
* Warning: do not duplicate the tax with attribute eu-tax-group="virtual" of the pack being updated.
*
* Mark the injected group with the attributes eu-tax-group="virtual" and auto-generated="1"
* Mark the injected taxes witth the attributes from-eu-tax-group="virtual" and auto-generated="1"
*
* Clean things up by removing all the previous taxes that had the attributes eu-tax-group="virtual" and auto-generated="1"
*/
@ini_set('display_errors', 'on');
$localizationPacksRoot = realpath(dirname(__FILE__) . '/../../localization');
if (!$localizationPacksRoot)
{
die("Could not find the folder containing the localization files (should be 'localization' at the root of the PrestaShop folder).\n");
}
$euLocalizationFiles = array();
foreach (scandir($localizationPacksRoot) as $entry)
{
if (!preg_match('/\.xml$/', $entry))
{
continue;
}
$localizationPackFile = $localizationPacksRoot . DIRECTORY_SEPARATOR . $entry;
$localizationPack = simplexml_load_file($localizationPackFile);
// Some packs do not have taxes
if (!$localizationPack->taxes->tax)
{
continue;
}
foreach ($localizationPack->taxes->tax as $tax)
{
if ((string)$tax['eu-tax-group'] === 'virtual')
{
if (!isset($euLocalizationFiles[$localizationPackFile]))
{
$euLocalizationFiles[$localizationPackFile] = array(
'virtualTax' => $tax,
'pack' => $localizationPack,
'iso_code_country' => basename($entry, '.xml')
);
}
else
{
die("Too many taxes with eu-tax-group=\"virtual\" found in `$localizationPackFile`.\n");
}
}
}
}
function addTax(SimpleXMLElement $taxes, SimpleXMLElement $tax, array $attributesToUpdate = array(), array $attributesToRemove = array())
{
$newTax = new SimpleXMLElement('<tax/>');
$insertBefore = $taxes->xpath('//taxRulesGroup[1]')[0];
if (!$insertBefore)
{
die("Could not find any `taxRulesGroup`, don't know where to append the tax.\n");
}
/**
* Add the `tax` node before the first `taxRulesGroup`.
* Yes, the dom API is beautiful.
*/
$dom = dom_import_simplexml($taxes);
$new = $dom->insertBefore(
$dom->ownerDocument->importNode(dom_import_simplexml($newTax)),
dom_import_simplexml($insertBefore)
);
$newTax = simplexml_import_dom($new);
$newAttributes = array();
foreach ($tax->attributes() as $attribute)
{
$name = $attribute->getName();
// This attribute seems to cause trouble, skip it.
if ($name === 'account_number' || in_array($name, $attributesToRemove))
{
continue;
}
$value = (string)$attribute;
$newAttributes[$name] = $value;
}
$newAttributes = array_merge($newAttributes, $attributesToUpdate);
foreach ($newAttributes as $name => $value)
{
$newTax->addAttribute($name, $value);
}
return $newTax;
}
function addTaxRule(SimpleXMLElement $taxRulesGroup, SimpleXMLElement $tax, $iso_code_country)
{
$taxRule = $taxRulesGroup->addChild('taxRule');
$taxRule->addAttribute('iso_code_country', $iso_code_country);
$taxRule->addAttribute('id_tax', (string)$tax['id']);
return $taxRule;
}
foreach ($euLocalizationFiles as $path => $file)
{
$nodesToKill = array();
// Get max tax id, and list of nodes to kill
$taxId = 0;
foreach ($file['pack']->taxes->tax as $tax)
{
if ((string)$tax['auto-generated'] === "1" && (string)$tax['from-eu-tax-group'] === 'virtual')
{
$nodesToKill[] = $tax;
}
else
{
// We only count the ids of the taxes we're not going to remove!
$taxId = max($taxId, (int)$tax['id']);
}
}
foreach ($file['pack']->taxes->taxRulesGroup as $trg)
{
if ((string)$trg['auto-generated'] === "1" && (string)$trg['eu-tax-group'] === 'virtual')
{
$nodesToKill[] = $trg;
}
}
// This is the first tax id we're allowed to use.
$taxId++;
// Prepare new taxRulesGroup
$taxRulesGroup = $file['pack']->taxes->addChild('taxRulesGroup');
$taxRulesGroup->addAttribute('name', 'EU VAT For Virtual Products');
$taxRulesGroup->addAttribute('auto-generated', '1');
$taxRulesGroup->addAttribute('eu-tax-group', 'virtual');
addTaxRule($taxRulesGroup, $file['virtualTax'], $file['iso_code_country']);
foreach ($euLocalizationFiles as $foreignPath => $foreignFile)
{
if ($foreignPath === $path)
{
// We already added the tax that belongs to this pack
continue;
}
$tax = addTax($file['pack']->taxes, $foreignFile['virtualTax'], array(
'id' => (string)$taxId,
'auto-generated' => '1',
'from-eu-tax-group' => 'virtual'
), array('eu-tax-group'));
addTaxRule($taxRulesGroup, $tax, $foreignFile['iso_code_country']);
$taxId++;
}
foreach ($nodesToKill as $node)
{
unset($node[0]);
}
$dom = new DOMDocument("1.0");
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($file['pack']->asXML());
file_put_contents($path, $dom->saveXML());
}
$nUpdated = count($euLocalizationFiles);
echo "Updated the virtual tax groups for $nUpdated localization files.\n";