issues/27: prod baseline without task branch

This commit is contained in:
Valery Petrov
2026-05-28 19:54:31 +03:00
parent f8f03fe849
commit 8579fe3472
31 changed files with 1468 additions and 986 deletions
+301 -116
View File
@@ -2,127 +2,312 @@
namespace App\Service;
use App\Entity\MedicalCenter;
use App\Repository\MedicalCenterRepository;
use Doctrine\ORM\EntityManagerInterface;
/**
* Импорт центров из материализованного представления (Bitrix view).
*
* См. MedicalCenterController + CrudResponder для CRUD; этот сервис — только syncFromView*.
*/
final class MedicalCenterCrudService
{
public function __construct(
private EntityManagerInterface $em,
) {
}
public function __construct(
private EntityManagerInterface $em,
private MedicalCenterRepository $medicalCenterRepository
) {
}
public function syncFromViewCenters(string $viewName = 'public.view_centers'): int
{
if (!preg_match('/^[A-Za-z0-9_\.]+$/', $viewName)) {
throw new \InvalidArgumentException('Invalid view name');
}
/**
* @return MedicalCenter[]
*/
public function getList(?int $regionId = null, ?bool $active = true): array
{
$criteria = [];
if ($regionId !== null) {
$criteria['regionId'] = $regionId;
}
if ($active !== null) {
$criteria['active'] = $active;
}
$sql = sprintf(
'INSERT INTO medical_center (
id,
name,
active,
region_id,
alias,
anons,
content,
update_at,
kod_uslug,
doctors,
services,
articles,
txt_up,
main_link_staff,
contraindications,
hide_picture,
indications,
link_sale,
plus_list,
plus_text,
plus_title,
process_text,
process_title,
services_list,
services_photos,
services_title,
sort_staff,
training_text,
training_text_title,
why_text,
why_title
)
SELECT
id,
name,
active,
region_id,
alias,
anons,
content,
update_at,
kod_uslug,
doctors,
services,
articles,
txt_up,
main_link_staff,
contraindications,
hide_picture,
indications,
link_sale,
plus_list,
plus_text,
plus_title,
process_text,
process_title,
services_list,
services_photos,
services_title,
sort_staff,
training_text,
training_text_title,
why_text,
why_title
FROM %s
ON CONFLICT (id) DO UPDATE SET
name = EXCLUDED.name,
active = EXCLUDED.active,
region_id = EXCLUDED.region_id,
alias = EXCLUDED.alias,
anons = EXCLUDED.anons,
content = EXCLUDED.content,
update_at = EXCLUDED.update_at,
kod_uslug = EXCLUDED.kod_uslug,
doctors = EXCLUDED.doctors,
services = EXCLUDED.services,
articles = EXCLUDED.articles,
txt_up = EXCLUDED.txt_up,
main_link_staff = EXCLUDED.main_link_staff,
contraindications = EXCLUDED.contraindications,
hide_picture = EXCLUDED.hide_picture,
indications = EXCLUDED.indications,
link_sale = EXCLUDED.link_sale,
plus_list = EXCLUDED.plus_list,
plus_text = EXCLUDED.plus_text,
plus_title = EXCLUDED.plus_title,
process_text = EXCLUDED.process_text,
process_title = EXCLUDED.process_title,
services_list = EXCLUDED.services_list,
services_photos = EXCLUDED.services_photos,
services_title = EXCLUDED.services_title,
sort_staff = EXCLUDED.sort_staff,
training_text = EXCLUDED.training_text,
training_text_title = EXCLUDED.training_text_title,
why_text = EXCLUDED.why_text,
why_title = EXCLUDED.why_title',
$viewName
);
return $this->medicalCenterRepository->findBy($criteria, ['id' => 'ASC']);
}
return (int) $this->em->getConnection()->executeStatement($sql);
}
public function getShow(int $id): ?MedicalCenter
{
return $this->medicalCenterRepository->find($id);
}
public function create(array $data): MedicalCenter
{
$medicalCenter = new MedicalCenter();
$this->updateEntity($medicalCenter, $data);
$this->em->persist($medicalCenter);
$this->em->flush();
return $medicalCenter;
}
public function update(MedicalCenter $medicalCenter, array $data): MedicalCenter
{
unset($data['id']);
$this->updateEntity($medicalCenter, $data);
$this->em->flush();
return $medicalCenter;
}
public function delete(MedicalCenter $medicalCenter): void
{
$this->em->remove($medicalCenter);
$this->em->flush();
}
private function updateEntity(MedicalCenter $medicalCenter, array $data): void
{
if (array_key_exists('id', $data) && $data['id'] !== null && $data['id'] !== '') {
$medicalCenter->setId((int) $data['id']);
}
if (array_key_exists('name', $data)) {
$medicalCenter->setName($data['name']);
}
if (array_key_exists('active', $data)) {
$medicalCenter->setActive($data['active']);
}
if (array_key_exists('regionId', $data) || array_key_exists('region_id', $data)) {
$v = $data['regionId'] ?? $data['region_id'];
$medicalCenter->setRegionId($v === null || $v === '' ? null : (int) $v);
}
if (array_key_exists('alias', $data)) {
$medicalCenter->setAlias($data['alias']);
}
if (array_key_exists('anons', $data)) {
$medicalCenter->setAnons($data['anons']);
}
if (array_key_exists('content', $data)) {
$medicalCenter->setContent($data['content']);
}
if (array_key_exists('updateAt', $data) || array_key_exists('update_at', $data)) {
$raw = $data['updateAt'] ?? $data['update_at'];
if ($raw === null || $raw === '') {
$medicalCenter->setUpdateAt(null);
} elseif ($raw instanceof \DateTimeInterface) {
$medicalCenter->setUpdateAt($raw);
} elseif (is_string($raw)) {
$medicalCenter->setUpdateAt(new \DateTimeImmutable($raw));
}
}
if (array_key_exists('kodUslug', $data) || array_key_exists('kod_uslug', $data)) {
$medicalCenter->setKodUslug($data['kodUslug'] ?? $data['kod_uslug']);
}
if (array_key_exists('doctors', $data)) {
$medicalCenter->setDoctors($data['doctors']);
}
if (array_key_exists('services', $data)) {
$medicalCenter->setServices($data['services']);
}
if (array_key_exists('articles', $data)) {
$medicalCenter->setArticles($data['articles']);
}
if (array_key_exists('txtUp', $data) || array_key_exists('txt_up', $data)) {
$medicalCenter->setTxtUp($data['txtUp'] ?? $data['txt_up']);
}
if (array_key_exists('mainLinkStaff', $data) || array_key_exists('main_link_staff', $data)) {
$medicalCenter->setMainLinkStaff($data['mainLinkStaff'] ?? $data['main_link_staff']);
}
if (array_key_exists('contraindications', $data)) {
$medicalCenter->setContraindications($data['contraindications']);
}
if (array_key_exists('hidePicture', $data) || array_key_exists('hide_picture', $data)) {
$v = $data['hidePicture'] ?? $data['hide_picture'];
$medicalCenter->setHidePicture($v === null || $v === '' ? null : (int) $v);
}
if (array_key_exists('indications', $data)) {
$medicalCenter->setIndications($data['indications']);
}
if (array_key_exists('linkSale', $data) || array_key_exists('link_sale', $data)) {
$medicalCenter->setLinkSale($data['linkSale'] ?? $data['link_sale']);
}
if (array_key_exists('plusList', $data) || array_key_exists('plus_list', $data)) {
$medicalCenter->setPlusList($data['plusList'] ?? $data['plus_list']);
}
if (array_key_exists('plusText', $data) || array_key_exists('plus_text', $data)) {
$medicalCenter->setPlusText($data['plusText'] ?? $data['plus_text']);
}
if (array_key_exists('plusTitle', $data) || array_key_exists('plus_title', $data)) {
$medicalCenter->setPlusTitle($data['plusTitle'] ?? $data['plus_title']);
}
if (array_key_exists('processText', $data) || array_key_exists('process_text', $data)) {
$medicalCenter->setProcessText($data['processText'] ?? $data['process_text']);
}
if (array_key_exists('processTitle', $data) || array_key_exists('process_title', $data)) {
$medicalCenter->setProcessTitle($data['processTitle'] ?? $data['process_title']);
}
if (array_key_exists('servicesList', $data) || array_key_exists('services_list', $data)) {
$medicalCenter->setServicesList($data['servicesList'] ?? $data['services_list']);
}
if (array_key_exists('servicesPhotos', $data) || array_key_exists('services_photos', $data)) {
$medicalCenter->setServicesPhotos($data['servicesPhotos'] ?? $data['services_photos']);
}
if (array_key_exists('servicesTitle', $data) || array_key_exists('services_title', $data)) {
$medicalCenter->setServicesTitle($data['servicesTitle'] ?? $data['services_title']);
}
if (array_key_exists('sortStaff', $data) || array_key_exists('sort_staff', $data)) {
$medicalCenter->setSortStaff($data['sortStaff'] ?? $data['sort_staff']);
}
if (array_key_exists('trainingText', $data) || array_key_exists('training_text', $data)) {
$medicalCenter->setTrainingText($data['trainingText'] ?? $data['training_text']);
}
if (array_key_exists('trainingTextTitle', $data) || array_key_exists('training_text_title', $data)) {
$medicalCenter->setTrainingTextTitle($data['trainingTextTitle'] ?? $data['training_text_title']);
}
if (array_key_exists('whyText', $data) || array_key_exists('why_text', $data)) {
$medicalCenter->setWhyText($data['whyText'] ?? $data['why_text']);
}
if (array_key_exists('whyTitle', $data) || array_key_exists('why_title', $data)) {
$medicalCenter->setWhyTitle($data['whyTitle'] ?? $data['why_title']);
}
}
public function syncFromViewCenters(string $viewName = 'public.view_centers'): int
{
// В опции разрешаем только идентификаторы (буквы/цифры/underscore) и точку для схемы.
if (!preg_match('/^[A-Za-z0-9_\.]+$/', $viewName)) {
throw new \InvalidArgumentException('Invalid view name');
}
$connection = $this->em->getConnection();
$sql = sprintf(
'INSERT INTO medical_center (
id,
name,
active,
region_id,
alias,
anons,
content,
update_at,
kod_uslug,
doctors,
services,
articles,
txt_up,
main_link_staff,
contraindications,
hide_picture,
indications,
link_sale,
plus_list,
plus_text,
plus_title,
process_text,
process_title,
services_list,
services_photos,
services_title,
sort_staff,
training_text,
training_text_title,
why_text,
why_title
)
SELECT
id,
name,
active,
region_id,
alias,
anons,
content,
update_at,
kod_uslug,
doctors,
services,
articles,
txt_up,
main_link_staff,
contraindications,
hide_picture,
indications,
link_sale,
plus_list,
plus_text,
plus_title,
process_text,
process_title,
services_list,
services_photos,
services_title,
sort_staff,
training_text,
training_text_title,
why_text,
why_title
FROM %s
ON CONFLICT (id) DO UPDATE SET
name = EXCLUDED.name,
active = EXCLUDED.active,
region_id = EXCLUDED.region_id,
alias = EXCLUDED.alias,
anons = EXCLUDED.anons,
content = EXCLUDED.content,
update_at = EXCLUDED.update_at,
kod_uslug = EXCLUDED.kod_uslug,
doctors = EXCLUDED.doctors,
services = EXCLUDED.services,
articles = EXCLUDED.articles,
txt_up = EXCLUDED.txt_up,
main_link_staff = EXCLUDED.main_link_staff,
contraindications = EXCLUDED.contraindications,
hide_picture = EXCLUDED.hide_picture,
indications = EXCLUDED.indications,
link_sale = EXCLUDED.link_sale,
plus_list = EXCLUDED.plus_list,
plus_text = EXCLUDED.plus_text,
plus_title = EXCLUDED.plus_title,
process_text = EXCLUDED.process_text,
process_title = EXCLUDED.process_title,
services_list = EXCLUDED.services_list,
services_photos = EXCLUDED.services_photos,
services_title = EXCLUDED.services_title,
sort_staff = EXCLUDED.sort_staff,
training_text = EXCLUDED.training_text,
training_text_title = EXCLUDED.training_text_title,
why_text = EXCLUDED.why_text,
why_title = EXCLUDED.why_title',
$viewName
);
return (int) $connection->executeStatement($sql);
}
}