Skip to content

Commit

Permalink
Version 2.12.7
Browse files Browse the repository at this point in the history
  • Loading branch information
eclipxe13 committed Dec 4, 2019
2 parents 10589f7 + 01156e9 commit d05189b
Show file tree
Hide file tree
Showing 20 changed files with 290 additions and 44 deletions.
33 changes: 20 additions & 13 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ environment:
- php: 7.1
- php: 7.2
- php: 7.3
- php: 7.4

init:
- SET PATH=c:\tools\php;C:\tools\composer;C:\OpenSSL-v111-Win64\bin;%PATH%
- SET COMPOSER_NO_INTERACTION=1
- SET ANSICON="121x90 (121x90)"
- SET saxonb-path=C:\ProgramData\chocolatey\bin\SaxonHE\bin\Transform.exe
- SET PHP_CS_FIXER_FUTURE_MODE=1
- SET PHP_CS_FIXER_IGNORE_ENV=1

## Check for openssl, install php using version environment, install
install:
# downgrade chocolatey to 0.10.13, otherwise versions query are not working
# see https://github.com/chocolatey/choco/issues/1843
- choco install chocolatey --yes --version 0.10.13 --allow-downgrade --no-progress --force
# check chocolatey sources and version
- choco source list
# check openssl exists and run from PATH
Expand All @@ -35,7 +41,7 @@ install:
- ps: |
Write-Host "PHP build version: $Env:php"
# Get current version of php (if any)
$current_version = ""
[string]$current_version = ""
if (Test-Path c:\tools\php\php.exe) {
[string]$current_version = php -r "printf('%s.%s.%s', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION);"
Write-Host "PHP current version: $current_version"
Expand All @@ -44,44 +50,45 @@ install:
}
# Get latest available version for php environment variable
$php_install_version = (( `
choco search php --all-versions --limit-output `
[string]$php_install_version = (( `
choco search php --exact --all-versions --limit-output `
| Select-String -Pattern "php|$Env:php" -SimpleMatch `
| Sort-Object { [version]($_ -Split '\|' | Select-Object -Last 1) } -Descending `
| Select-Object -First 1 `
) -Replace '[php|]', '')
Write-Host "PHP available version: $php_install_version"
if ($php_install_version -eq "") {
Write-Host "Unable to find a chocolatey php package version for PHP $env:php"
choco search php --all-versions --limit-output | Select-String -Pattern "php|$Env:php" -SimpleMatch
choco search php --exact --all-versions --limit-output | Select-String -Pattern "php|$Env:php" -SimpleMatch
Exit 1
}
# Test if require installation (not installed or upgrade available)
if (! ($current_version -eq $php_install_version)) {
# uninstall if previous version exists
if (! ($current_version -eq "")) {
choco uninstall php --yes --force --ignore-package-exit-codes --ignore-autouninstaller-failure
choco uninstall php --yes --force --ignore-package-exit-codes --ignore-autouninstaller-failure --no-progress
}
# install php on C:\tools\php
appveyor-retry choco install --ignore-checksums --params='""/InstallDir:C:\tools\php""' `
php --version $php_install_version --yes
php --version $php_install_version --yes --no-progress
}
# setup c:\tools\php\php.ini
if (Test-Path c:\tools\php\php.ini-production) {
Copy-Item -Path c:\tools\php\php.ini-production -Destination c:\tools\php\php.ini
[string]$php_ext_prefix=$(if ($Env:php -lt "7.2") {"php_"} else {""})
Add-Content c:\tools\php\php.ini "`
`n; PHP Custom config `
date.timezone=UTC `
extension_dir=ext `
memory_limit=1G `
extension=php_openssl `
extension=php_mbstring `
extension=php_fileinfo `
extension=php_curl `
extension=php_xsl `
extension=php_soap `
extension=${php_ext_prefix}openssl `
extension=${php_ext_prefix}mbstring `
extension=${php_ext_prefix}fileinfo `
extension=${php_ext_prefix}curl `
extension=${php_ext_prefix}xsl `
extension=${php_ext_prefix}soap `
"
}
Expand All @@ -104,7 +111,7 @@ install:
# saxonb
- ps: |
if (! (Test-Path ${Env:saxonb-path})) {
appveyor-retry choco install --ignore-checksums --yes saxonhe
appveyor-retry choco install --ignore-checksums --yes saxonhe --no-progress
}
# install project dependences and list available tools
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ php:
- "7.1"
- "7.2"
- "7.3"
- "7.4snapshot"
- "7.4"

matrix:
allow_failures:
- php: "7.4snapshot"
- php: "7.4"

branches:
except:
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ This library is compatible with PHP versions 7.0 and above.
Please, try to use the full potential of the language like type declarations.

The intented support is to be aligned with oldest *Active support* PHP Branch.
See <http://php.net/supported-versions.php> for more details.
See <https://www.php.net/supported-versions.php> for more details.


## Contributing
Expand Down Expand Up @@ -100,13 +100,13 @@ and licensed for use under the MIT License (MIT). Please see [LICENSE][] for mor
[coverage]: https://scrutinizer-ci.com/g/eclipxe13/CfdiUtils/code-structure/master/code-coverage/src/CfdiUtils/
[downloads]: https://packagist.org/packages/eclipxe/CfdiUtils

[badge-source]: http://img.shields.io/badge/source-eclipxe13/CfdiUtils-blue?logo=github&style=flat-square
[badge-source]: https://img.shields.io/badge/source-eclipxe13/CfdiUtils-blue?logo=github&style=flat-square
[badge-documentation]: https://img.shields.io/readthedocs/cfdiutils/stable?logo=read-the-docs&style=flat-square
[badge-discord]: https://img.shields.io/discord/459860554090283019?logo=discord&style=flat-square
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?style=flat-square
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?style=flat-square
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?logo=git&style=flat-square
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?logo=open-source-initiative&style=flat-square
[badge-build]: https://img.shields.io/travis/eclipxe13/CfdiUtils/master?logo=travis&style=flat-square
[badge-appveyor]: https://img.shields.io/appveyor/ci/eclipxe13/cfdiutils/master?logo=appveyor&style=flat-square
[badge-quality]: https://img.shields.io/scrutinizer/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
[badge-coverage]: https://img.shields.io/scrutinizer/coverage/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?logo=composer&style=flat-square
17 changes: 17 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@
- Change visibility of `CfdiUtils\Cleaner\Cleaner#removeIncompleteSchemaLocation()` to private.


## Version 2.12.7 2019-12-04

- Add 2 new default cleans, before loading the CFDI as XML DOM Document:
- Change invalid `xmlns:schemaLocation` to `xsi:schemaLocation`. SAT uses to create *"valid"* CFDI with this error.
- Remove `xmlns="http://www.sat.gob.mx/cfd/3"` when also `xmlns:cfdi="http://www.sat.gob.mx/cfd/3"` is found.
- Improve `SerialNumber` to use `map + impode` instead of concatenation.
- Improve `SerialNumber` to `substr` instead of `strpos` to check if a string start with text.
- (DOC) Add cleaner notes and example about clean before load.
- (DOC) Simplify example on `RequestParameters` usage.
- (DEV) Add support for PHP 7.4 on Travis-CI
- (DEV) Add support for PHP 7.4 on AppVeyor
- Downgrade `chocolatey` to 0.10.13
- Add `--no-progress` to `choco` commands
- Setup extensions declared without prefix `php_` on PHP versions lower than 7.2
- Add `PHP_CS_FIXER` environment variables


## Version 2.12.6 2019-10-23

- Fix `REGFIS01` validation when receiving an RFC with non-ASCII chars (like `Ñ`).
Expand Down
11 changes: 1 addition & 10 deletions docs/crear/crear-cfdi.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,7 @@ Este es un ejemplo para la obtener la URL directamente de un contenido XML.
```php
$xmlContents = '<cfdi:Comprobante Version="3.3">...</cfdi:Comprobante>';
$cfdi = \CfdiUtils\Cfdi::newFromString($xmlContents);
$comprobante = $cfdi->getNode(); // Nodo de trabajo del nodo cfdi:Comprobante

$parameters = new RequestParameters(
$comprobante['Version'],
$comprobante->searchAttribute('cfdi:Emisor', 'Rfc'),
$comprobante->searchAttribute('cfdi:Receptor', 'Rfc'),
$comprobante['Total'],
$comprobante->searchAttribute('cfdi:Complemento', 'tfd:TimbreFiscalDigital', 'UUID'),
$comprobante['Sello']
);
$parameters = \CfdiUtils\ConsultaCfdiSat\RequestParameters::createFromCfdi($cfdi);

echo $parameters->expression(); // https://verificacfdi.facturaelectronica.sat.gob.mx/...
```
Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ Consulte el archivo [LICENSE][] para más información.
[badge-source]: http://img.shields.io/badge/source-eclipxe13/CfdiUtils-blue?logo=github&style=flat-square
[badge-documentation]: https://img.shields.io/readthedocs/cfdiutils/stable?logo=read-the-docs&style=flat-square
[badge-discord]: https://img.shields.io/discord/459860554090283019?logo=discord&style=flat-square
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?style=flat-square
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?style=flat-square
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?logo=git&style=flat-square
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?logo=open-source-initiative&style=flat-square
[badge-build]: https://img.shields.io/travis/eclipxe13/CfdiUtils/master?logo=travis&style=flat-square
[badge-appveyor]: https://img.shields.io/appveyor/ci/eclipxe13/cfdiutils/master?logo=appveyor&style=flat-square
[badge-quality]: https://img.shields.io/scrutinizer/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
[badge-coverage]: https://img.shields.io/scrutinizer/coverage/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?logo=composer&style=flat-square
32 changes: 31 additions & 1 deletion docs/leer/limpieza-cfdi.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,30 @@ Estos errores comunes terminan en un error de validación.
Para evitar estos errores se puede usar el objeto `CfdiUtils\Cleaner\Cleaner`.
Este objeto requiere una cadena de texto con XML válido. Y limpia el XML siguiendo estos pasos:

1. Cambiar la defición incorrecta en algunos CFDI del SAT `xmlns:schemaLocation` por `xsi:schemaLocation`.
1. Remover la definición de CFDI 3 si no tiene prefijo `xmlns="http://www.sat.gob.mx/cfd/3"` siempre que la definición
con prefijo `xmlns:cfdi="http://www.sat.gob.mx/cfd/3"` sí esté presente.
1. Remueve el nodo `cfdi:Addenda`.
1. Remueve dentro de las locaciones de espacios de nombre `xsi:schemaLocation` los namespaces que no tengan
a continuación una uri que termine en `.xsd`.
a continuación una uri que termine en `.xsd`.
1. Remueve todos los nodos que no tengan relación con el SAT (los que no contengan `http://www.sat.gob.mx/`).
1. Remueve todos los pares de espacio de nombre y archivo xsd de los `xsi:schemaLocation` que no tengan relación con el SAT.
1. Remueve todos los espacios de nombres listados que no están en uso.
1. Colapsa los nodos `cfdi:Complemento` en uno solo, respetando el mismo orden de aparición para que se genere
exactamente la misma cadena de origen.

Las primeras dos formas no trabajan con el CFDI como XML, lo trabajan como una cadena de texto.

La forma rápida de usar el limpiador es usando el método estático
`CfdiUtils\Cleaner\Cleaner::staticClean(string $content): string`
que recibe el XML sucio y devuelve el XML limpio.

```php
<?php
$possibleDirty = '... el xml del cfdi ...';
$cleanContent = CfdiUtils\Cleaner\Cleaner::staticClean($possibleDirty);
```

También se puede instanciar un objeto de la clase `CfdiUtils\Cleaner\Cleaner` y usar estos métodos:

- `load(string $content)`: Carga un contenido XML "sucio"
Expand All @@ -47,3 +58,22 @@ También se puede instanciar un objeto de la clase `CfdiUtils\Cleaner\Cleaner` y

Si deseas implementar tu propio orden, hacer o agregar nuevos limpiadores puedes extender la clase o sobrescribir
el método `clean` o bien llamar a cada uno de los pasos de limpieza por tu propia cuenta.

De querer saltar las dos limpiezas previas a la carga del XML, es necesario construir el objeto `Cleaner`
pasando un objeto de tipo `BeforeLoadCleanerInterface` que no haga ninguna limpieza, por ejemplo:

```php
<?php
$content = '... el xml del cfdi ...';

// objeto que no hace limpieza implementando el patrón de diseño NULL
$nullBeforeLoadCleaner = new class () implements CfdiUtils\Cleaner\BeforeLoad\BeforeLoadCleanerInterface {
public function clean(string $content): string {
return $content;
}
};

$cleaner = new CfdiUtils\Cleaner\Cleaner($content, $nullBeforeLoadCleaner);
$cleaner->clean();
$content = $cleaner->retrieveXml();
```
14 changes: 7 additions & 7 deletions src/CfdiUtils/Certificado/SerialNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function loadHexadecimal(string $hexString)

public function loadDecimal(string $decString)
{
if (0 === strpos($decString, '0x') || 0 === strpos($decString, '0X')) {
if (0 === strcasecmp('0x', substr($decString, 0, 2))) {
$hexString = substr($decString, 2);
} else {
$hexString = BaseConverter::createBase36()->convert($decString, 10, 16);
Expand Down Expand Up @@ -59,16 +59,16 @@ public function asDecimal(): string

protected function hexToAscii(string $input): string
{
return array_reduce(str_split($input, 2), function (string $carry, string $value): string {
return $carry . chr(intval(hexdec($value)));
}, '');
return implode('', array_map(function (string $value): string {
return chr(intval(hexdec($value)));
}, str_split($input, 2)));
}

protected function asciiToHex(string $input): string
{
return array_reduce(str_split($input, 1), function (string $carry, string $value): string {
return $carry . dechex(ord($value));
}, '');
return implode('', array_map(function (string $value): string {
return dechex(ord($value));
}, str_split($input, 1)));
}

/**
Expand Down
40 changes: 40 additions & 0 deletions src/CfdiUtils/Cleaner/BeforeLoad/BeforeLoadCleaner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace CfdiUtils\Cleaner\BeforeLoad;

class BeforeLoadCleaner implements BeforeLoadCleanerInterface
{
/** @var BeforeLoadCleanerInterface[] */
private $cleaners;

public function __construct(BeforeLoadCleanerInterface ...$cleaners)
{
if ([] === $cleaners) {
$cleaners = $this->defaultCleaners();
}
$this->cleaners = $cleaners;
}

/** @return BeforeLoadCleanerInterface[] */
public static function defaultCleaners(): array
{
return [
new ChangeXmlnsSchemaLocation(),
new RemoveDuplicatedCfdi3Namespace(),
];
}

/** @return BeforeLoadCleanerInterface[] */
public function members(): array
{
return $this->cleaners;
}

public function clean(string $content): string
{
foreach ($this->cleaners as $cleaner) {
$content = $cleaner->clean($content);
}
return $content;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace CfdiUtils\Cleaner\BeforeLoad;

interface BeforeLoadCleanerInterface
{
public function clean(string $content): string;
}
11 changes: 11 additions & 0 deletions src/CfdiUtils/Cleaner/BeforeLoad/ChangeXmlnsSchemaLocation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace CfdiUtils\Cleaner\BeforeLoad;

class ChangeXmlnsSchemaLocation implements BeforeLoadCleanerInterface
{
public function clean(string $content): string
{
return str_replace(' xmlns:schemaLocation="', ' xsi:schemaLocation="', $content);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace CfdiUtils\Cleaner\BeforeLoad;

class RemoveDuplicatedCfdi3Namespace implements BeforeLoadCleanerInterface
{
public function clean(string $content): string
{
if (false !== strpos($content, ' xmlns="http://www.sat.gob.mx/cfd/3"')
&& false !== strpos($content, ' xmlns:cfdi="http://www.sat.gob.mx/cfd/3"')) {
$content = str_replace(' xmlns="http://www.sat.gob.mx/cfd/3"', '', $content);
}
return $content;
}
}
8 changes: 7 additions & 1 deletion src/CfdiUtils/Cleaner/Cleaner.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace CfdiUtils\Cleaner;

use CfdiUtils\Cfdi;
use CfdiUtils\Cleaner\BeforeLoad\BeforeLoadCleanerInterface;
use CfdiUtils\Utils\SchemaLocations;
use CfdiUtils\Utils\Xml;
use DOMAttr;
Expand All @@ -27,8 +28,12 @@ class Cleaner
/** @var DOMDocument|null */
protected $dom;

public function __construct(string $content)
/** @var BeforeLoadCleanerInterface */
private $beforeLoadCleaner;

public function __construct(string $content, BeforeLoadCleanerInterface $beforeLoadCleaner = null)
{
$this->beforeLoadCleaner = $beforeLoadCleaner ?? new BeforeLoad\BeforeLoadCleaner();
if ('' !== $content) {
$this->load($content);
}
Expand Down Expand Up @@ -104,6 +109,7 @@ public function clean()
public function load(string $content)
{
try {
$content = $this->beforeLoadCleaner->clean($content);
$cfdi = Cfdi::newFromString($content);
} catch (\Throwable $exception) {
throw new CleanerException($exception->getMessage(), $exception->getCode(), $exception->getPrevious());
Expand Down
Loading

0 comments on commit d05189b

Please sign in to comment.