263 lines
9.0 KiB
PHP
263 lines
9.0 KiB
PHP
<?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 ?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 "https://api.sovamed.ru/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 = "https://api.sovamed.ru/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');
|
|
}
|
|
} |