Skip to content

Commit d05189b

Browse files
committed
Version 2.12.7
2 parents 10589f7 + 01156e9 commit d05189b

20 files changed

+290
-44
lines changed

.appveyor.yml

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,21 @@ environment:
1818
- php: 7.1
1919
- php: 7.2
2020
- php: 7.3
21+
- php: 7.4
2122

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

2831
## Check for openssl, install php using version environment, install
2932
install:
33+
# downgrade chocolatey to 0.10.13, otherwise versions query are not working
34+
# see https://github.com/chocolatey/choco/issues/1843
35+
- choco install chocolatey --yes --version 0.10.13 --allow-downgrade --no-progress --force
3036
# check chocolatey sources and version
3137
- choco source list
3238
# check openssl exists and run from PATH
@@ -35,7 +41,7 @@ install:
3541
- ps: |
3642
Write-Host "PHP build version: $Env:php"
3743
# Get current version of php (if any)
38-
$current_version = ""
44+
[string]$current_version = ""
3945
if (Test-Path c:\tools\php\php.exe) {
4046
[string]$current_version = php -r "printf('%s.%s.%s', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION);"
4147
Write-Host "PHP current version: $current_version"
@@ -44,44 +50,45 @@ install:
4450
}
4551
4652
# Get latest available version for php environment variable
47-
$php_install_version = (( `
48-
choco search php --all-versions --limit-output `
53+
[string]$php_install_version = (( `
54+
choco search php --exact --all-versions --limit-output `
4955
| Select-String -Pattern "php|$Env:php" -SimpleMatch `
5056
| Sort-Object { [version]($_ -Split '\|' | Select-Object -Last 1) } -Descending `
5157
| Select-Object -First 1 `
5258
) -Replace '[php|]', '')
5359
Write-Host "PHP available version: $php_install_version"
5460
if ($php_install_version -eq "") {
5561
Write-Host "Unable to find a chocolatey php package version for PHP $env:php"
56-
choco search php --all-versions --limit-output | Select-String -Pattern "php|$Env:php" -SimpleMatch
62+
choco search php --exact --all-versions --limit-output | Select-String -Pattern "php|$Env:php" -SimpleMatch
5763
Exit 1
5864
}
5965
6066
# Test if require installation (not installed or upgrade available)
6167
if (! ($current_version -eq $php_install_version)) {
6268
# uninstall if previous version exists
6369
if (! ($current_version -eq "")) {
64-
choco uninstall php --yes --force --ignore-package-exit-codes --ignore-autouninstaller-failure
70+
choco uninstall php --yes --force --ignore-package-exit-codes --ignore-autouninstaller-failure --no-progress
6571
}
6672
# install php on C:\tools\php
6773
appveyor-retry choco install --ignore-checksums --params='""/InstallDir:C:\tools\php""' `
68-
php --version $php_install_version --yes
74+
php --version $php_install_version --yes --no-progress
6975
}
7076
7177
# setup c:\tools\php\php.ini
7278
if (Test-Path c:\tools\php\php.ini-production) {
7379
Copy-Item -Path c:\tools\php\php.ini-production -Destination c:\tools\php\php.ini
80+
[string]$php_ext_prefix=$(if ($Env:php -lt "7.2") {"php_"} else {""})
7481
Add-Content c:\tools\php\php.ini "`
7582
`n; PHP Custom config `
7683
date.timezone=UTC `
7784
extension_dir=ext `
7885
memory_limit=1G `
79-
extension=php_openssl `
80-
extension=php_mbstring `
81-
extension=php_fileinfo `
82-
extension=php_curl `
83-
extension=php_xsl `
84-
extension=php_soap `
86+
extension=${php_ext_prefix}openssl `
87+
extension=${php_ext_prefix}mbstring `
88+
extension=${php_ext_prefix}fileinfo `
89+
extension=${php_ext_prefix}curl `
90+
extension=${php_ext_prefix}xsl `
91+
extension=${php_ext_prefix}soap `
8592
"
8693
}
8794
@@ -104,7 +111,7 @@ install:
104111
# saxonb
105112
- ps: |
106113
if (! (Test-Path ${Env:saxonb-path})) {
107-
appveyor-retry choco install --ignore-checksums --yes saxonhe
114+
appveyor-retry choco install --ignore-checksums --yes saxonhe --no-progress
108115
}
109116
110117
# install project dependences and list available tools

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ php:
88
- "7.1"
99
- "7.2"
1010
- "7.3"
11-
- "7.4snapshot"
11+
- "7.4"
1212

1313
matrix:
1414
allow_failures:
15-
- php: "7.4snapshot"
15+
- php: "7.4"
1616

1717
branches:
1818
except:

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ This library is compatible with PHP versions 7.0 and above.
6969
Please, try to use the full potential of the language like type declarations.
7070

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

7474

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

103-
[badge-source]: http://img.shields.io/badge/source-eclipxe13/CfdiUtils-blue?logo=github&style=flat-square
103+
[badge-source]: https://img.shields.io/badge/source-eclipxe13/CfdiUtils-blue?logo=github&style=flat-square
104104
[badge-documentation]: https://img.shields.io/readthedocs/cfdiutils/stable?logo=read-the-docs&style=flat-square
105105
[badge-discord]: https://img.shields.io/discord/459860554090283019?logo=discord&style=flat-square
106-
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?style=flat-square
107-
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?style=flat-square
106+
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?logo=git&style=flat-square
107+
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?logo=open-source-initiative&style=flat-square
108108
[badge-build]: https://img.shields.io/travis/eclipxe13/CfdiUtils/master?logo=travis&style=flat-square
109109
[badge-appveyor]: https://img.shields.io/appveyor/ci/eclipxe13/cfdiutils/master?logo=appveyor&style=flat-square
110110
[badge-quality]: https://img.shields.io/scrutinizer/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
111111
[badge-coverage]: https://img.shields.io/scrutinizer/coverage/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
112-
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?style=flat-square
112+
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?logo=composer&style=flat-square

docs/CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@
2828
- Change visibility of `CfdiUtils\Cleaner\Cleaner#removeIncompleteSchemaLocation()` to private.
2929

3030

31+
## Version 2.12.7 2019-12-04
32+
33+
- Add 2 new default cleans, before loading the CFDI as XML DOM Document:
34+
- Change invalid `xmlns:schemaLocation` to `xsi:schemaLocation`. SAT uses to create *"valid"* CFDI with this error.
35+
- Remove `xmlns="http://www.sat.gob.mx/cfd/3"` when also `xmlns:cfdi="http://www.sat.gob.mx/cfd/3"` is found.
36+
- Improve `SerialNumber` to use `map + impode` instead of concatenation.
37+
- Improve `SerialNumber` to `substr` instead of `strpos` to check if a string start with text.
38+
- (DOC) Add cleaner notes and example about clean before load.
39+
- (DOC) Simplify example on `RequestParameters` usage.
40+
- (DEV) Add support for PHP 7.4 on Travis-CI
41+
- (DEV) Add support for PHP 7.4 on AppVeyor
42+
- Downgrade `chocolatey` to 0.10.13
43+
- Add `--no-progress` to `choco` commands
44+
- Setup extensions declared without prefix `php_` on PHP versions lower than 7.2
45+
- Add `PHP_CS_FIXER` environment variables
46+
47+
3148
## Version 2.12.6 2019-10-23
3249

3350
- Fix `REGFIS01` validation when receiving an RFC with non-ASCII chars (like `Ñ`).

docs/crear/crear-cfdi.md

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,7 @@ Este es un ejemplo para la obtener la URL directamente de un contenido XML.
154154
```php
155155
$xmlContents = '<cfdi:Comprobante Version="3.3">...</cfdi:Comprobante>';
156156
$cfdi = \CfdiUtils\Cfdi::newFromString($xmlContents);
157-
$comprobante = $cfdi->getNode(); // Nodo de trabajo del nodo cfdi:Comprobante
158-
159-
$parameters = new RequestParameters(
160-
$comprobante['Version'],
161-
$comprobante->searchAttribute('cfdi:Emisor', 'Rfc'),
162-
$comprobante->searchAttribute('cfdi:Receptor', 'Rfc'),
163-
$comprobante['Total'],
164-
$comprobante->searchAttribute('cfdi:Complemento', 'tfd:TimbreFiscalDigital', 'UUID'),
165-
$comprobante['Sello']
166-
);
157+
$parameters = \CfdiUtils\ConsultaCfdiSat\RequestParameters::createFromCfdi($cfdi);
167158

168159
echo $parameters->expression(); // https://verificacfdi.facturaelectronica.sat.gob.mx/...
169160
```

docs/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@ Consulte el archivo [LICENSE][] para más información.
125125
[badge-source]: http://img.shields.io/badge/source-eclipxe13/CfdiUtils-blue?logo=github&style=flat-square
126126
[badge-documentation]: https://img.shields.io/readthedocs/cfdiutils/stable?logo=read-the-docs&style=flat-square
127127
[badge-discord]: https://img.shields.io/discord/459860554090283019?logo=discord&style=flat-square
128-
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?style=flat-square
129-
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?style=flat-square
128+
[badge-release]: https://img.shields.io/github/release/eclipxe13/CfdiUtils?logo=git&style=flat-square
129+
[badge-license]: https://img.shields.io/github/license/eclipxe13/CfdiUtils?logo=open-source-initiative&style=flat-square
130130
[badge-build]: https://img.shields.io/travis/eclipxe13/CfdiUtils/master?logo=travis&style=flat-square
131131
[badge-appveyor]: https://img.shields.io/appveyor/ci/eclipxe13/cfdiutils/master?logo=appveyor&style=flat-square
132132
[badge-quality]: https://img.shields.io/scrutinizer/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
133133
[badge-coverage]: https://img.shields.io/scrutinizer/coverage/g/eclipxe13/CfdiUtils/master?logo=scrutinizer-ci&style=flat-square
134-
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?style=flat-square
134+
[badge-downloads]: https://img.shields.io/packagist/dt/eclipxe/CfdiUtils?logo=composer&style=flat-square

docs/leer/limpieza-cfdi.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,30 @@ Estos errores comunes terminan en un error de validación.
2626
Para evitar estos errores se puede usar el objeto `CfdiUtils\Cleaner\Cleaner`.
2727
Este objeto requiere una cadena de texto con XML válido. Y limpia el XML siguiendo estos pasos:
2828

29+
1. Cambiar la defición incorrecta en algunos CFDI del SAT `xmlns:schemaLocation` por `xsi:schemaLocation`.
30+
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
31+
con prefijo `xmlns:cfdi="http://www.sat.gob.mx/cfd/3"` sí esté presente.
2932
1. Remueve el nodo `cfdi:Addenda`.
3033
1. Remueve dentro de las locaciones de espacios de nombre `xsi:schemaLocation` los namespaces que no tengan
31-
a continuación una uri que termine en `.xsd`.
34+
a continuación una uri que termine en `.xsd`.
3235
1. Remueve todos los nodos que no tengan relación con el SAT (los que no contengan `http://www.sat.gob.mx/`).
3336
1. Remueve todos los pares de espacio de nombre y archivo xsd de los `xsi:schemaLocation` que no tengan relación con el SAT.
3437
1. Remueve todos los espacios de nombres listados que no están en uso.
3538
1. Colapsa los nodos `cfdi:Complemento` en uno solo, respetando el mismo orden de aparición para que se genere
3639
exactamente la misma cadena de origen.
3740

41+
Las primeras dos formas no trabajan con el CFDI como XML, lo trabajan como una cadena de texto.
42+
3843
La forma rápida de usar el limpiador es usando el método estático
3944
`CfdiUtils\Cleaner\Cleaner::staticClean(string $content): string`
4045
que recibe el XML sucio y devuelve el XML limpio.
4146

47+
```php
48+
<?php
49+
$possibleDirty = '... el xml del cfdi ...';
50+
$cleanContent = CfdiUtils\Cleaner\Cleaner::staticClean($possibleDirty);
51+
```
52+
4253
También se puede instanciar un objeto de la clase `CfdiUtils\Cleaner\Cleaner` y usar estos métodos:
4354

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

4859
Si deseas implementar tu propio orden, hacer o agregar nuevos limpiadores puedes extender la clase o sobrescribir
4960
el método `clean` o bien llamar a cada uno de los pasos de limpieza por tu propia cuenta.
61+
62+
De querer saltar las dos limpiezas previas a la carga del XML, es necesario construir el objeto `Cleaner`
63+
pasando un objeto de tipo `BeforeLoadCleanerInterface` que no haga ninguna limpieza, por ejemplo:
64+
65+
```php
66+
<?php
67+
$content = '... el xml del cfdi ...';
68+
69+
// objeto que no hace limpieza implementando el patrón de diseño NULL
70+
$nullBeforeLoadCleaner = new class () implements CfdiUtils\Cleaner\BeforeLoad\BeforeLoadCleanerInterface {
71+
public function clean(string $content): string {
72+
return $content;
73+
}
74+
};
75+
76+
$cleaner = new CfdiUtils\Cleaner\Cleaner($content, $nullBeforeLoadCleaner);
77+
$cleaner->clean();
78+
$content = $cleaner->retrieveXml();
79+
```

src/CfdiUtils/Certificado/SerialNumber.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function loadHexadecimal(string $hexString)
2929

3030
public function loadDecimal(string $decString)
3131
{
32-
if (0 === strpos($decString, '0x') || 0 === strpos($decString, '0X')) {
32+
if (0 === strcasecmp('0x', substr($decString, 0, 2))) {
3333
$hexString = substr($decString, 2);
3434
} else {
3535
$hexString = BaseConverter::createBase36()->convert($decString, 10, 16);
@@ -59,16 +59,16 @@ public function asDecimal(): string
5959

6060
protected function hexToAscii(string $input): string
6161
{
62-
return array_reduce(str_split($input, 2), function (string $carry, string $value): string {
63-
return $carry . chr(intval(hexdec($value)));
64-
}, '');
62+
return implode('', array_map(function (string $value): string {
63+
return chr(intval(hexdec($value)));
64+
}, str_split($input, 2)));
6565
}
6666

6767
protected function asciiToHex(string $input): string
6868
{
69-
return array_reduce(str_split($input, 1), function (string $carry, string $value): string {
70-
return $carry . dechex(ord($value));
71-
}, '');
69+
return implode('', array_map(function (string $value): string {
70+
return dechex(ord($value));
71+
}, str_split($input, 1)));
7272
}
7373

7474
/**
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace CfdiUtils\Cleaner\BeforeLoad;
4+
5+
class BeforeLoadCleaner implements BeforeLoadCleanerInterface
6+
{
7+
/** @var BeforeLoadCleanerInterface[] */
8+
private $cleaners;
9+
10+
public function __construct(BeforeLoadCleanerInterface ...$cleaners)
11+
{
12+
if ([] === $cleaners) {
13+
$cleaners = $this->defaultCleaners();
14+
}
15+
$this->cleaners = $cleaners;
16+
}
17+
18+
/** @return BeforeLoadCleanerInterface[] */
19+
public static function defaultCleaners(): array
20+
{
21+
return [
22+
new ChangeXmlnsSchemaLocation(),
23+
new RemoveDuplicatedCfdi3Namespace(),
24+
];
25+
}
26+
27+
/** @return BeforeLoadCleanerInterface[] */
28+
public function members(): array
29+
{
30+
return $this->cleaners;
31+
}
32+
33+
public function clean(string $content): string
34+
{
35+
foreach ($this->cleaners as $cleaner) {
36+
$content = $cleaner->clean($content);
37+
}
38+
return $content;
39+
}
40+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace CfdiUtils\Cleaner\BeforeLoad;
4+
5+
interface BeforeLoadCleanerInterface
6+
{
7+
public function clean(string $content): string;
8+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace CfdiUtils\Cleaner\BeforeLoad;
4+
5+
class ChangeXmlnsSchemaLocation implements BeforeLoadCleanerInterface
6+
{
7+
public function clean(string $content): string
8+
{
9+
return str_replace(' xmlns:schemaLocation="', ' xsi:schemaLocation="', $content);
10+
}
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace CfdiUtils\Cleaner\BeforeLoad;
4+
5+
class RemoveDuplicatedCfdi3Namespace implements BeforeLoadCleanerInterface
6+
{
7+
public function clean(string $content): string
8+
{
9+
if (false !== strpos($content, ' xmlns="http://www.sat.gob.mx/cfd/3"')
10+
&& false !== strpos($content, ' xmlns:cfdi="http://www.sat.gob.mx/cfd/3"')) {
11+
$content = str_replace(' xmlns="http://www.sat.gob.mx/cfd/3"', '', $content);
12+
}
13+
return $content;
14+
}
15+
}

src/CfdiUtils/Cleaner/Cleaner.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace CfdiUtils\Cleaner;
44

55
use CfdiUtils\Cfdi;
6+
use CfdiUtils\Cleaner\BeforeLoad\BeforeLoadCleanerInterface;
67
use CfdiUtils\Utils\SchemaLocations;
78
use CfdiUtils\Utils\Xml;
89
use DOMAttr;
@@ -27,8 +28,12 @@ class Cleaner
2728
/** @var DOMDocument|null */
2829
protected $dom;
2930

30-
public function __construct(string $content)
31+
/** @var BeforeLoadCleanerInterface */
32+
private $beforeLoadCleaner;
33+
34+
public function __construct(string $content, BeforeLoadCleanerInterface $beforeLoadCleaner = null)
3135
{
36+
$this->beforeLoadCleaner = $beforeLoadCleaner ?? new BeforeLoad\BeforeLoadCleaner();
3237
if ('' !== $content) {
3338
$this->load($content);
3439
}
@@ -104,6 +109,7 @@ public function clean()
104109
public function load(string $content)
105110
{
106111
try {
112+
$content = $this->beforeLoadCleaner->clean($content);
107113
$cfdi = Cfdi::newFromString($content);
108114
} catch (\Throwable $exception) {
109115
throw new CleanerException($exception->getMessage(), $exception->getCode(), $exception->getPrevious());

0 commit comments

Comments
 (0)