Initial xentral_oss_20.3.c9ffacf

This commit is contained in:
Alex
2021-05-21 08:49:41 +02:00
parent 5406e4a551
commit 34e5ac43d9
18884 changed files with 2109867 additions and 0 deletions
@@ -0,0 +1,127 @@
<?php
declare(strict_types=1);
namespace Xentral\Modules\Datanorm\Service;
use Xentral\Components\Database\Database;
use Xentral\Components\Database\Exception\QueryFailureException;
use Xentral\Modules\Datanorm\Exception\ArticleNotFoundException;
use Xentral\Modules\Datanorm\Exception\InvalidArgumentException;
final class ArticleService
{
/** @var Database */
private $db;
/**
* @param Database $db
*/
public function __construct(Database $db)
{
$this->db = $db;
}
/**
* @param array $articleArray
*
* @throws ArticleNotFoundException
* @throws QueryFailureException
* @throws InvalidArgumentException
*
* @return int
*/
public function InsertUpdateArticle(array $articleArray): ?int
{
if (empty($articleArray['nummer'])) {
throw new ArticleNotFoundException('No article number found.');
}
$articleId = $this->findArticleIdByNumber($articleArray['nummer']);
if (empty($articleId)) {
$articleId = $this->insertArrayIntoTable($articleArray, 'artikel');
} else {
$this->updateArrayIntoTable($articleArray, 'artikel', $articleId);
}
return $articleId;
}
/**
* @param array $data
* @param string $table
*
* @throws QueryFailureException
* @throws InvalidArgumentException
*
* @return int
*/
private function insertArrayIntoTable(array $data, string $table): ?int
{
if (empty($data)) {
throw new InvalidArgumentException('No data to insert into ' . $table . ' given');
}
$insert = $this->db->insert();
$insert
->cols($data)
->into($table);
$this->db->perform($insert->getStatement(), $insert->getBindValues());
return $this->db->lastInsertId();
}
/**
* @param array $data
* @param string $table
* @param int $id
*
* @throws QueryFailureException
* @throws InvalidArgumentException
*/
private function updateArrayIntoTable(array $data, string $table, int $id): void
{
if (empty($data)) {
throw new InvalidArgumentException('No data to update in ' . $table . ' given');
}
if (empty($id)) {
throw new InvalidArgumentException('No id for update in ' . $table . ' given');
}
$update = $this->db->update()
->table($table)
->cols($data)
->where('id=?', $id);
$this->db->perform($update->getStatement(), $update->getBindValues());
}
/**
* @param string $number
*
* @return int
*/
public function findArticleIdByNumber(string $number): ?int
{
$select = $this->db->select()
->cols(['id'])
->from('artikel')
->where('nummer=?', $number)
->limit(1);
$result = $this->db->fetchCol(
$select->getStatement(),
$select->getBindValues()
);
if (!empty($result)) {
return $result[0];
}
return 0;
}
}
@@ -0,0 +1,202 @@
<?php
declare(strict_types=1);
namespace Xentral\Modules\Datanorm\Service;
use Xentral\Modules\Datanorm\Data\DatanormATypeData;
use Xentral\Modules\Datanorm\Data\DatanormBTypeData;
final class DatanormConverter
{
/**
* @param DatanormATypeData $aType
*
* @return array
*/
public function transformATypeToArticleArray(DatanormATypeData $aType): array
{
$article = [];
$article['nummer'] = $aType->getArticleNumber();
$article['name_de'] = $aType->getShortDescription1();
$article['anabregs_text'] = $aType->getShortDescription2();
$article['ean'] = $aType->getEan();
$article['herstellernummer'] = $aType->getProducerNumber();
$article['einheit'] = $aType->getPackingUnit();
if ($aType->getArticleType() === '1') {
$article['lagerartikel'] = 1;
}
if ($aType->getWorkflowState() === 'L') {
$article['intern_gesperrt'] = 1;
$article['intern_gesperrtgrund'] = 'DATANORM';
}
$article['umsatzsteuer'] = 'normal';
if ($aType->getMwstType() === 3) {
$article['umsatzsteuer'] = 'ermaessigt';
}
return $article;
}
/**
* @param DatanormBTypeData $bType
*
* @return array
*/
public function transformBTypeToArticleArray(DatanormBTypeData $bType): array
{
$article = [];
if (!empty($bType->getEan())) {
$article['ean'] = $bType->getEan();
}
if ($bType->getProcessingFlag() === 'L') {
$article['intern_gesperrt'] = 1;
$article['intern_gesperrtgrund'] = 'DATANORM';
}
if (!empty($bType->getAltArticleNumber())) {
$article['herstellernummer'] = $bType->getAltArticleNumber();
}
if ($bType->getCopperWeightIndicator() != '0' && $bType->getCopperWeightIndicator() != '') {
$article['internerkommentar'] =
'Kupfer-Gewichtsmerker: ' . $bType->getCopperWeightIndicator() . PHP_EOL .
'Kupfer-Kennzahl: ' . $bType->getCopperWeightIndicator() . PHP_EOL .
'Kupfer-Gewicht: ' . $bType->getCopperWeightIndicator();
}
if (!empty($article)) {
$article['nummer'] = $bType->getArticleNumber();
}
return $article;
}
/**
* @param int $articleId
* @param string $priceMark
* @param string $currency
* @param int $amount
* @param float $price
* @param int $supplierId
* @param string $discountFlag1
* @param float $discount1
* @param string $discountFlag2
* @param float $discount2
* @param string $discountFlag3
* @param float $discount3
*
* @return array
*/
public function transformToPriceArray(
int $articleId,
string $priceMark,
string $currency,
int $amount,
float $price,
int $supplierId,
string $discountFlag1,
float $discount1,
string $discountFlag2,
float $discount2,
string $discountFlag3,
float $discount3
): array {
$sellingPrice = [];
$purchasePrices = [];
if ($priceMark === '2') {
$purchasePrices[] = [
'article_id' => $articleId,
'address_id' => $supplierId,
'currency_code' => $currency,
'quantity_from' => $amount,
'price' => $price,
];
} else {
$sellingPrice = [
'currency_code' => $currency,
'quantity_from' => $amount,
'article_id' => $articleId,
'price' => $price,
];
if ($priceMark === '1') {
if (!empty($discountFlag1)) {
$discountPrice1 = $this->calculateDiscountPrice($price, $discountFlag1, $discount1);
if (!empty($discountPrice1)) {
$purchasePrices[] = [
'article_id' => $articleId,
'address_id' => $supplierId,
'currency_code' => $currency,
'quantity_from' => $amount,
'price' => $discountPrice1,
];
}
}
if (!empty($discountFlag2)) {
$discountPrice2 = $this->calculateDiscountPrice($price, $discountFlag2, $discount2);
if (!empty($discountPrice2)) {
$purchasePrices[] = [
'article_id' => $articleId,
'address_id' => $supplierId,
'currency_code' => $currency,
'quantity_from' => $amount,
'price' => $discountPrice2,
];
}
}
if (!empty($discountFlag3)) {
$discountPrice3 = $this->calculateDiscountPrice($price, $discountFlag3, $discount3);
if (!empty($discountPrice3)) {
$purchasePrices[] = [
'article_id' => $articleId,
'address_id' => $supplierId,
'currency_code' => $currency,
'quantity_from' => $amount,
'price' => $discountPrice3,
];
}
}
}
}
return [
'sellingPrice' => $sellingPrice,
'purchasePrices' => $purchasePrices,
];
}
/**
* @param float $price
* @param string $discountFlag
* @param float $discount
*
* @return float
*/
private function calculateDiscountPrice(float $price, string $discountFlag, float $discount)
{
$discountPrice = 0.0;
// Discount
if ($discountFlag === '1') {
$discountPrice = $price - ($price * ($discount / 100));
} // Factor
elseif ($discountFlag === '2') {
$discountPrice = $price * $discount;
} // Surcharge
elseif ($discountFlag === '3') {
$discountPrice = $price + ($price * ($discount / 100));
}
return $discountPrice;
}
}
@@ -0,0 +1,253 @@
<?php
declare(strict_types=1);
namespace Xentral\Modules\Datanorm\Service;
use Xentral\Modules\Datanorm\Data\DatanormATypeData;
use Xentral\Modules\Datanorm\Data\DatanormDTypeData;
use Xentral\Modules\Datanorm\Data\DatanormPTypeData;
use Xentral\Modules\Datanorm\Data\DatanormTTypeData;
final class DatanormEnricher
{
/** @var DatanormIntermediateGateway $intermediateGateway */
private $intermediateGateway;
/**
* @param DatanormIntermediateGateway $intermediateGateway
*/
public function __construct(DatanormIntermediateGateway $intermediateGateway)
{
$this->intermediateGateway = $intermediateGateway;
}
/**
* @param DatanormPTypeData $pType
*
* @return DatanormPTypeData
*/
public function enrichPrice(DatanormPTypeData $pType): DatanormPTypeData
{
$articleNumber = $pType->getArticleNumber1();
$data = $this->intermediateGateway->findArticleLineByNumber($articleNumber);
$amount = $this->getPriceAmount($data);
$pType->setPriceAmount1($amount);
$price = $pType->getPrice1();
$pType->setPrice1($price / $amount);
$articleNumber2 = $pType->getArticleNumber2();
if (!empty($articleNumber2)) {
$data = $this->intermediateGateway->findArticleLineByNumber($articleNumber2);
if (isset($data['content'])) {
$amount = $this->getPriceAmount($data);
$pType->setPriceAmount2($amount);
$price = $pType->getPrice2();
$pType->setPrice2($price / $amount);
}
}
$articleNumber3 = $pType->getArticleNumber3();
if (!empty($articleNumber3)) {
$data = $this->intermediateGateway->findArticleLineByNumber($articleNumber3);
if (isset($data['content'])) {
$amount = $this->getPriceAmount($data);
$pType->setPriceAmount3($amount);
$price = $pType->getPrice3();
$pType->setPrice3($price / $amount);
}
}
return $pType;
}
/**
* @param array $data
*
* @return int
*/
private function getPriceAmount(array $data): int
{
$aType = new DatanormATypeData();
$aType->fillByJson($data['content']);
return (int)$aType->getPriceAmount();
}
/**
* @param DatanormATypeData $aType
*
* @return DatanormATypeData
*/
public function enrichArticle(DatanormATypeData $aType): DatanormATypeData
{
$longTextBlockNumber = $aType->getLongDecriptionKey();
$textFlag = substr($aType->getTextkey(), 0, 1);
$text = '';
$longtText = '';
$dimensionText = '';
if (!empty($longTextBlockNumber)) {
$longtextData = $this->intermediateGateway->findTTypeContentByBlocknumber($longTextBlockNumber);
if (!empty($longtextData)) {
$longtText = $this->createLongText($longtextData);
}
}
$dimensionTextData = $this->intermediateGateway->findDTypeContentByArticleNumer($aType->getArticleNumber());
if (!empty($dimensionTextData)) {
$dimensionText = $this->getDimensionText($dimensionTextData);
}
if ($textFlag === '0') { //KT1 + KT2
$text .= $aType->getShortDescription1() . PHP_EOL;
$text .= $aType->getShortDescription2();
} elseif ($textFlag === '1') { //LT + KT2
$text .= $longtText . PHP_EOL;
$text .= $aType->getShortDescription2();
} elseif ($textFlag === '2') { //KT1 + DT
$text .= $aType->getShortDescription1() . PHP_EOL;
$text .= $dimensionText;
} elseif ($textFlag === '3') { //LT + DT
$text .= $longtText . PHP_EOL;
$text .= $dimensionText;
} elseif ($textFlag === '4') { //KT1 + KT2 + LT
$text .= $aType->getShortDescription1() . PHP_EOL;
$text .= $aType->getShortDescription2() . PHP_EOL;
$text .= $longtText;
} elseif ($textFlag === '5') { //KT1 + KT2 + DT
$text .= $aType->getShortDescription1() . PHP_EOL;
$text .= $aType->getShortDescription2() . PHP_EOL;
$text .= $dimensionText;
} elseif ($textFlag === '6') { //KT1 + KT2 + LT + DT
$text .= $aType->getShortDescription1() . PHP_EOL;
$text .= $aType->getShortDescription2() . PHP_EOL;
$text .= $longtText . PHP_EOL;
$text .= $dimensionText;
}
if (!empty($text)) {
$aType->setShortDescription2(trim($text));
}
return $aType;
}
/**
* @param array $longTextData
*
* @return string
*/
private function createLongText(array $longTextData): string
{
$longtext = '';
foreach ($longTextData as $d) {
$tType = new DatanormTTypeData();
$tType->fillByJson($d['content']);
if (!empty($tType->getText1())) {
$longtext .= $tType->getText1() . PHP_EOL;
}
if (!empty($tType->getText2())) {
$longtext .= $tType->getText2() . PHP_EOL;
}
}
return trim($longtext);
}
/**
* @param array $dimensionTextData
*
* @return string
*/
private function getDimensionText(array $dimensionTextData): string
{
$dimensionText = '';
foreach ($dimensionTextData as $d) {
$dType = new DatanormDTypeData();
$dType->fillByJson($d['content']);
$textIndicator1 = $dType->getTextIndicator1();
$textIndicator2 = $dType->getTextIndicator2();
if (!empty($textIndicator1)) {
$txt = $this->createDimensionText(
$textIndicator1,
$dType->getText1(),
$dType->getTextblockNumber1()
);
if (!empty($txt)) {
$dimensionText .= $txt . PHP_EOL;
}
}
if (!empty($textIndicator2)) {
$txt = $this->createDimensionText(
$textIndicator2,
$dType->getText2(),
$dType->getTextblockNumber2()
);
if (!empty($txt)) {
$dimensionText .= $txt . PHP_EOL;
}
}
}
return trim($dimensionText);
}
/**
* @param string $textIndicator
* @param string $text
* @param string $textBlockNumber
*
* @return string
*/
private function createDimensionText(string $textIndicator, string $text, string $textBlockNumber): string
{
$dimensionText = '';
if ($textIndicator === 'F') {
$dimensionText = $text;
} else {
$longTextData = $this->intermediateGateway->findTTypeContentByBlocknumber(
$textBlockNumber
);
if ($textIndicator === 'T') {
$dimensionText .= $this->createLongText($longTextData);
} elseif ($textIndicator === 'E') {
$dimensionText .= $this->createInsertingText($text, $longTextData);
}
}
return $dimensionText;
}
/**
* @param string $fillementText
* @param array $longTextData
*
* @return string
*/
private function createInsertingText(string $fillementText, array $longTextData): string
{
$tType = new DatanormTTypeData();
$tType->fillByJson($longTextData[0]['content']);
$pattern = $tType->getText1();
$patternExp = explode('$$$', $pattern);
$fillmentExp = explode('$', $fillementText);
$text = '';
for ($i = 0; $i < count($patternExp); $i++) {
$text .= $patternExp[$i] . $fillmentExp[$i];
}
return $text;
}
}
@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
namespace Xentral\Modules\Datanorm\Service;
use Xentral\Components\Database\Database;
final class DatanormIntermediateGateway
{
/** @var Database */
private $db;
/**
* @param Database $db
*/
public function __construct(Database $db)
{
$this->db = $db;
}
/**
* @param int $limit
*
* @return array
*/
public function getLines(int $limit): array
{
$sqlOnlyA =
'SELECT d.id, d.fileName, d.type, d.content
FROM `datanorm_intermediate` AS `d`
WHERE d.type = \'A\'
AND d.errorFlag = 0
AND d.doneFlag = 0
AND d.ready = 1
ORDER BY d.id DESC
LIMIT ' . $limit;
$sqlNotV =
'SELECT d.id, d.fileName, d.type, d.content
FROM `datanorm_intermediate` AS `d`
WHERE d.type != \'V\'
AND d.errorFlag = 0
AND d.doneFlag = 0
AND d.ready = 1
ORDER BY d.id DESC
LIMIT ' . $limit;
// Articles (type A) MUST be imported before anything else;
// 'ORDER BY type' makes the query slower than 2 single querys
$rows = $this->db->fetchAll($sqlOnlyA);
if (empty($rows)) {
$rows = $this->db->fetchAll($sqlNotV);
}
return $rows;
}
/**
* @param int $limit
*
* @return array
*/
public function getLinesToEnrich(int $limit): array
{
$sql =
'SELECT d.id, d.fileName, d.type, d.content
FROM `datanorm_intermediate` AS `d`
WHERE d.enrich = 1
AND d.doneFlag = 0
ORDER BY d.id DESC
LIMIT ' . $limit;
return $this->db->fetchAll($sql);
}
/**
* @param string $fileName
*
* @return array
*/
public function getVType(string $fileName): array
{
$select = $this->db->select()
->cols(['id', 'fileName', 'type', 'content', 'supplier_address_id', 'user_address_id'])
->from('datanorm_intermediate')
->where('fileName = ?', $fileName)
->where('type = ?', 'V')
->limit(1);
return $this->db->fetchRow(
$select->getStatement(),
$select->getBindValues()
);
}
/**
* @param string $articleNumber
*
* @return array
*/
public function findArticleLineByNumber(string $articleNumber): array
{
$sql =
'SELECT di.content
FROM `datanorm_intermediate` AS `di`
WHERE di.type = \'A\'
AND di.nummer = :articleNumber
ORDER BY di.id DESC
LIMIT 1';
$values = [
'articleNumber' => $articleNumber,
];
return $this->db->fetchRow($sql, $values);
}
/**
* @param string $longTextBlockNumber
*
* @return array
*/
public function findTTypeContentByBlocknumber(string $longTextBlockNumber): array
{
$sql =
'SELECT di.content
FROM `datanorm_intermediate` AS `di`
WHERE di.type = \'T\'
AND di.nummer = :longTextBlockNumber
AND di.doneFlag = 0
ORDER BY di.id';
$values = [
'longTextBlockNumber' => $longTextBlockNumber,
];
return $this->db->fetchAll($sql, $values);
}
/**
* @param string $articleNumber
*
* @return array
*/
public function findDTypeContentByArticleNumer(string $articleNumber): array
{
$sql =
'SELECT di.content
FROM `datanorm_intermediate` AS `di`
WHERE di.type = \'D\'
AND di.nummer = :articleNumber
AND di.doneFlag = 0
ORDER BY di.id';
$values = [
'articleNumber' => $articleNumber,
];
return $this->db->fetchAll($sql, $values);
}
/**
* @param int $vId
*
* @return string
*/
public function findSupplierNumberByVid(int $vId)
{
$sql =
'SELECT a.lieferantennummer
FROM `adresse` AS `a`
LEFT JOIN `datanorm_intermediate` AS `di` ON di.supplier_address_id = a.id
WHERE di.id = :v_id';
$values = [
'v_id' => $vId,
];
$result = $this->db->fetchRow($sql, $values);
if (!empty($result)) {
return (string)$result['lieferantennummer'];
}
return '';
}
}
@@ -0,0 +1,152 @@
<?php
declare(strict_types=1);
namespace Xentral\Modules\Datanorm\Service;
use Xentral\Components\Database\Database;
final class DatanormIntermediateService
{
/** @var Database */
private $db;
/**
* @param Database $db
*/
public function __construct(Database $db)
{
$this->db = $db;
}
/**
* @param array $intermediateEntries
*/
public function writeMultiple(array $intermediateEntries): void
{
if (!empty($intermediateEntries)) {
$sql =
'INSERT IGNORE INTO `datanorm_intermediate` (`fileName`, `type`, `content` ,`hash`, `doneFlag`, `nummer`,`enrich`, `user_address_id`)
VALUES';
$values = [];
$sqlParams = [];
foreach ($intermediateEntries as $index => $entry) {
$fileName = $entry['fileName'];
$type = $entry['type'];
$content = json_encode($entry['obj']);
$doneFlag = ($type === 'V' ? 1 : 0);
$hash = ($type === 'V' ? $fileName : md5($content));
$nummer = $entry['nummer'];
$enrich = $entry['enrich'];
$userAddressId = $entry['user_address_id'];
$values['fileName' . $index] = $fileName;
$values['type' . $index] = $type;
$values['content' . $index] = $content;
$values['hash' . $index] = $hash;
$values['doneFlag' . $index] = $doneFlag;
$values['nummer' . $index] = $nummer;
$values['enrich' . $index] = $enrich;
$values['user_address_id' . $index] = $userAddressId;
$sqlParams[] =
'(:fileName' . $index .
',:type' . $index .
',:content' . $index .
',:hash' . $index .
',:doneFlag' . $index .
',:nummer' . $index .
',:enrich' . $index .
',:user_address_id' . $index . ')';
}
$sql .= implode(',', $sqlParams);
$this->db->perform($sql, $values);
}
}
/**
* @param array $intermdiateIds
* @param bool $done
*/
public function setMultipleDone(array $intermdiateIds, bool $done = true): void
{
if (!empty($intermdiateIds)) {
$sql = 'UPDATE `datanorm_intermediate` SET `doneFlag` = :done WHERE `id` IN (';
$values = [
'done' => $done,
];
$idStrs = [];
for ($i = 0; $i < count($intermdiateIds); $i++) {
$idStrs[] = ':id' . $i;
$values['id' . $i] = $intermdiateIds[$i];
}
$sql .= implode(',', $idStrs);
$sql .= ')';
$this->db->perform($sql, $values);
}
}
/**
* @param array $enrichData
*/
public function saveEnrichData(array $enrichData): void
{
foreach ($enrichData as $id => $data) {
$sql =
'UPDATE `datanorm_intermediate`
SET
`content` = :content,
`hash` = :hash,
`enrich` = :enrich
WHERE `id` = :id';
$values = [
'content' => $data['content'],
'hash' => $data['hash'],
'enrich' => $data['enrich'],
'id' => $id,
];
$this->db->perform($sql, $values);
}
}
public function setTAndDTypeDone(): void
{
$sql =
'UPDATE `datanorm_intermediate`
SET
`doneFlag` = :done
WHERE (`type` = \'T\' OR `type` = \'D\')
AND `doneFlag` = 0';
$values = ['done' => true];
$this->db->perform($sql, $values);
}
/**
* @param int $vId
* @param string $supplierNumber
*/
public function saveSupplierToVType(int $vId, string $supplierNumber)
{
$sql =
'UPDATE `datanorm_intermediate`
SET
`supplier_address_id` =
(
SELECT a.id
FROM `adresse` AS `a`
WHERE a.lieferantennummer = :supplier_number
LIMIT 1
)
WHERE `id` = :v_id';
$values = ['v_id' => $vId, 'supplier_number' => $supplierNumber];
$this->db->perform($sql, $values);
}
}
@@ -0,0 +1,358 @@
<?php
declare(strict_types=1);
namespace Xentral\Modules\Datanorm\Service;
use Generator;
use Xentral\Components\Filesystem\Exception\FileNotFoundException;
use Xentral\Components\Filesystem\FilesystemInterface;
use Xentral\Components\Filesystem\PathInfo;
use Xentral\Modules\Datanorm\Data\DatanormTypeDataInterface;
use Xentral\Modules\Datanorm\Exception\FileSystemException;
use Xentral\Modules\Datanorm\Exception\InvalidLineException;
use Xentral\Modules\Datanorm\Exception\NoAddressIdFoundException;
use Xentral\Modules\Datanorm\Exception\WrongDiscountFormatException;
use Xentral\Modules\Datanorm\Exception\WrongPriceFormatException;
use Xentral\Modules\Datanorm\Exception\WrongVersionException;
use Xentral\Modules\Datanorm\Handler\DatanormReaderHandlerInterface;
final class DatanormReader
{
/** @var FilesystemInterface $filesystem */
private $filesystem;
/** @var string $uploadDir */
private $uploadDir;
/** @var DatanormReaderHandlerInterface[] $readerHandlers */
private $readerHandlers;
/** @var int[] $readerVersions */
private $readerVersions;
/** @var DatanormIntermediateService $intermediateService */
private $intermediateService;
/**
* @param FilesystemInterface $filesystem
* @param DatanormIntermediateService $intermediateService
* @param DatanormReaderHandlerInterface[] $readerHandlers
* @param string $uploadDir Relative dir to filesystem-class root
*/
public function __construct(
FilesystemInterface $filesystem,
DatanormIntermediateService $intermediateService,
array $readerHandlers,
$uploadDir
) {
$this->filesystem = $filesystem;
$this->uploadDir = $uploadDir;
$this->readerHandlers = [];
$this->intermediateService = $intermediateService;
foreach ($readerHandlers as $r) {
$this->readerVersions[] = $r->getVersion();
$this->readerHandlers[] = $r;
}
if (!$filesystem->has($this->uploadDir)) {
$filesystem->createDir($this->uploadDir);
}
}
/**
* @param PathInfo $file
* @param int $limit
* @param int $lastLineNumber
*
* @throws FileNotFoundException
* @throws WrongVersionException
* @throws InvalidLineException
* @throws FileSystemException
* @throws WrongPriceFormatException
* @throws WrongDiscountFormatException
* @throws NoAddressIdFoundException
*
* @return int
*/
public function read(PathInfo $file, int $limit, int $lastLineNumber): int
{
$iterator = $this->getFileIterator($file->getPath());
$counter = 0;
$nextLastLineNumber = $lastLineNumber + $limit;
$intermediateEntries = [];
$version = 0;
foreach ($iterator as $line) {
if ($counter === 0) {
$version = $this->getVersionByTypV($line);
}
if ($counter >= $lastLineNumber && $counter < $nextLastLineNumber) {
$type = $this->getLineType($line);
$obj = $this->parseLine($line, $version);
if (!empty($obj)) {
$isEnrich = false;
if ($type === 'A' || $type === 'P') {
$isEnrich = $this->needsEnrichement($type, $obj, $version);
} elseif ($type === 'E' && $version === 4) {
$type = 'T';
}
$articleNumber = '';
if (method_exists($obj, 'getArticleNumber')) {
$articleNumber = $obj->getArticleNumber();
} elseif (method_exists($obj, 'getTextnumber')) {
$articleNumber = $obj->getTextnumber();
}
$intermediateEntries[] = [
'fileName' => $file->getFilename(),
'type' => $type,
'obj' => $obj,
'nummer' => $articleNumber,
'enrich' => $isEnrich,
'directory' => $file->getDir(),
'user_address_id' => $this->getUserIdFromPath($file->getFilename()),
];
}
}
$counter++;
}
if (count($intermediateEntries) > 0) {
$this->intermediateService->writeMultiple($intermediateEntries);
}
if ($nextLastLineNumber - $counter >= 0) {
$isDeleted = $this->deleteFile($file->getPath());
if (!$isDeleted) {
$scriptOwner = @posix_getpwuid(@fileowner(__FILE__));
$scriptGroup = @posix_getgrgid(@filegroup(__FILE__));
$phpUsername = get_current_user();
$msg =
'Could not delete file: ' . $file->getPath() .
', scriptowner: ' . $scriptOwner[0] .
', scriptGroup: ' . $scriptGroup[0] .
', phpUsername: ' . $phpUsername;
throw new FileSystemException($msg);
}
$nextLastLineNumber = -1;
}
return $nextLastLineNumber;
}
/**
* @param string $fileName
*
* @return int
*/
private function getUserIdFromPath(string $fileName): int
{
$pos = strstr($fileName, '_', true);
if (strstr($fileName, '_') === false) {
throw new NoAddressIdFoundException('No user-id found in filename: ' . $fileName);
} else {
return (int)$pos;
}
}
/**
* @param string $line
* @param int $version
*
* @throws WrongVersionException
* @throws WrongPriceFormatException
* @throws WrongDiscountFormatException
*
* @return null|DatanormTypeDataInterface
*/
private function parseLine(string $line, int $version): ?DatanormTypeDataInterface
{
$readerHandler = $this->getReaderHandler($version);
$line = iconv('CP850', 'UTF-8', $line);
$obj = null;
$type = $this->getLineType($line);
switch ($type) {
case 'A':
$obj = $readerHandler->transformToTypeA($line);
break;
case'P':
$obj = $readerHandler->transformToTypeP($line);
break;
case'V':
$obj = $readerHandler->transformToTypeV($line);
break;
case'B':
$obj = $readerHandler->transformToTypeB($line);
break;
case'E':
if ($version === 4) {
$obj = $readerHandler->transformToTypeT($line);
}
break;
case'T':
$obj = $readerHandler->transformToTypeT($line);
break;
case'D':
$obj = $readerHandler->transformToTypeD($line);
break;
}
return $obj;
}
/**
* @param int $version
*
* @throws WrongVersionException
*
* @return DatanormReaderHandlerInterface
*/
private function getReaderHandler(int $version): DatanormReaderHandlerInterface
{
$readerHandler = null;
foreach ($this->readerHandlers as $r) {
if ($r->getVersion() === $version) {
$readerHandler = $r;
break;
}
}
if (empty($readerHandler)) {
throw new WrongVersionException(
'The DATANORM-Version is not supported. Only ' .
implode(', ', $this->readerVersions) . ' are allowed. Requested version was: ' . $version
);
}
return $readerHandler;
}
/**
* @param string $filePath Relative path to filesystem-class root
*
* @throws FileNotFoundException
*
* @return Generator
*/
private function getFileIterator(string $filePath): Generator
{
$stream = $this->filesystem->readStream($filePath);
while ($line = fgets($stream)) {
yield $line;
}
if (is_resource($stream)) {
fclose($stream);
}
}
/**
* @param string $line
*
* @throws InvalidLineException
*
* @return string
*/
private function getLineType(string $line): string
{
$lineType = substr(trim($line), 0, 1);
if ($lineType === false || empty($lineType)) {
throw new InvalidLineException('Unknown linetype in this line: ' . $line);
}
return $lineType;
}
/**
* @param string $line
*
* @throws WrongVersionException
*
* @return int
*/
private function getVersionByTypV(string $line): int
{
$v5indicator = false;
$split = explode(';', $line);
if (isset($split[1])) {
$v5indicator = $split[1] === '050';
}
$v4indicator = false;
if (strlen($line) > 123) {
$v4indicator = trim(substr($line, 123, 2)) === '04';
}
if ($v5indicator) {
return 5;
} elseif ($v4indicator) {
return 4;
}
throw new WrongVersionException('DATANORM-Version not found.');
}
/**
* @param string $path
*
* @throws FileNotFoundException
*
* @return bool
*/
public function deleteFile(string $path): bool
{
return $this->filesystem->delete($path);
}
/**
* @return array|PathInfo[]
*/
public function listUploadedDatanormFiles(): array
{
return $this->filesystem->listFiles($this->uploadDir);
}
/**
* @param string $type
* @param DatanormTypeDataInterface $object
* @param int $version
*
* @return bool
*/
private function needsEnrichement(string $type, DatanormTypeDataInterface $object, int $version): bool
{
if ($version === 4 && $type === 'P') {
return true;
}
if ($type === 'A' && method_exists($object, 'getTextkey')) {
$textFlag = '0';
if (!empty($object->getTextkey())) {
$textFlag = substr($object->getTextkey(), 0, 1);
}
if ($textFlag != '0') {
return true;
}
}
return false;
}
}