Миграции мета-тегов Битрикс
Миграция SEO свойств
php
<?php
namespace Sprint\Migration;
use Bitrix\Iblock\ElementTable;
use Bitrix\Iblock\InheritedProperty\ElementValues;
use Bitrix\Iblock\InheritedProperty\SectionValues;
use Bitrix\Iblock\InheritedPropertyTable;
use Bitrix\Iblock\SectionTable;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\Loader;
use Bitrix\Main\LoaderException;
use Bitrix\Main\ObjectPropertyException;
use Bitrix\Main\SystemException;
use Exception;
use Sprint\Migration\Exceptions\HelperException;
class Version20241231000000 extends Version
{
protected $description = "Описание";
protected $moduleVersion = "4.2.4";
/**
* @return void
* @throws Exceptions\MigrationException
* @throws Exceptions\RestartException
*/
public function up(): void
{
$this->run('up/iproperties.xml');
}
/**
* @return void
* @throws Exceptions\MigrationException
* @throws Exceptions\RestartException
*/
public function down(): void
{
$this->run('down/iproperties.xml');
}
/**
* @param string $path
* @return void
* @throws Exceptions\MigrationException
* @throws Exceptions\RestartException
*/
public function run(string $path): void
{
$this->getExchangeManager()
->IblockElementsImport()
->setExchangeResource($path)
->setLimit(5)
->execute(function ($item) {
$this->saveIProperties($item['fields']);
});
}
/**
* @param array $arEntity
* @return void
* @throws HelperException
* @throws ArgumentException
* @throws LoaderException
* @throws ObjectPropertyException
* @throws SystemException
* @throws Exception
*/
protected function saveIProperties(array $arEntity): void
{
Loader::includeModule('iblock');
$codePrefix = $this->getCodePrefixByType($arEntity['ENTITY_TYPE']);
$ormClass = $this->getOrmClassByType($arEntity['ENTITY_TYPE']);
$iblockId = $this->getIblockId($arEntity['IBLOCK_UID']);
$entityId = $this->getEntityId($ormClass, [
'IBLOCK_ID' => $iblockId,
'CODE' => $arEntity['CODE'],
]);
$iPropCodes = array_filter(array_map(function ($code) use ($arEntity, $codePrefix) {
return isset($arEntity[$code]) ? $codePrefix . $code : null;
}, ["META_TITLE", "META_DESCRIPTION", "PAGE_TITLE"]));
$iProps = InheritedPropertyTable::getList([
'select' => ['ID', 'CODE', 'ENTITY_ID'],
'filter' => [
'IBLOCK_ID' => $iblockId,
'ENTITY_ID' => $entityId,
'CODE' => $iPropCodes
]
])->fetchAll();
foreach ($iPropCodes as $iPropCode) {
$newPropValue = trim($arEntity[str_replace($codePrefix, '', $iPropCode)]);
$found = false;
foreach ($iProps as $iProp) {
if ($iProp['CODE'] == $iPropCode) {
$found = true;
if ($newPropValue) {
InheritedPropertyTable::update($iProp['ID'], ["TEMPLATE" => $newPropValue]);
} else {
InheritedPropertyTable::delete($iProp['ID']);
}
}
}
if (!$found) {
InheritedPropertyTable::add([
'IBLOCK_ID' => $iblockId,
'CODE' => $iPropCode,
'ENTITY_TYPE' => $arEntity['ENTITY_TYPE'],
'ENTITY_ID' => $entityId,
'TEMPLATE' => $newPropValue
]);
}
}
$iPropValuesClass = $this->getIPropValuesClassByType($arEntity['ENTITY_TYPE']);
$ipropValues = new $iPropValuesClass($iblockId, $entityId);
$ipropValues->clearValues();
}
/**
* @param string $ormClass
* @param array $filter
* @return int
* @throws HelperException
*/
protected function getEntityId(string $ormClass, array $filter): int
{
$element = $ormClass::getList([
'select' => ['ID'],
'filter' => $filter,
'limit' => 1,
])->fetch();
if (!$element) {
throw new HelperException("Could not find " . json_encode($filter) . " at " . $ormClass);
}
return intval($element['ID']);
}
/**
* @param string $uid
* @return int
* @throws HelperException
*/
protected function getIblockId(string $uid): int
{
$result = $this->getHelperManager()->Iblock()->getIblockIdByUid($uid);
if (!$result) {
throw new HelperException("Iblock " . $uid . " not found");
}
return $result;
}
/**
* @param mixed $type
* @return string
* @throws HelperException
*/
protected function getCodePrefixByType(mixed $type): string
{
return $this->getByType($type, 'SECTION_', 'ELEMENT_');
}
/**
* @param mixed $type
* @return string
* @throws HelperException
*/
protected function getOrmClassByType(mixed $type): string
{
return "\\" . $this->getByType($type, SectionTable::class, ElementTable::class);
}
/**
* @param mixed $type
* @return string
* @throws HelperException
*/
public function getIPropValuesClassByType(mixed $type): string
{
return "\\" . $this->getByType($type, SectionValues::class, ElementValues::class);
}
/**
* @param mixed $entityType
* @param mixed $sectionResult
* @param mixed $elementResult
* @return mixed
* @throws HelperException
*/
protected function getByType(mixed $entityType, mixed $sectionResult, mixed $elementResult): mixed
{
return match ($entityType) {
'S' => $sectionResult,
'E' => $elementResult,
default => throw new HelperException("Undefined ENTITY_TYPE: " . $entityType),
};
}
}
XML файл
up|down
iproperties.xml
xml
<?xml version="1.0" encoding="UTF-8"?>
<items iblockUid="catalog:IB_CATALOG" exchangeVersion="2">
<item>
<field name="CODE">
<value>code</value>
</field>
<field name="ENTITY_TYPE">
<value>E</value>
</field>
<field name="IBLOCK_UID">
<value>catalog:IB_CATALOG</value>
</field>
<field name="META_TITLE">
<value>Meta title</value>
</field>
<field name="META_DESCRIPTION">
<value>Meta description</value>
</field>
<field name="PAGE_TITLE">
<value>Page title</value>
</field>
</item>
</items>
Миграция наследование
php
<?php
namespace Sprint\Migration;
require_once __DIR__ . '/Version20241231000000.php';
class Version20240101000000 extends Version20241231000000
{
protected $description = "Описание";
protected $moduleVersion = "4.2.4";
}