From 6167ad02245a235aa8c299508cf6afb663e5f868 Mon Sep 17 00:00:00 2001 From: Ms_Natali Date: Sun, 14 Oct 2018 22:07:12 +0300 Subject: [PATCH 1/7] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D1=8B=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 + migrator | 9 +- src/BaseMigrations/BitrixMigration.php | 19 + src/Constructors/FieldConstructor.php | 21 + src/Constructors/IBlock.php | 590 +++++++++++++++++++++++++ src/Constructors/IBlockProperty.php | 60 +++ src/Constructors/IBlockType.php | 156 +++++++ src/Interfaces/MigrationInterface.php | 7 + src/Logger.php | 36 ++ src/Migrator.php | 56 ++- src/Storages/BitrixDatabaseStorage.php | 25 ++ templates/default.template | 2 + 12 files changed, 979 insertions(+), 7 deletions(-) create mode 100644 src/Constructors/FieldConstructor.php create mode 100644 src/Constructors/IBlock.php create mode 100644 src/Constructors/IBlockProperty.php create mode 100644 src/Constructors/IBlockType.php create mode 100644 src/Logger.php diff --git a/README.md b/README.md index 94602e3..2ca871d 100644 --- a/README.md +++ b/README.md @@ -258,3 +258,8 @@ Arrilot\BitrixMigrations\Autocreate\Manager::init($_SERVER["DOCUMENT_ROOT"].'/mi 2) Реализовать свой аналог ` Arrilot\BitrixMigrations\Repositories\BitrixDatabaseRepository;` и использовать его. 3) По желанию отключить существующие шаблоны миграций, сделав свои. + +## Конструкторы миграций + +- транзакции +- значения по умолчанию \ No newline at end of file diff --git a/migrator b/migrator index 2e2277b..4a35c24 100644 --- a/migrator +++ b/migrator @@ -8,6 +8,7 @@ use Arrilot\BitrixMigrations\Commands\MigrateCommand; use Arrilot\BitrixMigrations\Commands\RollbackCommand; use Arrilot\BitrixMigrations\Commands\TemplatesCommand; use Arrilot\BitrixMigrations\Commands\StatusCommand; +use Arrilot\BitrixMigrations\Constructors\IBlockType; use Arrilot\BitrixMigrations\Migrator; use Arrilot\BitrixMigrations\Storages\BitrixDatabaseStorage; use Arrilot\BitrixMigrations\TemplatesCollection; @@ -19,11 +20,17 @@ $DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"]; require $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php"; CModule::IncludeModule("iblock"); - + $config = [ 'table' => 'migrations', 'dir' => './migrations', // 'dir_archive' => 'archive', // not required. default = "archive" + // 'use_transaction' => false, // not required. default = false + 'default_fields' => [ + IBlockType::class => [ + 'SORT' => 400 + ] + ] ]; $database = new BitrixDatabaseStorage($config['table']); diff --git a/src/BaseMigrations/BitrixMigration.php b/src/BaseMigrations/BitrixMigration.php index 3c6ba6d..ba77294 100644 --- a/src/BaseMigrations/BitrixMigration.php +++ b/src/BaseMigrations/BitrixMigration.php @@ -19,6 +19,11 @@ class BitrixMigration implements MigrationInterface */ protected $db; + /** + * @var bool + */ + public $use_transaction = null; + /** * Constructor. */ @@ -47,6 +52,20 @@ public function down() // } + /** + * Does migration use transaction + * @param bool $default + * @return bool + */ + public function useTransaction($default = false) + { + if (!is_null($this->use_transaction)) { + return $this->use_transaction; + } + + return $default; + } + /** * Find iblock id by its code. * diff --git a/src/Constructors/FieldConstructor.php b/src/Constructors/FieldConstructor.php new file mode 100644 index 0000000..dc5e3f1 --- /dev/null +++ b/src/Constructors/FieldConstructor.php @@ -0,0 +1,21 @@ +fields); + } +} \ No newline at end of file diff --git a/src/Constructors/IBlock.php b/src/Constructors/IBlock.php new file mode 100644 index 0000000..7d94ecf --- /dev/null +++ b/src/Constructors/IBlock.php @@ -0,0 +1,590 @@ +Add($this->getFieldsWithDefault())) { + throw new \Exception($obj->LAST_ERROR); + } + + Logger::log("Добавлен инфоблок {$this->fields['ID']}", Logger::COLOR_GREEN); + } + + /** + * Обновить инфоблок + * @param $id + * @throws \Exception + */ + public function update($id) + { + $obj = new \CIBlock(); + if (!$obj->Update($id, $this->fields)) { + throw new \Exception($obj->LAST_ERROR); + } + + Logger::log("Обновлен инфоблок {$id}", Logger::COLOR_GREEN); + } + + /** + * Удалить инфоблок + * @param $id + * @throws \Exception + */ + public static function delete($id) + { + Application::getConnection()->startTransaction(); + if (!\CIBlock::Delete($id)) { + Application::getConnection()->rollbackTransaction(); + throw new \Exception('Ошибка при удалении инфоблока'); + } + + Application::getConnection()->commitTransaction(); + + Logger::log("Удален инфоблок {$id}", Logger::COLOR_GREEN); + } + + /** + * ID информационного блока. + * @param string $id + * @return $this + */ + public function setId($id) + { + $this->fields['ID'] = $id; + + return $this; + } + + /** + * ID сайта. + * @param string $siteId + * @return $this + */ + public function setSiteId($siteId) + { + $this->fields['SITE_ID'] = $siteId; + + return $this; + } + + /** + * Символьный идентификатор. + * @param string $code + * @return $this + */ + public function setCode($code) + { + $this->fields['CODE'] = $code; + + return $this; + } + + /** + * Внешний код. + * @param string $xml_id + * @return $this + */ + public function setXmlId($xml_id) + { + $this->fields['XML_ID'] = $xml_id; + + return $this; + } + + /** + * Внешний код. + * @param string $iblockTypeId + * @return $this + */ + public function setIblockTypeId($iblockTypeId) + { + $this->fields['IBLOCK_TYPE_ID'] = $iblockTypeId; + + return $this; + } + + /** + * Название. + * @param string $name + * @return $this + */ + public function setName($name) + { + $this->fields['NAME'] = $name; + + return $this; + } + + /** + * Флаг активности + * @param bool $active + * @return $this + */ + public function setActive($active = true) + { + $this->fields['ACTIVE'] = $active ? 'Y' : 'N'; + + return $this; + } + + /** + * Индекс сортировки. + * @param int $sort + * @return $this + */ + public function setSort($sort = 500) + { + $this->fields['SORT'] = $sort; + + return $this; + } + + /** + * Шаблон URL-а к странице для публичного просмотра списка элементов информационного блока. + * @param string $listPageUrl + * @return $this + */ + public function setListPageUrl($listPageUrl) + { + $this->fields['LIST_PAGE_URL'] = $listPageUrl; + + return $this; + } + + /** + * Шаблон URL-а к странице для просмотра раздела. + * @param string $sectionPageUrl + * @return $this + */ + public function setSectionPageUrl($sectionPageUrl) + { + $this->fields['SECTION_PAGE_URL'] = $sectionPageUrl; + + return $this; + } + + /** + * Канонический URL элемента. + * @param string $canonicalPageUrl + * @return $this + */ + public function setCanonicalPageUrl($canonicalPageUrl) + { + $this->fields['CANONICAL_PAGE_URL'] = $canonicalPageUrl; + + return $this; + } + + /** + * Код картинки в таблице файлов. + * @param array $picture + * @return $this + */ + public function setPicture($picture) + { + $this->fields['PICTURE'] = $picture; + + return $this; + } + + /** + * Описание. + * @param string $description + * @return $this + */ + public function setDescription($description) + { + $this->fields['DESCRIPTION'] = $description; + + return $this; + } + + /** + * Тип описания (text/html) + * @param string $descriptionType + * @return $this + */ + public function setDescriptionType($descriptionType = 'text') + { + $this->fields['DESCRIPTION_TYPE'] = $descriptionType; + + return $this; + } + + /** + * Разрешен экспорт в RSS динамически + * @param bool $rssActive + * @return $this + */ + public function setRssActive($rssActive = true) + { + $this->fields['RSS_ACTIVE'] = $rssActive ? 'Y' : 'N'; + + return $this; + } + + /** + * Время жизни RSS и интервал между генерациями файлов RSS (при включенном RSS_FILE_ACTIVE или RSS_YANDEX_ACTIVE) (часов). + * @param int $rssTtl + * @return $this + */ + public function setRssTtl($rssTtl = 24) + { + $this->fields['RSS_TTL'] = $rssTtl; + + return $this; + } + + /** + * Прегенерировать выгрузку в файл. + * @param bool $rssFileActive + * @return $this + */ + public function setRssFileActive($rssFileActive = false) + { + $this->fields['RSS_FILE_ACTIVE'] = $rssFileActive ? 'Y' : 'N'; + + return $this; + } + + /** + * Количество экспортируемых в RSS файл элементов (при включенном RSS_FILE_ACTIVE) + * @param int $rssFileLimit + * @return $this + */ + public function setRssFileLimit($rssFileLimit) + { + $this->fields['RSS_FILE_LIMIT'] = $rssFileLimit; + + return $this; + } + + /** + * За сколько последних дней экспортировать в RSS файл. (при включенном RSS_FILE_ACTIVE). -1 без ограничения по дням. + * @param int $rssFileDays + * @return $this + */ + public function setRssFileDays($rssFileDays) + { + $this->fields['RSS_FILE_DAYS'] = $rssFileDays; + + return $this; + } + + /** + * Экспортировать в RSS файл в формате для yandex + * @param bool $rssYandexActive + * @return $this + */ + public function setRssYandexActive($rssYandexActive = false) + { + $this->fields['RSS_YANDEX_ACTIVE'] = $rssYandexActive ? 'Y' : 'N'; + + return $this; + } + + /** + * Индексировать для поиска элементы информационного блока. + * @param bool $indexElement + * @return $this + */ + public function setIndexElement($indexElement = true) + { + $this->fields['INDEX_ELEMENT'] = $indexElement ? 'Y' : 'N'; + + return $this; + } + + /** + * Индексировать для поиска разделы информационного блока. + * @param bool $indexSection + * @return $this + */ + public function setIndexSection($indexSection = false) + { + $this->fields['INDEX_SECTION'] = $indexSection ? 'Y' : 'N'; + + return $this; + } + + /** + * Режим отображения списка элементов в административном разделе (S|C). + * @param string $listMode + * @return $this + */ + public function setListMode($listMode) + { + $this->fields['LIST_MODE'] = $listMode; + + return $this; + } + + /** + * Режим проверки прав доступа (S|E). + * @param string $rightsMode + * @return $this + */ + public function setRightsMode($rightsMode = 'S') + { + $this->fields['RIGHTS_MODE'] = $rightsMode; + + return $this; + } + + /** + * Признак наличия привязки свойств к разделам (Y|N). + * @param string $sectionProperty + * @return $this + */ + public function setSectionProperty($sectionProperty) + { + $this->fields['SECTION_PROPERTY'] = $sectionProperty; + + return $this; + } + + /** + * Признак наличия фасетного индекса (N|Y|I). + * @param string $propertyIndex + * @return $this + */ + public function setPropertyIndex($propertyIndex) + { + $this->fields['PROPERTY_INDEX'] = $propertyIndex; + + return $this; + } + + /** + * Служебное поле для процедуры конвертации места хранения значений свойств инфоблока. + * @param int $lastConvElement + * @return $this + */ + public function setLastConvElement($lastConvElement) + { + $this->fields['LAST_CONV_ELEMENT'] = $lastConvElement; + + return $this; + } + + /** + * Служебное поле для привязки к группе социальной сети. + * @param int $socnetGroupId + * @return $this + */ + public function setSocnetGroupId($socnetGroupId) + { + $this->fields['SOCNET_GROUP_ID'] = $socnetGroupId; + + return $this; + } + + /** + * Инфоблок участвует в документообороте (Y|N). + * @param bool $workflow + * @return $this + */ + public function setWorkflow($workflow = true) + { + $this->fields['WORKFLOW'] = $workflow ? 'Y' : 'N'; + + return $this; + } + + /** + * Инфоблок участвует в бизнес-процессах (Y|N). + * @param bool $bizproc + * @return $this + */ + public function setBizProc($bizproc = false) + { + $this->fields['BIZPROC'] = $bizproc ? 'Y' : 'N'; + + return $this; + } + + /** + * Флаг выбора интерфейса отображения привязки элемента к разделам (D|L|P). + * @param string $sectionChooser + * @return $this + */ + public function setSectionChooser($sectionChooser) + { + $this->fields['SECTION_CHOOSER'] = $sectionChooser; + + return $this; + } + + /** + * Флаг хранения значений свойств элементов инфоблока (1 - в общей таблице | 2 - в отдельной). + * @param int $version + * @return $this + */ + public function setVersion($version = 1) + { + $this->fields['VERSION'] = $version; + + return $this; + } + + /** + * Полный путь к файлу-обработчику массива полей элемента перед сохранением на странице редактирования элемента. + * @param string $editFileBefore + * @return $this + */ + public function setEditFileBefore($editFileBefore) + { + $this->fields['EDIT_FILE_BEFORE'] = $editFileBefore; + + return $this; + } + + /** + * Полный путь к файлу-обработчику вывода интерфейса редактирования элемента. + * @param string $editFileAfter + * @return $this + */ + public function setEditFileAfter($editFileAfter) + { + $this->fields['EDIT_FILE_AFTER'] = $editFileAfter; + + return $this; + } + + /** + * Название элемента в единственном числе + * @param string $message + * @return $this + */ + public function setMessElementName($message = 'Элемент') + { + $this->fields['ELEMENT_NAME'] = $message; + + return $this; + } + + /** + * Название элемента во множнственном числе + * @param string $message + * @return $this + */ + public function setMessElementsName($message = 'Элементы') + { + $this->fields['ELEMENTS_NAME'] = $message; + + return $this; + } + + /** + * Действие по добавлению элемента + * @param string $message + * @return $this + */ + public function setMessElementAdd($message = 'Добавить элемент') + { + $this->fields['ELEMENT_ADD'] = $message; + + return $this; + } + + /** + * Действие по редактированию/изменению элемента + * @param string $message + * @return $this + */ + public function setMessElementEdit($message = 'Изменить элемент') + { + $this->fields['ELEMENT_EDIT'] = $message; + + return $this; + } + + /** + * Действие по удалению элемента + * @param string $message + * @return $this + */ + public function setMessElementDelete($message = 'Удалить элемент') + { + $this->fields['ELEMENT_DELETE'] = $message; + + return $this; + } + + /** + * Название раздела в единственном числе + * @param string $message + * @return $this + */ + public function setMessSectionName($message = 'Раздел') + { + $this->fields['SECTION_NAME'] = $message; + + return $this; + } + + /** + * Название раздела во множнственном числе + * @param string $message + * @return $this + */ + public function setMessSectionsName($message = 'Разделы') + { + $this->fields['SECTIONS_NAME'] = $message; + + return $this; + } + + /** + * Действие по добавлению раздела + * @param string $message + * @return $this + */ + public function setMessSectionAdd($message = 'Добавить раздел') + { + $this->fields['SECTION_ADD'] = $message; + + return $this; + } + + /** + * Действие по редактированию/изменению раздела + * @param string $message + * @return $this + */ + public function setMessSectionEdit($message = 'Изменить раздел') + { + $this->fields['SECTION_EDIT'] = $message; + + return $this; + } + + /** + * Действие по удалению раздела + * @param string $message + * @return $this + */ + public function setMessSectionDelete($message = 'Удалить раздел') + { + $this->fields['SECTION_DELETE'] = $message; + + return $this; + } + + +} \ No newline at end of file diff --git a/src/Constructors/IBlockProperty.php b/src/Constructors/IBlockProperty.php new file mode 100644 index 0000000..98dbf86 --- /dev/null +++ b/src/Constructors/IBlockProperty.php @@ -0,0 +1,60 @@ +Add($this->getFieldsWithDefault())) { + throw new \Exception($obj->LAST_ERROR); + } + + Logger::log("Добавлено свойство инфоблока {$this->fields['ID']}", Logger::COLOR_GREEN); + } + + /** + * Обновить свойство инфоблока + * @param $id + * @throws \Exception + */ + public function update($id) + { + $obj = new \CIBlockProperty(); + if (!$obj->Update($id, $this->fields)) { + throw new \Exception($obj->LAST_ERROR); + } + + Logger::log("Обновлено свойство инфоблока {$id}", Logger::COLOR_GREEN); + } + + /** + * Удалить свойство инфоблока + * @param $id + * @throws \Exception + */ + public static function delete($id) + { + Application::getConnection()->startTransaction(); + if (!\CIBlockProperty::Delete($id)) { + Application::getConnection()->rollbackTransaction(); + throw new \Exception('Ошибка при удалении свойства инфоблока'); + } + + Application::getConnection()->commitTransaction(); + + Logger::log("Удалено свойство инфоблока {$id}", Logger::COLOR_GREEN); + } +} \ No newline at end of file diff --git a/src/Constructors/IBlockType.php b/src/Constructors/IBlockType.php new file mode 100644 index 0000000..40d2425 --- /dev/null +++ b/src/Constructors/IBlockType.php @@ -0,0 +1,156 @@ +Add($this->getFieldsWithDefault())) { + throw new \Exception($obj->LAST_ERROR); + } + + Logger::log("Добавлен тип инфоблока {$this->fields['ID']}", Logger::COLOR_GREEN); + } + + /** + * Обновить тип инфоблока + * @param $id + * @throws \Exception + */ + public function update($id) + { + $obj = new \CIBlockType(); + if (!$obj->Update($id, $this->fields)) { + throw new \Exception($obj->LAST_ERROR); + } + + Logger::log("Обновлен тип инфоблока {$id}", Logger::COLOR_GREEN); + } + + /** + * Удалить тип инфоблока + * @param $id + * @throws \Exception + */ + public static function delete($id) + { + Application::getConnection()->startTransaction(); + if (!\CIBlockType::Delete($id)) { + Application::getConnection()->rollbackTransaction(); + throw new \Exception('Ошибка при удалении типа инфоблока'); + } + + Application::getConnection()->commitTransaction(); + + Logger::log("Удален тип инфоблока {$id}", Logger::COLOR_GREEN); + } + + /** + * ID типа информационных блоков. Уникален. + * @param string $id + * @return $this + */ + public function setId($id) + { + $this->fields['ID'] = $id; + + return $this; + } + + /** + * Разделяются ли элементы блока этого типа по разделам. + * @param bool $has + * @return $this + */ + public function setSections($has = true) + { + $this->fields['SECTIONS'] = $has ? 'Y' : 'N'; + + return $this; + } + + /** + * Полный путь к файлу-обработчику массива полей элемента перед сохранением на странице редактирования элемента. + * @param string $editFileBefore + * @return $this + */ + public function setEditFileBefore($editFileBefore) + { + $this->fields['EDIT_FILE_BEFORE'] = $editFileBefore; + + return $this; + } + + /** + * Полный путь к файлу-обработчику вывода интерфейса редактирования элемента. + * @param string $editFileAfter + * @return $this + */ + public function setEditFileAfter($editFileAfter) + { + $this->fields['EDIT_FILE_AFTER'] = $editFileAfter; + + return $this; + } + + /** + * Блоки данного типа экспортировать в RSS + * @param bool $inRss + * @return $this + */ + public function setInRss($inRss = false) + { + $this->fields['IN_RSS'] = $inRss ? 'Y' : 'N'; + + return $this; + } + + /** + * Порядок сортировки типа + * @param int $sort + * @return $this + */ + public function setSort($sort = 500) + { + $this->fields['SORT'] = $sort; + + return $this; + } + + /** + * Указать языковые фразы + * @param string $lang ключ языка (ru) + * @param string $name + * @param string $sectionName + * @param string $elementName + * @return $this + */ + public function setLang($lang, $name, $sectionName = null, $elementName = null) + { + $setting = ['NAME' => $name]; + + if ($sectionName) { + $setting['SECTION_NAME'] = $sectionName; + } + if ($elementName) { + $setting['ELEMENT_NAME'] = $elementName; + } + + $this->fields['LANG'][$lang] = $setting; + + return $this; + } +} \ No newline at end of file diff --git a/src/Interfaces/MigrationInterface.php b/src/Interfaces/MigrationInterface.php index 2e9f380..2b667a7 100644 --- a/src/Interfaces/MigrationInterface.php +++ b/src/Interfaces/MigrationInterface.php @@ -17,4 +17,11 @@ public function up(); * @return void */ public function down(); + + /** + * use transaction + * + * @return bool + */ + public function useTransaction($default = false); } diff --git a/src/Logger.php b/src/Logger.php new file mode 100644 index 0000000..64b43bb --- /dev/null +++ b/src/Logger.php @@ -0,0 +1,36 @@ +config = $config; $this->dir = $config['dir']; $this->dir_archive = isset($config['dir_archive']) ? $config['dir_archive'] : 'archive'; + $this->use_transaction = isset($config['use_transaction']) ? $config['use_transaction'] : false; + + if (is_array($config['default_fields'])) { + foreach ($config['default_fields'] as $class => $default_fields) { + FieldConstructor::$defaultFields[$class] = $default_fields; + } + } $this->templates = $templates; $this->database = $database ?: new BitrixDatabaseStorage($config['table']); @@ -141,9 +157,11 @@ public function runMigration($file) $this->disableBitrixIblockHelperCache(); - if ($migration->up() === false) { - throw new Exception("Migration up from {$file}.php returned false"); - } + $this->checkTransactionAndRun($migration, function () use ($migration, $file) { + if ($migration->up() === false) { + throw new Exception("Migration up from {$file}.php returned false"); + } + }); $this->logSuccessfulMigration($file); } @@ -205,9 +223,11 @@ public function rollbackMigration($file) { $migration = $this->getMigrationObjectByFileName($file); - if ($migration->down() === false) { - throw new Exception("Can't rollback migration: {$file}.php"); - } + $this->checkTransactionAndRun($migration, function () use ($migration, $file) { + if ($migration->down() === false) { + throw new Exception("Can't rollback migration: {$file}.php"); + } + }); $this->removeSuccessfulMigrationFromLog($file); } @@ -405,4 +425,28 @@ private function disableBitrixIblockHelperCache() } } } + + /** + * @param MigrationInterface $migration + * @param callable $callback + * @throws Exception + */ + protected function checkTransactionAndRun($migration, $callback) + { + if ($migration->useTransaction($this->use_transaction)) { + $this->database->startTransaction(); + Logger::log("Начало транзакции", Logger::COLOR_LIGHT_BLUE); + try { + $callback(); + } catch (\Exception $e) { + $this->database->rollbackTransaction(); + Logger::log("Откат транзакции из-за ошибки '{$e->getMessage()}'", Logger::COLOR_LIGHT_RED); + throw $e; + } + $this->database->commitTransaction(); + Logger::log("Конец транзакции", Logger::COLOR_LIGHT_BLUE); + } else { + $callback(); + } + } } diff --git a/src/Storages/BitrixDatabaseStorage.php b/src/Storages/BitrixDatabaseStorage.php index 48505b1..1e2772b 100644 --- a/src/Storages/BitrixDatabaseStorage.php +++ b/src/Storages/BitrixDatabaseStorage.php @@ -3,6 +3,7 @@ namespace Arrilot\BitrixMigrations\Storages; use Arrilot\BitrixMigrations\Interfaces\DatabaseStorageInterface; +use Bitrix\Main\Application; use CDatabase; class BitrixDatabaseStorage implements DatabaseStorageInterface @@ -97,4 +98,28 @@ public function removeSuccessfulMigrationFromLog($name) { $this->db->query("DELETE FROM {$this->table} WHERE MIGRATION = '".$this->db->forSql($name)."'"); } + + /** + * Start transaction + */ + public function startTransaction() + { + $this->db->StartTransaction(); + } + + /** + * Commit transaction + */ + public function commitTransaction() + { + $this->db->Commit(); + } + + /** + * Rollback transaction + */ + public function rollbackTransaction() + { + $this->db->Rollback(); + } } diff --git a/templates/default.template b/templates/default.template index 99a85fc..de3e27d 100644 --- a/templates/default.template +++ b/templates/default.template @@ -9,6 +9,7 @@ class __className__ extends BitrixMigration * Run the migration. * * @return mixed + * @throws \Exception */ public function up() { @@ -19,6 +20,7 @@ class __className__ extends BitrixMigration * Reverse the migration. * * @return mixed + * @throws \Exception */ public function down() { From 8a99b628841463d99a0e6aa59ca9531c149dc3a3 Mon Sep 17 00:00:00 2001 From: Ms_Natali Date: Mon, 15 Oct 2018 18:58:13 +0300 Subject: [PATCH 2/7] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- migrator | 9 +- src/Constructors/IBlock.php | 20 +- src/Constructors/IBlockProperty.php | 349 +++++++++++++++++++++++++++- 3 files changed, 365 insertions(+), 13 deletions(-) diff --git a/migrator b/migrator index 4a35c24..66b8fc2 100644 --- a/migrator +++ b/migrator @@ -8,7 +8,7 @@ use Arrilot\BitrixMigrations\Commands\MigrateCommand; use Arrilot\BitrixMigrations\Commands\RollbackCommand; use Arrilot\BitrixMigrations\Commands\TemplatesCommand; use Arrilot\BitrixMigrations\Commands\StatusCommand; -use Arrilot\BitrixMigrations\Constructors\IBlockType; +use Arrilot\BitrixMigrations\Constructors\IBlock; use Arrilot\BitrixMigrations\Migrator; use Arrilot\BitrixMigrations\Storages\BitrixDatabaseStorage; use Arrilot\BitrixMigrations\TemplatesCollection; @@ -27,8 +27,11 @@ $config = [ // 'dir_archive' => 'archive', // not required. default = "archive" // 'use_transaction' => false, // not required. default = false 'default_fields' => [ - IBlockType::class => [ - 'SORT' => 400 + IBlock::class => [ + 'INDEX_ELEMENT' => 'N', + 'INDEX_SECTION' => 'N', + 'VERSION' => 2, + 'SITE_ID' => 's1', ] ] ]; diff --git a/src/Constructors/IBlock.php b/src/Constructors/IBlock.php index 7d94ecf..7354cfc 100644 --- a/src/Constructors/IBlock.php +++ b/src/Constructors/IBlock.php @@ -18,11 +18,15 @@ class IBlock public function add() { $obj = new \CIBlock(); - if (!$obj->Add($this->getFieldsWithDefault())) { + + $iblockId = $obj->Add($this->getFieldsWithDefault()); + if (!$iblockId) { throw new \Exception($obj->LAST_ERROR); } - Logger::log("Добавлен инфоблок {$this->fields['ID']}", Logger::COLOR_GREEN); + Logger::log("Добавлен инфоблок {$this->fields['CODE']}", Logger::COLOR_GREEN); + + return $iblockId; } /** @@ -59,15 +63,15 @@ public static function delete($id) } /** - * ID информационного блока. - * @param string $id + * Установить настройки для добавления инфоблока по умолчанию + * @param $name + * @param $code + * @param $iblock_type_id * @return $this */ - public function setId($id) + public function constructDefault($name, $code, $iblock_type_id) { - $this->fields['ID'] = $id; - - return $this; + return $this->setName($name)->setCode($code)->setIblockTypeId($iblock_type_id); } /** diff --git a/src/Constructors/IBlockProperty.php b/src/Constructors/IBlockProperty.php index 98dbf86..2e2a823 100644 --- a/src/Constructors/IBlockProperty.php +++ b/src/Constructors/IBlockProperty.php @@ -18,11 +18,16 @@ class IBlockProperty public function add() { $obj = new \CIBlockProperty(); - if (!$obj->Add($this->getFieldsWithDefault())) { + + $property_id = $obj->Add($this->getFieldsWithDefault()); + + if (!$property_id) { throw new \Exception($obj->LAST_ERROR); } - Logger::log("Добавлено свойство инфоблока {$this->fields['ID']}", Logger::COLOR_GREEN); + Logger::log("Добавлено свойство инфоблока {$this->fields['CODE']}", Logger::COLOR_GREEN); + + return $property_id; } /** @@ -57,4 +62,344 @@ public static function delete($id) Logger::log("Удалено свойство инфоблока {$id}", Logger::COLOR_GREEN); } + + /** + * Установить настройки для добавления свойства инфоблока по умолчанию + * @param string $code + * @param string $name + * @param int $iblockId + * @return IBlockProperty + */ + public function constructDefault($code, $name, $iblockId) + { + return $this->setPropertyType('S')->setCode($code)->setName($name)->setIblockId($iblockId); + } + + /** + * Символьный идентификатор. + * @param string $code + * @return $this + */ + public function setCode($code) + { + $this->fields['CODE'] = $code; + + return $this; + } + + /** + * Внешний код. + * @param string $xml_id + * @return $this + */ + public function setXmlId($xml_id) + { + $this->fields['XML_ID'] = $xml_id; + + return $this; + } + + /** + * Код информационного блока. + * @param string $iblock_id + * @return $this + */ + public function setIblockId($iblock_id) + { + $this->fields['IBLOCK_ID'] = $iblock_id; + + return $this; + } + + /** + * Название. + * @param string $name + * @return $this + */ + public function setName($name) + { + $this->fields['NAME'] = $name; + + return $this; + } + + /** + * Флаг активности + * @param bool $active + * @return $this + */ + public function setActive($active = true) + { + $this->fields['ACTIVE'] = $active ? 'Y' : 'N'; + + return $this; + } + + /** + * Обязательное (Y|N). + * @param bool $isRequired + * @return $this + */ + public function setIsRequired($isRequired = true) + { + $this->fields['IS_REQUIRED'] = $isRequired ? 'Y' : 'N'; + + return $this; + } + + /** + * Индекс сортировки. + * @param int $sort + * @return $this + */ + public function setSort($sort = 500) + { + $this->fields['SORT'] = $sort; + + return $this; + } + + /** + * Тип свойства. Возможные значения: S - строка, N - число, F - файл, L - список, E - привязка к элементам, G - привязка к группам. + * @param string $propertyType + * @return $this + */ + public function setPropertyType($propertyType = 'S') + { + $this->fields['PROPERTY_TYPE'] = $propertyType; + + return $this; + } + + /** + * Установить тип свойства "Список" + * @param string $listType Тип, может быть "L" - выпадающий список или "C" - флажки. + * @param int $multipleCnt Количество строк в выпадающем списке + * @return $this + */ + public function setPropertyTypeList($listType = null, $multipleCnt = null) + { + $this->setPropertyType('L'); + + if (!is_null($listType)) { + $this->setListType($listType); + } + + if (!is_null($multipleCnt)) { + $this->setMultipleCnt($multipleCnt); + } + + return $this; + } + + /** + * Установить тип свойства "Файл" + * @param string $fileType Список допустимых расширений (через запятую). + * @return $this + */ + public function setPropertyTypeFile($fileType = null) + { + $this->setPropertyType('F'); + + if (!is_null($fileType)) { + $this->setFileType($fileType); + } + + return $this; + } + + /** + * Установить тип свойства "привязка к элементам" или "привязка к группам" + * @param string $property_type Тип свойства. Возможные значения: E - привязка к элементам, G - привязка к группам. + * @param string $linkIblockId код информационного блока с элементами/группами которого и будут связано значение. + * @return $this + */ + public function setPropertyTypeIblock($property_type, $linkIblockId) + { + $this->setPropertyType($property_type)->setLinkIblockId($linkIblockId); + + return $this; + } + + /** + * Установить тип свойства "справочник" + * @param string $table_name таблица HL для связи + * @return $this + */ + public function setPropertyTypeHl($table_name) + { + $this->setPropertyType('S')->setUserType('directory')->setUserTypeSettings([ + 'TABLE_NAME' => $table_name + ]); + + return $this; + } + + /** + * Множественность (Y|N). + * @param bool $multiple + * @return $this + */ + public function setMultiple($multiple = false) + { + $this->fields['MULTIPLE'] = $multiple ? 'Y' : 'N'; + + return $this; + } + + /** + * Количество строк в выпадающем списке для свойств типа "список". + * @param int $multipleCnt + * @return $this + */ + public function setMultipleCnt($multipleCnt) + { + $this->fields['MULTIPLE_CNT'] = $multipleCnt; + + return $this; + } + + /** + * Значение свойства по умолчанию (кроме свойства типа список L). + * @param string $defaultValue + * @return $this + */ + public function setDefaultValue($defaultValue) + { + $this->fields['DEFAULT_VALUE'] = $defaultValue; + + return $this; + } + + /** + * Количество строк в ячейке ввода значения свойства. + * @param int $rowCount + * @return $this + */ + public function setRowCount($rowCount) + { + $this->fields['ROW_COUNT'] = $rowCount; + + return $this; + } + + /** + * Количество столбцов в ячейке ввода значения свойства. + * @param int $colCount + * @return $this + */ + public function setColCount($colCount) + { + $this->fields['COL_COUNT'] = $colCount; + + return $this; + } + + /** + * Тип для свойства список (L). Может быть "L" - выпадающий список или "C" - флажки. + * @param string $listType + * @return $this + */ + public function setListType($listType = 'L') + { + $this->fields['LIST_TYPE'] = $listType; + + return $this; + } + + /** + * Список допустимых расширений для свойств файл "F" (через запятую). + * @param string $fileType + * @return $this + */ + public function setFileType($fileType) + { + $this->fields['FILE_TYPE'] = $fileType; + + return $this; + } + + /** + * Индексировать значения данного свойства. + * @param bool $searchable + * @return $this + */ + public function setSearchable($searchable = false) + { + $this->fields['SEARCHABLE'] = $searchable ? 'Y' : 'N'; + + return $this; + } + + /** + * Выводить поля для фильтрации по данному свойству на странице списка элементов в административном разделе. + * @param bool $filtrable + * @return $this + */ + public function setFiltrable($filtrable = false) + { + $this->fields['FILTRABLE'] = $filtrable ? 'Y' : 'N'; + + return $this; + } + + /** + * Для свойств типа привязки к элементам и группам задает код информационного блока с элементами/группами которого и будут связано значение. + * @param int $linkIblockId + * @return $this + */ + public function setLinkIblockId($linkIblockId) + { + $this->fields['LINK_IBLOCK_ID'] = $linkIblockId; + + return $this; + } + + /** + * Признак наличия у значения свойства дополнительного поля описания. Только для типов S - строка, N - число и F - файл (Y|N). + * @param bool $withDescription + * @return $this + */ + public function setWithDescription($withDescription) + { + $this->fields['WITH_DESCRIPTION'] = $withDescription ? 'Y' : 'N'; + + return $this; + } + + /** + * Идентификатор пользовательского типа свойства. + * @param string $user_type + * @return $this + */ + public function setUserType($user_type) + { + $this->fields['USER_TYPE'] = $user_type; + + return $this; + } + + /** + * Идентификатор пользовательского типа свойства. + * @param array $user_type_settings + * @return $this + */ + public function setUserTypeSettings($user_type_settings) + { + $this->fields['USER_TYPE_SETTINGS'] = array_merge((array)$this->fields['USER_TYPE_SETTINGS'], $user_type_settings); + + return $this; + } + + /** + * Подсказка + * @param string $hint + * @return $this + */ + public function setHint($hint) + { + $this->fields['HINT'] = $hint; + + return $this; + } } \ No newline at end of file From 5a7413f36c550a66c57d8644aa34940abe03cd5f Mon Sep 17 00:00:00 2001 From: Ms_Natali Date: Mon, 15 Oct 2018 19:31:59 +0300 Subject: [PATCH 3/7] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Constructors/IBlockProperty.php | 4 +- src/Constructors/IBlockPropertyEnum.php | 139 ++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 src/Constructors/IBlockPropertyEnum.php diff --git a/src/Constructors/IBlockProperty.php b/src/Constructors/IBlockProperty.php index 2e2a823..e3dbe11 100644 --- a/src/Constructors/IBlockProperty.php +++ b/src/Constructors/IBlockProperty.php @@ -173,13 +173,15 @@ public function setPropertyType($propertyType = 'S') /** * Установить тип свойства "Список" + * @param array $values массив доступных значений (можно собрать с помощью класса IBlockPropertyEnum) * @param string $listType Тип, может быть "L" - выпадающий список или "C" - флажки. * @param int $multipleCnt Количество строк в выпадающем списке * @return $this */ - public function setPropertyTypeList($listType = null, $multipleCnt = null) + public function setPropertyTypeList($values, $listType = null, $multipleCnt = null) { $this->setPropertyType('L'); + $this->fields['VALUES'] = $values; if (!is_null($listType)) { $this->setListType($listType); diff --git a/src/Constructors/IBlockPropertyEnum.php b/src/Constructors/IBlockPropertyEnum.php new file mode 100644 index 0000000..9f33be3 --- /dev/null +++ b/src/Constructors/IBlockPropertyEnum.php @@ -0,0 +1,139 @@ +Add($this->getFieldsWithDefault()); + + if (!$property_id) { + throw new \Exception("Ошибка добавления значения enum"); + } + + Logger::log("Добавлено значение списка enum {$this->fields['VALUE']}", Logger::COLOR_GREEN); + + return $property_id; + } + + /** + * Обновить свойство инфоблока + * @param $id + * @throws \Exception + */ + public function update($id) + { + $obj = new \CIBlockPropertyEnum(); + if (!$obj->Update($id, $this->fields)) { + throw new \Exception("Ошибка обновления значения enum"); + } + + Logger::log("Обновлено значение списка enum {$id}", Logger::COLOR_GREEN); + } + + /** + * Удалить свойство инфоблока + * @param $id + * @throws \Exception + */ + public static function delete($id) + { + if (!\CIBlockPropertyEnum::Delete($id)) { + throw new \Exception('Ошибка при удалении значения enum'); + } + + Logger::log("Удалено значение списка enum {$id}", Logger::COLOR_GREEN); + } + + /** + * Установить настройки для добавления свойства инфоблока по умолчанию + * @param string $xml_id + * @param string $value + * @param int $propertyId + * @return $this + */ + public function constructDefault($xml_id, $value, $propertyId = null) + { + $this->setXmlId($xml_id)->setValue($value); + + if ($propertyId) { + $this->setPropertyId($propertyId); + } + + return $this; + } + + /** + * Код свойства. + * @param string $propertyId + * @return $this + */ + public function setPropertyId($propertyId) + { + $this->fields['PROPERTY_ID'] = $propertyId; + + return $this; + } + + /** + * Внешний код. + * @param string $xml_id + * @return $this + */ + public function setXmlId($xml_id) + { + $this->fields['XML_ID'] = $xml_id; + + return $this; + } + + /** + * Индекс сортировки. + * @param int $sort + * @return $this + */ + public function setSort($sort = 500) + { + $this->fields['SORT'] = $sort; + + return $this; + } + + /** + * Значение варианта свойства. + * @param string $value + * @return $this + */ + public function setValue($value) + { + $this->fields['VALUE'] = $value; + + return $this; + } + + /** + * Значение варианта свойства. + * @param bool $def + * @return $this + */ + public function setDef($def) + { + $this->fields['DEF'] = $def ? 'Y' : 'N'; + + return $this; + } +} \ No newline at end of file From e34fc982d9c88052d779f33e5777063170676581 Mon Sep 17 00:00:00 2001 From: Ms_Natali Date: Wed, 17 Oct 2018 22:22:10 +0300 Subject: [PATCH 4/7] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=20HL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Constructors/Constructor.php | 49 ++++ src/Constructors/HighloadBlock.php | 124 ++++++++ src/Constructors/IBlock.php | 4 - src/Constructors/IBlockProperty.php | 4 - src/Constructors/IBlockPropertyEnum.php | 8 +- src/Constructors/IBlockType.php | 4 - src/Constructors/UserField.php | 358 ++++++++++++++++++++++++ src/Helpers.php | 40 +++ 8 files changed, 575 insertions(+), 16 deletions(-) create mode 100644 src/Constructors/Constructor.php create mode 100644 src/Constructors/HighloadBlock.php create mode 100644 src/Constructors/UserField.php diff --git a/src/Constructors/Constructor.php b/src/Constructors/Constructor.php new file mode 100644 index 0000000..d27611d --- /dev/null +++ b/src/Constructors/Constructor.php @@ -0,0 +1,49 @@ +getFieldsWithDefault()); + + if (!$result->isSuccess()) { + throw new \Exception(join(', ', $result->getErrorMessages())); + } + + foreach ($this->lang as $lid => $name) { + HighloadBlockLangTable::add([ + "ID" => $result->getId(), + "LID" => $lid, + "NAME" => $name + ]); + } + + Logger::log("Добавлен HL {$this->fields['NAME']}", Logger::COLOR_GREEN); + + return $result->getId(); + } + + /** + * Обновить HL + * @param $table_name + * @throws \Exception + */ + public function update($table_name) + { + $id = Helpers::getHlId($table_name); + $result = HighloadBlockTable::update($id, $this->fields); + + if (!$result->isSuccess()) { + throw new \Exception(join(', ', $result->getErrorMessages())); + } + + Logger::log("Обновлен HL {$table_name}", Logger::COLOR_GREEN); + } + + /** + * Удалить HL + * @param $table_name + * @throws \Exception + */ + public static function delete($table_name) + { + $id = Helpers::getHlId($table_name); + $result = HighloadBlockTable::delete($id); + + if (!$result->isSuccess()) { + throw new \Exception(join(', ', $result->getErrorMessages())); + } + + Logger::log("Удален HL {$table_name}", Logger::COLOR_GREEN); + } + + /** + * Установить настройки для добавления HL по умолчанию + * @param string $name Название highload-блока + * @param string $table_name Название таблицы с элементами highload-блока. + * @return $this + */ + public function constructDefault($name, $table_name) + { + return $this->setName($name)->setTableName($table_name); + } + + /** + * Название highload-блока. + * @param string $name + * @return $this + */ + public function setName($name) + { + $this->fields['NAME'] = $name; + + return $this; + } + + /** + * Название таблицы с элементами highload-блока. + * @param string $table_name + * @return $this + */ + public function setTableName($table_name) + { + $this->fields['TABLE_NAME'] = $table_name; + + return $this; + } + + /** + * Установить локализацию + * @param $lang + * @param $text + * @return HighloadBlock + */ + public function setLang($lang, $text) + { + $this->lang[$lang] = $text; + + return $this; + } +} \ No newline at end of file diff --git a/src/Constructors/IBlock.php b/src/Constructors/IBlock.php index 7354cfc..3689f77 100644 --- a/src/Constructors/IBlock.php +++ b/src/Constructors/IBlock.php @@ -51,14 +51,10 @@ public function update($id) */ public static function delete($id) { - Application::getConnection()->startTransaction(); if (!\CIBlock::Delete($id)) { - Application::getConnection()->rollbackTransaction(); throw new \Exception('Ошибка при удалении инфоблока'); } - Application::getConnection()->commitTransaction(); - Logger::log("Удален инфоблок {$id}", Logger::COLOR_GREEN); } diff --git a/src/Constructors/IBlockProperty.php b/src/Constructors/IBlockProperty.php index e3dbe11..e7a0b8e 100644 --- a/src/Constructors/IBlockProperty.php +++ b/src/Constructors/IBlockProperty.php @@ -52,14 +52,10 @@ public function update($id) */ public static function delete($id) { - Application::getConnection()->startTransaction(); if (!\CIBlockProperty::Delete($id)) { - Application::getConnection()->rollbackTransaction(); throw new \Exception('Ошибка при удалении свойства инфоблока'); } - Application::getConnection()->commitTransaction(); - Logger::log("Удалено свойство инфоблока {$id}", Logger::COLOR_GREEN); } diff --git a/src/Constructors/IBlockPropertyEnum.php b/src/Constructors/IBlockPropertyEnum.php index 9f33be3..988f3e2 100644 --- a/src/Constructors/IBlockPropertyEnum.php +++ b/src/Constructors/IBlockPropertyEnum.php @@ -19,15 +19,15 @@ public function add() { $obj = new \CIBlockPropertyEnum(); - $property_id = $obj->Add($this->getFieldsWithDefault()); + $property_enum_id = $obj->Add($this->getFieldsWithDefault()); - if (!$property_id) { + if (!$property_enum_id) { throw new \Exception("Ошибка добавления значения enum"); } Logger::log("Добавлено значение списка enum {$this->fields['VALUE']}", Logger::COLOR_GREEN); - return $property_id; + return $property_enum_id; } /** @@ -60,7 +60,7 @@ public static function delete($id) } /** - * Установить настройки для добавления свойства инфоблока по умолчанию + * Установить настройки для добавления значения enum инфоблока по умолчанию * @param string $xml_id * @param string $value * @param int $propertyId diff --git a/src/Constructors/IBlockType.php b/src/Constructors/IBlockType.php index 40d2425..7d598a7 100644 --- a/src/Constructors/IBlockType.php +++ b/src/Constructors/IBlockType.php @@ -47,14 +47,10 @@ public function update($id) */ public static function delete($id) { - Application::getConnection()->startTransaction(); if (!\CIBlockType::Delete($id)) { - Application::getConnection()->rollbackTransaction(); throw new \Exception('Ошибка при удалении типа инфоблока'); } - Application::getConnection()->commitTransaction(); - Logger::log("Удален тип инфоблока {$id}", Logger::COLOR_GREEN); } diff --git a/src/Constructors/UserField.php b/src/Constructors/UserField.php new file mode 100644 index 0000000..37e5daf --- /dev/null +++ b/src/Constructors/UserField.php @@ -0,0 +1,358 @@ +Add($this->getFieldsWithDefault()); + + if (!$result) { + global $APPLICATION; + throw new \Exception($APPLICATION->GetException()); + } + + Logger::log("Добавлен UF {$this->fields['FIELD_NAME']} для {$this->fields['ENTITY_ID']}", Logger::COLOR_GREEN); + + return $result; + } + + /** + * Обновить UF + * @param $id + * @throws \Exception + */ + public function update($id) + { + $uf = new \CUserTypeEntity(); + $result = $uf->Update($id, $this->fields); + + if (!$result) { + global $APPLICATION; + throw new \Exception($APPLICATION->GetException()); + } + + Logger::log("Обновлен UF {$id}", Logger::COLOR_GREEN); + } + + /** + * Удалить UF + * @param $id + * @throws \Exception + */ + public static function delete($id) + { + $result = \CUserTypeEntity::Delete($id); + + if (!$result) { + global $APPLICATION; + throw new \Exception($APPLICATION->GetException()); + } + + Logger::log("Удален UF {$id}", Logger::COLOR_GREEN); + } + + /** + * Установить настройки для добавления UF по умолчанию + * @param string $entityId Идентификатор сущности + * @param string $fieldName Код поля. + * @return $this + */ + public function constructDefault($entityId, $fieldName) + { + return $this->setEntityId($entityId)->setFieldName($fieldName)->setUserType('string'); + } + + /** + * Идентификатор сущности, к которой будет привязано свойство. + * @param string $entityId + * @return $this + */ + public function setEntityId($entityId) + { + $this->fields['ENTITY_ID'] = $entityId; + + return $this; + } + + /** + * Код поля. Всегда должно начинаться с UF_ + * @param string $fieldName + * @return $this + */ + public function setFieldName($fieldName) + { + $this->fields['FIELD_NAME'] = static::prepareUf($fieldName); + + return $this; + } + + /** + * тип пользовательского свойства + * @param string $userType + * @return $this + */ + public function setUserType($userType) + { + $this->fields['USER_TYPE_ID'] = $userType; + + return $this; + } + + /** + * тип нового пользовательского свойства HL + * @param string $table_name + * @param string $showField + * @return $this + */ + public function setUserTypeHL($table_name, $showField) + { + $linkId = Helpers::getHlId($table_name); + $this->setUserType('hlblock')->setSettings([ + 'HLBLOCK_ID' => Helpers::getHlId($table_name), + 'HLFIELD_ID' => Helpers::getFieldId(Constructor::objHLBlock($linkId), static::prepareUf($showField)), + ]); + + return $this; + } + + /** + * тип нового пользовательского свойства "связь с разелом ИБ" + * @param string $iblockId + * @return $this + */ + public function setUserTypeIblockSection($iblockId) + { + $this->setUserType('iblock_section')->setSettings([ + 'IBLOCK_ID' => $iblockId, + ]); + + return $this; + } + + /** + * тип нового пользовательского свойства "связь с элементом ИБ" + * @param string $iblockId + * @return $this + */ + public function setUserTypeIblockElement($iblockId) + { + $this->setUserType('iblock_element')->setSettings([ + 'IBLOCK_ID' => $iblockId, + ]); + + return $this; + } + + /** + * XML_ID пользовательского свойства. Используется при выгрузке в качестве названия поля + * @param string $xmlId + * @return $this + */ + public function setXmlId($xmlId) + { + $this->fields['XML_ID'] = $xmlId; + + return $this; + } + + /** + * Сортировка + * @param int $sort + * @return $this + */ + public function setSort($sort) + { + $this->fields['SORT'] = $sort; + + return $this; + } + + /** + * Является поле множественным или нет + * @param bool $multiple + * @return $this + */ + public function setMultiple($multiple) + { + $this->fields['MULTIPLE'] = $multiple ? 'Y' : 'N'; + + return $this; + } + + /** + * Обязательное или нет свойство + * @param bool $mandatory + * @return $this + */ + public function setMandatory($mandatory) + { + $this->fields['MANDATORY'] = $mandatory ? 'Y' : 'N'; + + return $this; + } + + /** + * Показывать в фильтре списка. Возможные значения: не показывать = N, точное совпадение = I, поиск по маске = E, поиск по подстроке = S + * @param string $showInFilter + * @return $this + */ + public function setShowFilter($showInFilter) + { + $this->fields['SHOW_FILTER'] = $showInFilter; + + return $this; + } + + /** + * Не показывать в списке. Если передать какое-либо значение, то будет считаться, что флаг выставлен. + * @param bool $showInList + * @return $this + */ + public function setShowInList($showInList) + { + $this->fields['SHOW_IN_LIST'] = $showInList ? 'Y' : ''; + + return $this; + } + + /** + * Пустая строка разрешает редактирование. Если передать какое-либо значение, то будет считаться, что флаг выставлен. + * @param bool $editInList + * @return $this + */ + public function setEditInList($editInList) + { + $this->fields['EDIT_IN_LIST'] = $editInList ? 'Y' : ''; + + return $this; + } + + /** + * Значения поля участвуют в поиске + * @param bool $isSearchable + * @return $this + */ + public function setIsSearchable($isSearchable = false) + { + $this->fields['IS_SEARCHABLE'] = $isSearchable ? 'Y' : 'N'; + + return $this; + } + + /** + * Дополнительные настройки поля (зависят от типа). В нашем случае для типа string + * @param array $settings + * @return $this + */ + public function setSettings($settings) + { + $this->fields['SETTINGS'] = array_merge((array)$this->fields['SETTINGS'], $settings); + + return $this; + } + + /** + * Языковые фразы + * @param string $lang + * @param string $text + * @return $this + */ + public function setLangDefault($lang, $text) + { + $this->setLangForm($lang, $text); + $this->setLangColumn($lang, $text); + $this->setLangFilter($lang, $text); + + return $this; + } + + /** + * Текст "Заголовок в списке" + * @param string $lang + * @param string $text + * @return $this + */ + public function setLangForm($lang, $text) + { + $this->fields['EDIT_FORM_LABEL'][$lang] = $text; + + return $this; + } + + /** + * Текст "Заголовок в списке" + * @param string $lang + * @param string $text + * @return $this + */ + public function setLangColumn($lang, $text) + { + $this->fields['LIST_COLUMN_LABEL'][$lang] = $text; + + return $this; + } + + /** + * Текст "Подпись фильтра в списке" + * @param string $lang + * @param string $text + * @return $this + */ + public function setLangFilter($lang, $text) + { + $this->fields['LIST_FILTER_LABEL'][$lang] = $text; + + return $this; + } + + /** + * Текст "Помощь" + * @param string $lang + * @param string $text + * @return $this + */ + public function setLangHelp($lang, $text) + { + $this->fields['HELP_MESSAGE'][$lang] = $text; + + return $this; + } + + /** + * Текст "Сообщение об ошибке (не обязательное)" + * @param string $lang + * @param string $text + * @return $this + */ + public function setLangError($lang, $text) + { + $this->fields['ERROR_MESSAGE'][$lang] = $text; + + return $this; + } + + protected static function prepareUf($name) + { + if (substr($name, 0, 3) != 'UF_') { + $name = "UF_{$name}"; + } + + return $name; + } +} \ No newline at end of file diff --git a/src/Helpers.php b/src/Helpers.php index dafe171..e83a146 100644 --- a/src/Helpers.php +++ b/src/Helpers.php @@ -2,8 +2,13 @@ namespace Arrilot\BitrixMigrations; +use Bitrix\Main\Application; + class Helpers { + protected static $hls = []; + protected static $ufs = []; + /** * Convert a value to studly caps case. * @@ -30,4 +35,39 @@ public static function rGlob($pattern, $flags = 0) { } return $files; } + + /** + * Получить ID HL по названию таблицы + * @param $table_name + * @return mixed + */ + public static function getHlId($table_name) + { + if (!isset(static::$hls[$table_name])) { + $dbRes = Application::getConnection()->query('SELECT `ID`, `NAME`, `TABLE_NAME` FROM b_hlblock_entity'); + while ($block = $dbRes->fetch()) { + static::$hls[$block['TABLE_NAME']] = $block; + } + } + + return static::$hls[$table_name]['ID']; + } + + /** + * Получить ID UF + * @param $obj + * @param $field_name + * @return mixed + */ + public static function getFieldId($obj, $field_name) + { + if (!isset(static::$ufs[$obj][$field_name])) { + $dbRes = Application::getConnection()->query('SELECT * FROM b_user_field'); + while ($uf = $dbRes->fetch()) { + static::$ufs[$uf['ENTITY_ID']][$uf['FIELD_NAME']] = $uf; + } + } + + return static::$ufs[$obj][$field_name]['ID']; + } } From 3db30895e6c43e7d386624089c36228bdb486a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D1=82=D0=B0=D0=BB=D0=B8=D1=8F?= Date: Thu, 18 Oct 2018 10:02:32 +0300 Subject: [PATCH 5/7] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 2ca871d..374ee2d 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,3 @@ Arrilot\BitrixMigrations\Autocreate\Manager::init($_SERVER["DOCUMENT_ROOT"].'/mi 3) По желанию отключить существующие шаблоны миграций, сделав свои. -## Конструкторы миграций - -- транзакции -- значения по умолчанию \ No newline at end of file From 99b13705b288ef8a7fb86c84037fbef75ad8f097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D1=82=D0=B0=D0=BB=D0=B8=D1=8F?= Date: Thu, 18 Oct 2018 10:08:27 +0300 Subject: [PATCH 6/7] Update Migrator.php --- src/Migrator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Migrator.php b/src/Migrator.php index e913a59..1a62112 100644 --- a/src/Migrator.php +++ b/src/Migrator.php @@ -79,7 +79,7 @@ public function __construct($config, TemplatesCollection $templates, DatabaseSto $this->dir_archive = isset($config['dir_archive']) ? $config['dir_archive'] : 'archive'; $this->use_transaction = isset($config['use_transaction']) ? $config['use_transaction'] : false; - if (is_array($config['default_fields'])) { + if (isset($config['default_fields']) && is_array($config['default_fields'])) { foreach ($config['default_fields'] as $class => $default_fields) { FieldConstructor::$defaultFields[$class] = $default_fields; } From fe5766d05d0177d164edadbb76ec7af684d5923a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D1=82=D0=B0=D0=BB=D0=B8=D1=8F?= Date: Thu, 18 Oct 2018 10:43:25 +0300 Subject: [PATCH 7/7] Update migrator --- migrator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrator b/migrator index 66b8fc2..11495b2 100644 --- a/migrator +++ b/migrator @@ -25,7 +25,7 @@ $config = [ 'table' => 'migrations', 'dir' => './migrations', // 'dir_archive' => 'archive', // not required. default = "archive" - // 'use_transaction' => false, // not required. default = false + 'use_transaction' => true, // not required. default = false 'default_fields' => [ IBlock::class => [ 'INDEX_ELEMENT' => 'N',