*/ 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'); } }