66
77use GuzzleHttp \Client ;
88use PhpCfdi \SatPysScraper \Data \Types ;
9+ use PhpCfdi \SatPysScraper \Exceptions \HttpException ;
10+ use PhpCfdi \SatPysScraper \Exceptions \HttpServerException ;
911use PhpCfdi \SatPysScraper \Generator ;
1012use PhpCfdi \SatPysScraper \NullGeneratorTracker ;
1113use PhpCfdi \SatPysScraper \Scraper ;
1517
1618final readonly class SatPysScraper
1719{
18- /**
19- * @param list<string> $arguments
20- */
21- public function __construct (private string $ command , private array $ arguments , private ScraperInterface $ scraper )
20+ public function printHelp (string $ command ): void
2221 {
23- }
24-
25- /** @param string[] $argv */
26- public static function run (
27- array $ argv ,
28- ScraperInterface $ scraper = new Scraper (new Client ()),
29- string $ stdErrFile = 'php://stderr '
30- ): int {
31- $ command = (string ) array_shift ($ argv );
32- $ argv = array_values ($ argv );
33- $ app = new self ($ command , $ argv , $ scraper );
34- try {
35- $ app ->execute ();
36- return 0 ;
37- } catch (Throwable $ exception ) {
38- file_put_contents ($ stdErrFile , 'ERROR: ' . $ exception ->getMessage () . PHP_EOL , FILE_APPEND );
39- return 1 ;
40- }
41- }
42-
43- public function printHelp (): void
44- {
45- $ command = basename ($ this ->command );
4622 echo <<< HELP
4723 $ command - Crea un archivo XML con la clasificación de productos y servicios del SAT.
4824
4925 Sintaxis:
5026 $ command help|-h|--help
51- $ command [--quiet|-q] [--json|-j JSON_FILE] [--xml|-x XML_FILE]
27+ $ command [--quiet|-q] [--debug|-d] [-- json|-j JSON_FILE] [--xml|-x XML_FILE] [--tries|-t TRIES ]
5228
5329 Argumentos:
5430 --xml|-x XML_FILE
@@ -59,12 +35,18 @@ public function printHelp(): void
5935 los datos generados en formato JSON.
6036 --sort|-s SORT
6137 Establece el orden de elementos, default: key, se puede usar "key" o "name".
38+ --tries|-t TRIES
39+ Establece cuántas veces debe intentar hacer la descarga si encuentra un error de servidor.
40+ Default: 1. El valor debe ser mayor o igual a 1.
41+ --debug|-d
42+ Mensajes de intentos e información del error se envían a la salida estándar de error.
6243 --quiet|-q
6344 Modo de operación silencioso.
6445
6546 Notas:
6647 Debe especificar al menos un argumento "--xml" o "--json", o ambos.
6748 No se puede especificar "-" como salida de "--xml" y "--json" al mismo tiempo.
49+ Al especificar la salida "-" se activa automáticamente el modo silencioso.
6850
6951 Acerca de:
7052 Este script pertenece al proyecto https://github.com/phpcfdi/sat-pys-scraper
@@ -74,84 +56,66 @@ public function printHelp(): void
7456 HELP ;
7557 }
7658
77- /** @throws ArgumentException */
78- public function execute ( ): void
59+ /** @param list<string> $argv */
60+ public function run ( array $ argv , ScraperInterface | null $ scraper = null , string $ stdErrFile = ' php://stderr ' ): int
7961 {
80- if ([] !== array_intersect ($ this ->arguments , ['help ' , '-h ' , '--help ' ])) {
81- $ this ->printHelp ();
82- return ;
83- }
84-
85- $ arguments = $ this ->processArguments (...$ this ->arguments );
86- $ tracker = ($ arguments ['quiet ' ]) ? new NullGeneratorTracker () : new PrinterGeneratorTracker ();
87- $ types = (new Generator ($ this ->scraper , $ tracker ))->generate ();
88-
89- // sort types
90- match ($ arguments ['sort ' ]) {
91- 'key ' => $ types ->sortByKey (),
92- 'name ' => $ types ->sortByName (),
93- default => throw new ArgumentException ('Unrecognized sort argument ' ),
94- };
62+ $ command = (string ) array_shift ($ argv );
63+ $ app = new self ();
9564
96- if ('' !== $ arguments ['xml ' ]) {
97- $ this ->toXml ($ arguments ['xml ' ], $ types );
98- }
99- if ('' !== $ arguments ['json ' ]) {
100- $ this ->toJson ($ arguments ['json ' ], $ types );
65+ if ([] !== array_intersect ($ argv , ['help ' , '-h ' , '--help ' ])) {
66+ $ app ->printHelp (basename ($ command ));
67+ return 0 ;
10168 }
102- }
69+ $ debug = [] !== array_intersect ($ argv , ['-d ' , '--debug ' ]);
70+ $ try = 0 ;
10371
104- /**
105- * @return array{xml: string, json: string, quiet: bool, sort: string}
106- * @throws ArgumentException
107- */
108- public function processArguments (string ...$ arguments ): array
109- {
110- $ arguments = array_values ($ arguments );
111- $ xml = '' ;
112- $ json = '' ;
113- $ quiet = false ;
114- $ sort = 'key ' ;
115-
116- while ([] !== $ arguments ) {
117- $ argument = (string ) array_shift ($ arguments );
118- if (in_array ($ argument , ['--xml ' , '-x ' ], true )) {
119- $ xml = (string ) array_shift ($ arguments );
120- } elseif (in_array ($ argument , ['--json ' , '-j ' ], true )) {
121- $ json = (string ) array_shift ($ arguments );
122- } elseif (in_array ($ argument , ['--sort ' , '-s ' ], true )) {
123- $ sort = (string ) array_shift ($ arguments );
124- if (! in_array ($ sort , ['key ' , 'name ' ])) {
125- throw new ArgumentException (sprintf ('Invalid sort "%s" ' , $ sort ));
72+ try {
73+ $ arguments = (new ArgumentsBuilder ())->build (...$ argv );
74+ $ debug = $ arguments ->debug ;
75+ do {
76+ $ try = $ try + 1 ;
77+ try {
78+ $ app ->execute ($ arguments , $ scraper );
79+ $ serverException = null ;
80+ break ;
81+ } catch (HttpServerException $ exception ) {
82+ $ serverException = $ exception ;
83+ usleep (1000 );
12684 }
127- } elseif (in_array ($ argument , ['--quiet ' , '-q ' ], true )) {
128- $ quiet = true ;
129- } else {
130- throw new ArgumentException (sprintf ('Invalid argument "%s" ' , $ argument ));
85+ } while ($ try < $ arguments ->tries );
86+ if (null !== $ serverException ) {
87+ throw $ serverException ;
13188 }
89+ } catch (Throwable $ exception ) {
90+ file_put_contents ($ stdErrFile , 'ERROR: ' . $ exception ->getMessage () . PHP_EOL , FILE_APPEND );
91+ if ($ debug ) {
92+ file_put_contents ($ stdErrFile , "The procedure was executed $ try times \n" , FILE_APPEND );
93+ file_put_contents ($ stdErrFile , print_r ($ exception , true ), FILE_APPEND );
94+ }
95+ return 1 ;
13296 }
97+ return 0 ;
98+ }
13399
134- if ('' === $ xml && '' === $ json ) {
135- throw new ArgumentException ('Did not specify --xml or --json arguments ' );
136- }
137- if ('- ' === $ xml && '- ' === $ json ) {
138- throw new ArgumentException ('Cannot send --xml and --json result to standard output at the same time ' );
139- }
140- if ('- ' === $ xml ) {
141- $ xml = 'php://stdout ' ;
142- $ quiet = true ;
100+ /** @throws HttpServerException|HttpException */
101+ private function execute (Arguments $ arguments , ScraperInterface |null $ scraper ): void
102+ {
103+ $ tracker = ($ arguments ->quiet ) ? new NullGeneratorTracker () : new PrinterGeneratorTracker ();
104+ $ scraper ??= new Scraper (new Client ());
105+ $ types = (new Generator ($ scraper , $ tracker ))->generate ();
106+
107+ // sort types
108+ match ($ arguments ->sort ) {
109+ 'name ' => $ types ->sortByName (),
110+ default => $ types ->sortByKey (),
111+ };
112+
113+ if ('' !== $ arguments ->xml ) {
114+ $ this ->toXml ($ arguments ->xml , $ types );
143115 }
144- if ('- ' === $ json ) {
145- $ json = 'php://stdout ' ;
146- $ quiet = true ;
116+ if ('' !== $ arguments ->json ) {
117+ $ this ->toJson ($ arguments ->json , $ types );
147118 }
148-
149- return [
150- 'xml ' => $ xml ,
151- 'json ' => $ json ,
152- 'quiet ' => $ quiet ,
153- 'sort ' => $ sort ,
154- ];
155119 }
156120
157121 public function toXml (string $ output , Types $ types ): void
0 commit comments