| <?php |
| namespace yakov_255\EGRPDDU\Fond; |
| use Exception; |
| use InvalidArgumentException; |
| use yakov_255\EGRPDDU\Csv\CSVWrite; |
| use yakov_255\EGRPDDU\Util\Regex; |
| use yakov_255\EGRPDDU\XML\XMLReader; |
| class Fond |
| { |
| private $input = ROOT . "/data/input"; |
| private $output = ROOT . "/data/output"; |
| private $schemaPath = ROOT . "/data/fond"; |
| private $templatePath = ROOT . "/data/fond/fond_template.xlsx"; |
| public function extractXmlToCSV() |
| { |
| $xml_files = glob($this->input . "/*.xml"); |
| foreach ($xml_files as $path) { |
| try { |
| $this->processXml($path); |
| } catch (Exception $exception) { |
| echo $exception->getMessage() . PHP_EOL; |
| break; |
| } |
| } |
| foreach (glob($this->output . "/*.csv*") as $path) { |
| unlink($path); |
| } |
| } |
| /** |
| * @param $path |
| * @throws Exception |
| */ |
| private function processXml($path): void |
| { |
| $schema_list = glob($this->schemaPath . "/schema - *.xml"); |
| $csv_list = array(); |
| foreach ($schema_list as $schema_path) { |
| $class_name = Regex::regexFirst("/schema - (\w+)\.xml/u", $schema_path); |
| $class = null; |
| switch ($class_name) { |
| case "Требования": |
| $class = new TableEncumbrance(['check' => false]); |
| break; |
| case "Участники": |
| $class = new TableOwners(['check' => false]); |
| break; |
| case "Оплата": |
| $class = new TablePay(['check' => false]); |
| break; |
| default: |
| throw new Exception("Cannot parse schema. Check schema name"); |
| } |
| try { |
| $csv_list[$class_name] = $this->extractCSVFromXML($path, $schema_path, $class); |
| } catch (InvalidArgumentException $exception) { |
| echo "error on file: $path with schema: $schema_path " . $exception->getMessage() . PHP_EOL; |
| } |
| } |
| $out_name = pathinfo($path)['filename']; |
| $this->copyCsvToExcel($csv_list, $out_name); |
| } |
| /** |
| * @param $pathToXml |
| * @param $pathToSchema |
| * @param string $input |
| * @throws Exception |
| */ |
| private function extractCSVFromXML($pathToXml, $pathToSchema, ITable $worker): string |
| { |
| $xml = file_get_contents($pathToXml); |
| $schema = file_get_contents($pathToSchema); |
| $transformer = new XMLReader($schema); |
| $transformer::$skip = true; |
| try { |
| $resultArray = $transformer->extract($xml); |
| } catch (Exception $e) { |
| throw new InvalidArgumentException("file: $pathToXml, schema: $pathToSchema " . $e->getMessage(), 200, $e); |
| } |
| if (!count($resultArray)) { |
| throw new InvalidArgumentException("empty result at file: $pathToXml"); |
| } |
| // make first sheet |
| $resultArray = $worker->format($resultArray); |
| // rename |
| $count = count($resultArray); |
| $suffix = Regex::regexFirst("/schema - (\w+)\.xml$/u", $pathToSchema);; |
| $name = basename($pathToXml) . (strlen($suffix) ? (' - ' . $suffix) : ''); |
| $output_path = $this->output . '/' . $name . " ($count)" . '.csv'; |
| // convert to xml |
| $result_string = CSVWrite::writeToString($resultArray, ";", '"'); |
| // encode to 1251 |
| $result_string = iconv("utf-8", "windows-1251", $result_string); |
| file_put_contents($output_path, $result_string); |
| return $output_path; |
| } |
| private function copyCsvToExcel(array $csv_list, string $out_name) |
| { |
| $ext = pathinfo($this->templatePath)['extension']; |
| $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile($this->templatePath); |
| //$reader->setReadDataOnly(true); |
| $template_wb = $reader->load($this->templatePath); |
| foreach ($csv_list as $sheet_name => $full_path) { |
| $array = $this->readCsvIntoArray($full_path); |
| // remove csv header |
| array_splice($array, 0, 1); |
| $template_sheet = $template_wb->getSheetByName($sheet_name); |
| $template_sheet->fromArray($array, null, 'A3'); |
| } |
| $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($template_wb, ucfirst($ext)); |
| $writer->save($this->output . "/" . $out_name . "." . $ext); |
| } |
| /** |
| * @param $full_path |
| * @return array |
| * @throws \PhpOffice\PhpSpreadsheet\Exception |
| * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception |
| */ |
| private function readCsvIntoArray($full_path): array |
| { |
| $reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); |
| $reader->setInputEncoding('CP1251'); |
| $reader->setDelimiter(';'); |
| $reader->setEnclosure(''); |
| $reader->setSheetIndex(0); |
| $csv_wb = $reader->load($full_path); |
| $csv_sheet = $csv_wb->getActiveSheet(); |
| $csv_range = $csv_sheet->getHighestRowAndColumn(); |
| $range = "A1:" . $csv_range['column'] . $csv_range['row']; |
| $array = $csv_sheet |
| ->rangeToArray( |
| $range, // The worksheet range that we want to retrieve |
| NULL, // Value that should be returned for empty cells |
| TRUE, // Should formulas be calculated (the equivalent of getCalculatedValue() for each cell) |
| TRUE, // Should values be formatted (the equivalent of getFormattedValue() for each cell) |
| TRUE // Should the array be indexed by cell row and cell column |
| ); |
| return $array; |
| } |
| } |
Комментарии