chore: initial import for test contour
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\XmlFeedGenerator;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use App\Dto\SpecialistFilterDto;
|
||||
use App\Entity\Filial;
|
||||
use App\Entity\Specialist;
|
||||
use App\Service\PriceList\PriceListService;
|
||||
use App\Service\Specialist\SpecialistService;
|
||||
use App\Service\Helper\HelperService;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class XmlFeedGeneratorV1Service
|
||||
{
|
||||
private DOMDocument $dom;
|
||||
private Filial $filial;
|
||||
|
||||
/** @var array<int, Filial> */
|
||||
private array $filialsByFid = [];
|
||||
|
||||
public function __construct(
|
||||
private PriceListService $priceListService,
|
||||
private SpecialistService $specialistService,
|
||||
private HelperService $helperService,
|
||||
private Connection $connection,
|
||||
private string $apiPublicUrl,
|
||||
private ?LoggerInterface $logger = null,
|
||||
) {
|
||||
$this->dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$this->dom->formatOutput = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Filial|Filial[] $filials один филиал или массив филиалов (например, по региону)
|
||||
*/
|
||||
public function generateFeed(Filial|array $filials): string
|
||||
{
|
||||
$filialList = is_array($filials) ? $filials : [$filials];
|
||||
if ($filialList === []) {
|
||||
$this->dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$this->dom->formatOutput = true;
|
||||
return $this->dom->saveXML();
|
||||
}
|
||||
|
||||
$this->dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$this->dom->formatOutput = true;
|
||||
|
||||
$this->filial = $filialList[0];
|
||||
$this->filialsByFid = [];
|
||||
foreach ($filialList as $f) {
|
||||
$this->filialsByFid[$f->getFid()] = $f;
|
||||
}
|
||||
|
||||
$ymlCatalog = $this->dom->createElement('yml_catalog');
|
||||
$ymlCatalog->setAttribute('date', date('Y-m-d H:i'));
|
||||
$this->dom->appendChild($ymlCatalog);
|
||||
|
||||
$shop = $this->dom->createElement('shop');
|
||||
$ymlCatalog->appendChild($shop);
|
||||
|
||||
$this->addShopInfo($shop);
|
||||
$this->addCurrencies($shop);
|
||||
$this->addCategories($shop);
|
||||
$this->addSets($shop);
|
||||
$this->addOffers($shop);
|
||||
|
||||
return $this->dom->saveXML();
|
||||
}
|
||||
|
||||
private function addShopInfo(DOMElement $shop): void
|
||||
{
|
||||
$this->addTextElement($shop, 'name', $this->getShopName());
|
||||
$this->addTextElement($shop, 'company', $this->filial->getCompany());
|
||||
$this->addTextElement($shop, 'url', $this->filial->getOrigin());
|
||||
$this->addTextElement($shop, 'email', $this->filial->getEmail());
|
||||
}
|
||||
|
||||
private function addCurrencies(DOMElement $shop): void
|
||||
{
|
||||
$currencies = $this->dom->createElement('currencies');
|
||||
$currency = $this->dom->createElement('currency');
|
||||
$currency->setAttribute('id', 'RUR');
|
||||
$currency->setAttribute('rate', '1');
|
||||
$currencies->appendChild($currency);
|
||||
$shop->appendChild($currencies);
|
||||
}
|
||||
|
||||
private function addCategories(DOMElement $shop): void
|
||||
{
|
||||
$categories = $this->dom->createElement('categories');
|
||||
$category = $this->dom->createElement('category', 'Врач');
|
||||
$category->setAttribute('id', '1');
|
||||
$categories->appendChild($category);
|
||||
$shop->appendChild($categories);
|
||||
}
|
||||
|
||||
private function addSets(DOMElement $shop): void
|
||||
{
|
||||
$sets = $this->dom->createElement('sets');
|
||||
$departments = $this->connection->fetchAllAssociative(
|
||||
'SELECT did, name FROM departments WHERE active = :active ORDER BY id ASC',
|
||||
['active' => true]
|
||||
);
|
||||
|
||||
foreach ($departments as $department) {
|
||||
$set = $this->dom->createElement('set');
|
||||
$set->setAttribute('id', (string) $department['did']);
|
||||
|
||||
$name = $this->dom->createElement('name', (string) $department['name']);
|
||||
$set->appendChild($name);
|
||||
|
||||
$sets->appendChild($set);
|
||||
}
|
||||
|
||||
$shop->appendChild($sets);
|
||||
}
|
||||
|
||||
private function getShopName(): string
|
||||
{
|
||||
return match ($this->filial->getRegionId()) {
|
||||
94 => 'Клиника ВМТ Сова',
|
||||
default => match ($this->filial->getFid()) {
|
||||
9 => 'Совёнок',
|
||||
default => 'Сова',
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private function getShopPicture(): string
|
||||
{
|
||||
$picture = match ($this->filial->getRegionId()) {
|
||||
94 => 'wmtmed.png',
|
||||
default => match ($this->filial->getFid()) {
|
||||
9 => 'sovenok.png',
|
||||
10 => 'comfort.jpg',
|
||||
default => 'sovamed.png',
|
||||
}
|
||||
};
|
||||
|
||||
return rtrim($this->apiPublicUrl, '/') . "/images/logo/{$picture}";
|
||||
}
|
||||
|
||||
private function getSpecialistLink(Specialist $specialist): string
|
||||
{
|
||||
$url = $this->filial->getOrigin();
|
||||
$url .= match ($this->filial->getId()) {
|
||||
9 => '/doctors/',
|
||||
14 => '/doctors/',
|
||||
10 => '/doctors/',
|
||||
8 => '/specialisty',
|
||||
default => '/vrachi'
|
||||
};
|
||||
|
||||
if (!in_array($this->filial->getId(), [9, 14, 10])) {
|
||||
$sType = $specialist->getSType();
|
||||
if ($sType !== null) {
|
||||
$url .= match ($sType) {
|
||||
0 => '/vzroslyj-vrach/',
|
||||
1 => '/detskij-vrach/',
|
||||
2 => '/administraciya/',
|
||||
default => '/vzroslyj-vrach/',
|
||||
};
|
||||
} else {
|
||||
$this->logger?->info('Specialist type is not set', ['specialist' => $specialist->getId()]);
|
||||
}
|
||||
}
|
||||
$url .= $specialist->getAlias();
|
||||
$url .= '/';
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
private function getCity(): string
|
||||
{
|
||||
return match ((int) $this->filial->getRegionId()) {
|
||||
91 => 'Саратов',
|
||||
92 => 'Волгоград',
|
||||
93 => 'Воронеж',
|
||||
94 => 'Краснодар',
|
||||
default => ''
|
||||
};
|
||||
}
|
||||
|
||||
private function addOffers(DOMElement $shop): void
|
||||
{
|
||||
$offersElement = $this->dom->createElement('offers');
|
||||
|
||||
$fids = array_keys($this->filialsByFid);
|
||||
if ($fids === []) {
|
||||
$shop->appendChild($offersElement);
|
||||
return;
|
||||
}
|
||||
|
||||
$filter = new SpecialistFilterDto();
|
||||
$filter->kiosk = true;
|
||||
$filter->sFilial = array_map('strval', $fids);
|
||||
$specialistList = $this->specialistService->getList($filter);
|
||||
|
||||
foreach ($specialistList as $specialist) {
|
||||
$specialistDescription = $specialist->getPost();
|
||||
|
||||
$offerElement = $this->dom->createElement('offer');
|
||||
$offerElement->setAttribute('id', (string) $specialist->getId());
|
||||
$url = $this->getSpecialistLink($specialist);
|
||||
$experience = $specialist->getExperience();
|
||||
$experienceYears = $experience && is_numeric($experience) && $experience > 1900 && $experience <= date('Y')
|
||||
? date('Y') - (int) $experience
|
||||
: null;
|
||||
|
||||
if ($experienceYears !== null) {
|
||||
$specialistDescription .= ' с опытом работы ' . $this->helperService->textYear($experienceYears, true);
|
||||
}
|
||||
$specialistDescription .= '. Запись к специалисту на сайте';
|
||||
|
||||
$this->addTextElement($offerElement, 'name', $specialist->getName() ?? '');
|
||||
$this->addTextElement($offerElement, 'description', $specialistDescription ?? '');
|
||||
$this->addTextElement($offerElement, 'url', $url);
|
||||
$this->addTextElement($offerElement, 'set-ids', $specialist->getDcodes());
|
||||
|
||||
$picture = rtrim($this->apiPublicUrl, '/') . "/specialist/picture/{$specialist->getId()}";
|
||||
$this->addTextElement($offerElement, 'picture', $picture);
|
||||
$this->addTextElement($offerElement, 'categoryId', '1');
|
||||
$this->addTextElement($offerElement, 'currencyId', 'RUR');
|
||||
$offersElement->appendChild($offerElement);
|
||||
}
|
||||
|
||||
$shop->appendChild($offersElement);
|
||||
}
|
||||
|
||||
private function addTextElement(DOMElement $parent, string $name, $value): void
|
||||
{
|
||||
if ($value !== null && $value !== '') {
|
||||
$parent->appendChild($this->dom->createElement($name, $this->prepareXmlContent((string)$value)));
|
||||
}
|
||||
}
|
||||
|
||||
private function addParamElement(DOMElement $parent, string $name, $value): void
|
||||
{
|
||||
if ($value !== null && $value !== '') {
|
||||
$param = $this->dom->createElement('param', $this->prepareXmlContent((string)$value));
|
||||
$param->setAttribute('name', $name);
|
||||
$parent->appendChild($param);
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareXmlContent($content): string
|
||||
{
|
||||
$content = str_replace('&', '&', $content);
|
||||
$validEntities = [
|
||||
'&nbsp;' => ' ',
|
||||
'&amp;' => '&',
|
||||
'&lt;' => '<',
|
||||
'&gt;' => '>',
|
||||
'&quot;' => '"',
|
||||
'&apos;' => '''
|
||||
];
|
||||
$content = str_replace(array_keys($validEntities), array_values($validEntities), $content);
|
||||
|
||||
return htmlspecialchars($content, ENT_XML1 | ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user