├── .gitignore ├── .settings.php ├── LICENSE.txt ├── README.md ├── admin ├── assets │ ├── script.js │ ├── style.css │ ├── style.php │ └── version.php ├── fields │ ├── input_hidden.php │ ├── input_text.php │ ├── select.php │ ├── select_groups.php │ ├── select_groups_multiple.php │ ├── select_multiple.php │ └── textarea.php ├── includes │ ├── builder_form.php │ ├── builder_group.php │ ├── config_list.php │ ├── errors.php │ ├── help.php │ ├── interface.php │ ├── options.php │ └── version.php ├── menu.php ├── sprint_migrations.php └── steps │ ├── migration_create.php │ ├── migration_delete.php │ ├── migration_execute.php │ ├── migration_list.php │ ├── migration_mark.php │ ├── migration_settag.php │ ├── migration_status.php │ └── migration_transfer.php ├── commands-en.txt ├── commands.txt ├── composer.json ├── contributors.txt ├── description.ru ├── examples ├── Version20150520000001.php ├── Version20150520000002.php ├── Version20150520000003.php ├── Version20150520000004.php ├── Version20150520000005.php ├── Version20170213000006.php ├── Version20170213000007.php ├── Version20170213000008.php ├── Version20170213000009.php ├── Version20190606000011.php ├── Version20190606000012.php ├── Version20190606000013.php └── Version20250606000014.php ├── include.php ├── install ├── admin │ └── sprint_migrations.php ├── gadgets │ └── sprint.migration │ │ └── dashboard │ │ ├── .description.php │ │ ├── .parameters.php │ │ ├── includes │ │ ├── errors.php │ │ ├── interface.php │ │ └── style.php │ │ └── index.php ├── index.php └── version.php ├── lib ├── builder.php ├── builders │ ├── agentbuilder.php │ ├── blankbuilder.php │ ├── cachecleanerbuilder.php │ ├── eventbuilder.php │ ├── formbuilder.php │ ├── hlblockbuilder.php │ ├── hlblockelementsbuilder.php │ ├── iblockbuilder.php │ ├── iblockcategorybuilder.php │ ├── iblockdeletebuilder.php │ ├── iblockelementsbuilder.php │ ├── markerbuilder.php │ ├── medialibelementsbuilder.php │ ├── optionbuilder.php │ ├── transferbuilder.php │ ├── usergroupbuilder.php │ ├── useroptionsbuilder.php │ └── usertypeentitiesbuilder.php ├── console.php ├── controller │ └── main.php ├── enum │ ├── eventsenum.php │ └── versionenum.php ├── exceptions │ ├── builderexception.php │ ├── consoleexception.php │ ├── helperexception.php │ ├── migrationexception.php │ ├── rebuildexception.php │ └── restartexception.php ├── exchange │ ├── exchangemanager.php │ ├── reader.php │ ├── restartablereader.php │ ├── restartablewriter.php │ ├── writer.php │ └── writertag.php ├── helper.php ├── helpermanager.php ├── helpers │ ├── agenthelper.php │ ├── deliveryservicehelper.php │ ├── eventhelper.php │ ├── formhelper.php │ ├── hlblockexchangehelper.php │ ├── hlblockhelper.php │ ├── iblockexchangehelper.php │ ├── iblockhelper.php │ ├── langhelper.php │ ├── medialibexchangehelper.php │ ├── medialibhelper.php │ ├── optionhelper.php │ ├── sitehelper.php │ ├── sqlhelper.php │ ├── texthelper.php │ ├── traits │ │ ├── iblock │ │ │ ├── iblockelementtrait.php │ │ │ ├── iblockfieldtrait.php │ │ │ ├── iblockpropertytrait.php │ │ │ ├── iblocksectiontrait.php │ │ │ ├── iblocktrait.php │ │ │ └── iblocktypetrait.php │ │ └── useroptions │ │ │ ├── hlblocktrait.php │ │ │ ├── iblocktrait.php │ │ │ ├── usergrouptrait.php │ │ │ └── usertrait.php │ ├── usergrouphelper.php │ ├── useroptionshelper.php │ └── usertypeentityhelper.php ├── installer.php ├── interfaces │ ├── readerhelperinterface.php │ ├── restartableinterface.php │ └── writerhelperinterface.php ├── locale.php ├── module.php ├── out.php ├── storagemanager.php ├── symfonybundle │ ├── command │ │ └── consolecommand.php │ └── sprintmigrationbundle.php ├── tables │ ├── abstract.php │ ├── formgroup.php │ ├── option.php │ ├── smstemplatesite.php │ ├── storage.php │ └── version.php ├── traits │ ├── currentusertrait.php │ ├── helpermanagertrait.php │ ├── outtrait.php │ ├── restartabletrait.php │ └── versionconfigtrait.php ├── version.php ├── versionbuilder.php ├── versionconfig.php └── versionmanager.php ├── locale ├── en.php └── ru.php ├── options.php ├── templates ├── AgentExport.php ├── EventExport.php ├── FormExport.php ├── HlblockElementsExport.php ├── HlblockExport.php ├── IblockCategoryExport.php ├── IblockDelete.php ├── IblockElementsExport.php ├── IblockExport.php ├── MedialibElementsExport.php ├── OptionExport.php ├── UserGroupExport.php ├── UserOptionsExport.php ├── UserTypeEntities.php └── version.php ├── tools └── migrate.php └── updater.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .settings 3 | .buildpath 4 | .project 5 | nbproject/ -------------------------------------------------------------------------------- /.settings.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'value' => [ 6 | 'defaultNamespace' => '\\Sprint\\Migration\\Controller', 7 | ], 8 | 'readonly' => true, 9 | ] 10 | ]; 11 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015,2018 andreyryabin@yandex.ru 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Миграции для разработчиков (1С-Битрикс) # 2 | [![Latest Stable Version](https://poser.pugx.org/andreyryabin/sprint.migration/v/stable.svg)](https://packagist.org/packages/andreyryabin/sprint.migration/) 3 | [![Total Downloads](https://img.shields.io/packagist/dt/andreyryabin/sprint.migration.svg?style=flat)](https://packagist.org/packages/andreyryabin/sprint.migration) 4 | 5 | Помогает переносить изменения между нескольким копиями проекта. 6 | 7 | Все изменения для базы данных пишутся в файлы миграций, эти файлы, как и весь код проекта, хранятся в системе контроля версий (например git) и попадают в копии разработчиков, после чего им необходимо выполнить установку новых миграций, чтобы обновить бд. 8 | 9 | Работать можно как через консоль, так и через админку. 10 | 11 | * Маркетплейс: [http://marketplace.1c-bitrix.ru/solutions/sprint.migration/](http://marketplace.1c-bitrix.ru/solutions/sprint.migration/) 12 | * Composer: [https://packagist.org/packages/andreyryabin/sprint.migration](https://packagist.org/packages/andreyryabin/sprint.migration) 13 | * Документация: [https://github.com/andreyryabin/sprint.migration/wiki](https://github.com/andreyryabin/sprint.migration/wiki) 14 | * Материалы: [https://dev.1c-bitrix.ru/community/webdev/user/39653/blog/](https://dev.1c-bitrix.ru/community/webdev/user/39653/blog/) 15 | * Группа в телеграм: [https://t.me/sprint_migration_bitrix](https://t.me/sprint_migration_bitrix) 16 | 17 | Особая благодарность 18 | ------------------------- 19 | Самой лучшей IDE на свете!\ 20 | [![Phpstorm](https://raw.githubusercontent.com/wiki/andreyryabin/sprint.migration/assets/phpstorm.png)](https://www.jetbrains.com/?from=sprint.migration) 21 | 22 | А также всем помощникам!\ 23 | [https://github.com/andreyryabin/sprint.migration/blob/master/contributors.txt](https://github.com/andreyryabin/sprint.migration/blob/master/contributors.txt) 24 | 25 | 26 | Установка через composer 27 | ------------------------- 28 | Пример вашего composer.json с установкой модуля в local/modules/ 29 | ``` 30 | { 31 | "extra": { 32 | "installer-paths": { 33 | "local/modules/{$name}/": ["type:bitrix-module"] 34 | } 35 | }, 36 | "require": { 37 | "andreyryabin/sprint.migration": "dev-master" 38 | }, 39 | } 40 | 41 | ``` 42 | Работа в консоли 43 | ------------------------- 44 | [https://github.com/andreyryabin/sprint.migration/wiki/Работа-в-консоли](https://github.com/andreyryabin/sprint.migration/wiki/Работа-в-консоли) 45 | 46 | 47 | Скриншоты 48 | ------------------------- 49 | Админка миграций 50 | ![bitrix-sprint-migration-1.png](https://raw.githubusercontent.com/wiki/andreyryabin/sprint.migration/assets/bitrix-sprint-migration-1.png) 51 | 52 | Формы создания миграций 53 | ![bitrix-sprint-migration-2.png](https://raw.githubusercontent.com/wiki/andreyryabin/sprint.migration/assets/bitrix-sprint-migration-2.png) 54 | 55 | 56 | Полезные ссылки 57 | ------------------------- 58 | [Миграции шаблонов бизнес-процессов для Битрикс24. Вот что для этого нужно](https://habr.com/ru/companies/ibs/articles/788566/) 59 | -------------------------------------------------------------------------------- /admin/assets/style.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /admin/assets/version.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /admin/fields/input_hidden.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /admin/fields/input_text.php: -------------------------------------------------------------------------------- 1 | 11 | 15 | placeholder="" 16 | 17 | 18 | style="width: px;" 19 | 20 | /> 21 | -------------------------------------------------------------------------------- /admin/fields/select.php: -------------------------------------------------------------------------------- 1 | 11 |
12 | 8) { ?> 13 |
14 | 15 |
16 | 17 |
18 | 19 | 28 | 29 |
30 |
31 | -------------------------------------------------------------------------------- /admin/fields/select_groups.php: -------------------------------------------------------------------------------- 1 | 12 |
13 |
14 | 15 |
16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 32 | 33 |
34 | 35 | 36 |
37 | -------------------------------------------------------------------------------- /admin/fields/select_groups_multiple.php: -------------------------------------------------------------------------------- 1 | 12 |
13 |
14 | 15 |
16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 32 | 33 |
34 | 35 | 36 |
37 | 38 |
39 |
40 | -------------------------------------------------------------------------------- /admin/fields/select_multiple.php: -------------------------------------------------------------------------------- 1 | 12 |
13 | 8) { ?> 14 |
15 | 16 |
17 | 18 |
19 | 20 | 29 | 30 |
31 |
32 | 33 |
34 |
35 | -------------------------------------------------------------------------------- /admin/fields/textarea.php: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /admin/includes/builder_form.php: -------------------------------------------------------------------------------- 1 | '; 9 | foreach ($builder->getFields() as $fieldCode => $fieldItem) { 10 | if ($fieldItem['type'] == 'hidden') { 11 | include __DIR__ . '/../fields/input_hidden.php'; 12 | continue; 13 | } 14 | 15 | echo '
'; 16 | 17 | echo !empty($fieldItem['title']) ? '
' . $fieldItem['title'] . '
' : ''; 18 | echo !empty($fieldItem['note']) ? '
' . $fieldItem['note'] . '
' : ''; 19 | 20 | if (!empty($fieldItem['height'])) { 21 | include __DIR__ . '/../fields/textarea.php'; 22 | } elseif (isset($fieldItem['select']) && !$fieldItem['multiple']) { 23 | include __DIR__ . '/../fields/select.php'; 24 | } elseif (isset($fieldItem['select']) && $fieldItem['multiple']) { 25 | include __DIR__ . '/../fields/select_multiple.php'; 26 | } elseif (isset($fieldItem['items']) && !$fieldItem['multiple']) { 27 | include __DIR__ . '/../fields/select_groups.php'; 28 | } elseif (isset($fieldItem['items']) && $fieldItem['multiple']) { 29 | include __DIR__ . '/../fields/select_groups_multiple.php'; 30 | } else { 31 | include __DIR__ . '/../fields/input_text.php'; 32 | } 33 | echo '
'; 34 | } 35 | 36 | echo '
' . 37 | '' . 38 | '' . 39 | '
'; 40 | 41 | if ($builder->hasDescription()) { 42 | echo '
'; 43 | Out::outToHtml($builder->getDescription(), ['make_links' => true]); 44 | echo '
'; 45 | } 46 | 47 | echo ''; 48 | -------------------------------------------------------------------------------- /admin/includes/builder_group.php: -------------------------------------------------------------------------------- 1 | getVal('version_builders', []); 10 | 11 | $builderTree = []; 12 | foreach ($builderList as $builderName => $builderClass) { 13 | $builder = $versionManager->createBuilder($builderName); 14 | if ($builder->isEnabled()) { 15 | $builderGroup = $builder->getGroup(); 16 | 17 | if (!isset($builderTree[$builderGroup])) { 18 | $builderTree[$builderGroup] = []; 19 | } 20 | $builderTree[$builderGroup][] = [ 21 | 'NAME' => $builder->getName(), 22 | 'TITLE' => $builder->getTitle(), 23 | ]; 24 | } 25 | } 26 | 27 | ?> 28 |
29 |
30 |
31 | $groupItems) { ?> 32 |
33 | 34 |
35 | 36 |
37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 | -------------------------------------------------------------------------------- /admin/includes/config_list.php: -------------------------------------------------------------------------------- 1 | getList(); 9 | 10 | ?> 11 | 12 | humanValues($configItem['values']); 15 | 16 | ?> 17 |
18 |
19 |
20 |

:

21 | 22 | $val) { ?> 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /admin/includes/errors.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | 8 | -------------------------------------------------------------------------------- /admin/includes/help.php: -------------------------------------------------------------------------------- 1 | GetCurPage(), 'settings.php'); 9 | 10 | ?> 11 |
12 |
13 |
14 |
15 | : 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 | 51 |
52 |
53 | -------------------------------------------------------------------------------- /admin/includes/interface.php: -------------------------------------------------------------------------------- 1 | SetTitle(Locale::getMessage('TITLE')); 8 | 9 | if ($_SERVER["REQUEST_METHOD"] == "POST") { 10 | CUtil::JSPostUnescape(); 11 | } 12 | 13 | $versionConfig = new Sprint\Migration\VersionConfig($_REQUEST['config']??''); 14 | 15 | if ($versionConfig->getVal('show_admin_interface')) { 16 | if ($_SERVER["REQUEST_METHOD"] == "POST") { 17 | require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_admin_js.php"); 18 | 19 | try { 20 | include __DIR__ . '/../steps/migration_execute.php'; 21 | include __DIR__ . '/../steps/migration_list.php'; 22 | include __DIR__ . '/../steps/migration_status.php'; 23 | include __DIR__ . '/../steps/migration_create.php'; 24 | include __DIR__ . '/../steps/migration_mark.php'; 25 | include __DIR__ . '/../steps/migration_delete.php'; 26 | include __DIR__ . '/../steps/migration_settag.php'; 27 | include __DIR__ . '/../steps/migration_transfer.php'; 28 | } catch (Throwable $e) { 29 | Out::outException($e); 30 | } 31 | 32 | require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_admin_js.php"); 33 | die(); 34 | } 35 | } 36 | 37 | require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_admin_after.php"); 38 | CJSCore::Init(["jquery3"]); 39 | 40 | if ($versionConfig->getVal('show_admin_interface')) { 41 | include __DIR__ . '/../includes/version.php'; 42 | include __DIR__ . '/../assets/version.php'; 43 | } 44 | 45 | $sperrors = []; 46 | if (!$versionConfig->getVal('show_admin_interface')) { 47 | $sperrors[] = Locale::getMessage('ADMIN_INTERFACE_HIDDEN'); 48 | } 49 | 50 | include __DIR__ . '/../includes/errors.php'; 51 | include __DIR__ . '/../includes/help.php'; 52 | include __DIR__ . '/../assets/style.php'; 53 | -------------------------------------------------------------------------------- /admin/includes/options.php: -------------------------------------------------------------------------------- 1 | getRequest(); 9 | 10 | if ($request->isPost() && check_bitrix_sessid()) { 11 | if ($request->getPost("options_remove")) { 12 | Module::removeDbOptions(); 13 | Out::outSuccess( 14 | Locale::getMessage('OPTIONS_REMOVE_success') 15 | ); 16 | } 17 | 18 | if ($request->getPost("configuration_remove")) { 19 | $versionConfig = new VersionConfig(); 20 | if ($versionConfig->deleteConfig($request->getPost('configuration_name'))) { 21 | Out::outSuccess( 22 | Locale::getMessage('BUILDER_Cleaner_success') 23 | ); 24 | } else { 25 | Out::outError( 26 | Locale::getMessage('BUILDER_Cleaner_error') 27 | ); 28 | } 29 | } 30 | 31 | if ($request->getPost("configuration_create")) { 32 | $versionConfig = new VersionConfig(); 33 | if ($versionConfig->createConfig($request->getPost('configuration_name'))) { 34 | Out::outSuccess( 35 | Locale::getMessage('BUILDER_Configurator_success') 36 | ); 37 | } else { 38 | Out::outError( 39 | Locale::getMessage('BUILDER_Configurator_error') 40 | ); 41 | } 42 | } 43 | 44 | if ($request->getPost("gadgets_install")) { 45 | /** @var $tmpmodule sprint_migration */ 46 | $tmpmodule = CModule::CreateModuleObject(Module::ID); 47 | $tmpmodule->installGadgets(); 48 | Out::outSuccess( 49 | Locale::getMessage('GD_INSTALL_success') 50 | ); 51 | } 52 | } 53 | ?> 54 | 55 | 56 |
57 | 58 |
59 |
60 |
61 |
62 |

63 |

65 |

67 | 68 |
69 |
70 |
71 |
72 |

73 |

75 |

77 | 78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 |
87 |

88 |

90 | 91 |
92 |
93 |
94 |
95 |

96 |

98 | 99 |
100 |
101 |
102 |
103 | 104 |
105 | 106 | 107 | -------------------------------------------------------------------------------- /admin/includes/version.php: -------------------------------------------------------------------------------- 1 | Locale::getMessage('UP_START_WITH_TAG'), 12 | 'ONCLICK' => 'migrationMigrationsUpWithTag()', 13 | ]; 14 | $menu[] = [ 15 | 'TEXT' => Locale::getMessage('DOWN_START'), 16 | 'ONCLICK' => 'migrationMigrationsDownConfirm()', 17 | ]; 18 | return CUtil::PhpToJSObject($menu); 19 | } 20 | ?> 21 |
22 |
23 |
24 |
25 | 40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 52 | 56 |
57 |
58 |
59 |
60 |
61 |
62 | 63 |
64 |
65 | -------------------------------------------------------------------------------- /admin/menu.php: -------------------------------------------------------------------------------- 1 | GetGroupRight('sprint.migration') == 'D') { 10 | return false; 11 | } 12 | 13 | if (!Loader::includeModule('sprint.migration')) { 14 | return false; 15 | } 16 | 17 | try { 18 | $versionConfig = new Sprint\Migration\VersionConfig(); 19 | $configList = $versionConfig->getList(); 20 | 21 | $items = []; 22 | foreach ($configList as $item) { 23 | $items[] = [ 24 | 'text' => $item['title'], 25 | 'url' => 'sprint_migrations.php?' . http_build_query([ 26 | 'config' => $item['name'], 27 | 'lang' => LANGUAGE_ID, 28 | ]), 29 | ]; 30 | } 31 | 32 | $aMenu = [ 33 | 'parent_menu' => 'global_menu_settings', 34 | 'section' => 'Sprint', 35 | 'sort' => 50, 36 | 'text' => Locale::getMessage('MENU_SPRINT'), 37 | 'icon' => 'sys_menu_icon', 38 | 'page_icon' => 'sys_page_icon', 39 | 'items_id' => 'sprint_migrations', 40 | 'items' => $items, 41 | ]; 42 | 43 | return $aMenu; 44 | } catch (Throwable $e) { 45 | $aMenu = [ 46 | 'parent_menu' => 'global_menu_settings', 47 | 'section' => 'Sprint', 48 | 'sort' => 50, 49 | 'text' => Locale::getMessage('MENU_SPRINT'), 50 | 'icon' => 'sys_menu_icon', 51 | 'page_icon' => 'sys_page_icon', 52 | 'items_id' => 'sprint_migrations', 53 | 'url' => 'sprint_migrations.php?' . http_build_query([ 54 | 'config' => VersionEnum::CONFIG_DEFAULT, 55 | 'lang' => LANGUAGE_ID, 56 | ]), 57 | ]; 58 | 59 | return $aMenu; 60 | } 61 | -------------------------------------------------------------------------------- /admin/sprint_migrations.php: -------------------------------------------------------------------------------- 1 | GetGroupRight('sprint.migration') == 'D') { 20 | throw new Exception(Locale::getMessage("ACCESS_DENIED")); 21 | } 22 | 23 | Module::checkHealth(); 24 | 25 | include __DIR__ . '/includes/interface.php'; 26 | 27 | require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_admin.php"); 28 | } catch (Throwable $exception) { 29 | require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_admin_after.php"); 30 | 31 | $sperrors = []; 32 | $sperrors[] = sprintf( 33 | "[%s] %s (%s) in %s:%d \n", 34 | get_class($exception), 35 | $exception->getMessage(), 36 | $exception->getCode(), 37 | $exception->getFile(), 38 | $exception->getLine() 39 | ); 40 | 41 | include __DIR__ . '/includes/errors.php'; 42 | include __DIR__ . '/includes/help.php'; 43 | include __DIR__ . '/assets/style.php'; 44 | 45 | require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_admin.php"); 46 | } 47 | -------------------------------------------------------------------------------- /admin/steps/migration_create.php: -------------------------------------------------------------------------------- 1 | createBuilder($builderName, $_POST); 22 | } catch (BuilderException $e) { 23 | return; 24 | } 25 | 26 | if ($stepCode == 'migration_create') { 27 | $builder->buildExecute(); 28 | $builder->buildAfter(); 29 | $builder->renderHtml(); 30 | 31 | if ($builder->isRestart()) { 32 | ?> 33 | isRebuild()) { 35 | ?> 36 | 39 | renderHtml(); 48 | ?> 49 | deleteMigration($version); 22 | Sprint\Migration\Out::outMessages($deleteresult); 23 | 24 | ?> 25 | $search, 28 | 'tag' => '', 29 | 'modified' => '', 30 | 'older' => '', 31 | 'actual' => '', 32 | ]; 33 | 34 | if ($migrationView == 'migration_view_tag') { 35 | $filter['tag'] = $search; 36 | $filter['search'] = ''; 37 | } elseif ($migrationView == 'migration_view_modified') { 38 | $filter['modified'] = 1; 39 | } elseif ($migrationView == 'migration_view_older') { 40 | $filter['older'] = 1; 41 | } 42 | 43 | if (!$versionName) { 44 | if ($nextAction == VersionEnum::ACTION_UP || $nextAction == VersionEnum::ACTION_DOWN) { 45 | $action = $nextAction; 46 | $versionName = $versionManager->getOnceForExecute($filter, $action); 47 | } 48 | } 49 | 50 | if ($versionName && $action) { 51 | if (!$restart) { 52 | Out::out('[%s]%s (%s) start[/]', $action, $versionName, $action); 53 | } 54 | 55 | $success = $versionManager->startMigration( 56 | $versionName, 57 | $action, 58 | $params, 59 | $settag 60 | ); 61 | 62 | $restart = ($success) ? $versionManager->needRestart() : $restart; 63 | 64 | if ($success && !$restart) { 65 | Out::out('%s (%s) success', $versionName, $action); 66 | 67 | if ($nextAction) { 68 | $json = json_encode([ 69 | 'next_action' => $nextAction, 70 | 'settag' => $settag, 71 | 'search' => $search, 72 | 'migration_view' => $migrationView, 73 | ]); 74 | 75 | ?> 76 | 83 | $versionManager->getRestartParams(), 92 | 'action' => $action, 93 | 'version' => $versionName, 94 | 'next_action' => $nextAction, 95 | 'restart' => 1, 96 | 'search' => $search, 97 | 'migration_view' => $migrationView, 98 | 'settag' => $settag, 99 | ]); 100 | 101 | ?> 102 | getLastException()); 107 | 108 | $json = json_encode([ 109 | 'params' => $params, 110 | 'action' => $action, 111 | 'version' => $versionName, 112 | 'next_action' => $nextAction, 113 | 'restart' => 1, 114 | 'search' => $search, 115 | 'migration_view' => $migrationView, 116 | 'settag' => $settag, 117 | ]); 118 | ?> 119 | 133 | markMigration($version, $status); 23 | Sprint\Migration\Out::outMessages($markresult); 24 | 25 | ?> 26 | setMigrationTag($version, $settag); 23 | Sprint\Migration\Out::outMessages($settagresult); 24 | ?> 25 | getVersions( 19 | [ 20 | 'search' => $search, 21 | ] 22 | ); 23 | 24 | $status = [ 25 | VersionEnum::STATUS_NEW => 0, 26 | VersionEnum::STATUS_INSTALLED => 0, 27 | VersionEnum::STATUS_UNKNOWN => 0, 28 | ]; 29 | 30 | foreach ($versions as $item) { 31 | $key = $item['status']; 32 | $status[$key]++; 33 | } 34 | 35 | ?> 36 | 37 | $cnt) { 38 | $ucode = strtoupper($code); ?> 39 | 40 | 46 | 49 | 50 | 51 |
41 | 42 | 43 | 44 | 45 | 47 | 48 |
52 | transferMigration( 24 | $version, 25 | $vmTo 26 | ); 27 | 28 | Sprint\Migration\Out::outMessages($transferresult); 29 | ?> 30 | =8.1", 23 | "composer/installers": "~1", 24 | "ext-json": "*", 25 | "ext-xmlreader": "*", 26 | "ext-xmlwriter": "*" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contributors.txt: -------------------------------------------------------------------------------- 1 | Андрей Рябин 2 | Александр Кузнецов 3 | Антон Тузлуков 4 | XOlegator 5 | Анатолий Солдатов 6 | Сергей Поляков 7 | Никита Морковкин 8 | Сергей Мартынович 9 | Егор Ковязин 10 | Марат Бакиров 11 | Дмитрий Третьяков 12 | anton-citrus-soft NA 13 | Andrew Kopylov 14 | Грипинский Сергей 15 | Митин Вадим 16 | Игорь Пинчук 17 | ildar r. khasanshin 18 | Максим Ляпцев 19 | Горбунов Александр 20 | Михнев Никита 21 | Степан Родионов 22 | Сергей Волков 23 | Константин Сумароков 24 | Константин Карнаухов 25 | Игорь Долгополов 26 | Nikita Kurgalin 27 | ... 28 | Это место специально для тебя :) 29 | -------------------------------------------------------------------------------- /description.ru: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreyryabin/sprint.migration/ce03248d386b653681f07d8420d38ec2bc5467b0/description.ru -------------------------------------------------------------------------------- /examples/Version20150520000001.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 17 | 18 | $helper->Iblock()->saveIblockType([ 19 | 'ID' => 'content', 20 | 'LANG' => [ 21 | 'en' => [ 22 | 'NAME' => 'Контент', 23 | 'SECTION_NAME' => 'Sections', 24 | 'ELEMENT_NAME' => 'Elements', 25 | ], 26 | 'ru' => [ 27 | 'NAME' => 'Контент', 28 | 'SECTION_NAME' => 'Разделы', 29 | 'ELEMENT_NAME' => 'Элементы', 30 | ], 31 | ], 32 | ]); 33 | 34 | $iblockId1 = $helper->Iblock()->saveIblock([ 35 | 'NAME' => 'Новости', 36 | 'CODE' => 'content_news', 37 | 'LID' => ['s1'], 38 | 'IBLOCK_TYPE_ID' => 'content', 39 | 'LIST_PAGE_URL' => '', 40 | 'DETAIL_PAGE_URL' => '#SITE_DIR#/news/#ELEMENT_ID#', 41 | ]); 42 | 43 | $helper->Iblock()->saveIblockFields($iblockId1, [ 44 | 'CODE' => [ 45 | 'DEFAULT_VALUE' => [ 46 | 'TRANSLITERATION' => 'Y', 47 | 'UNIQUE' => 'Y', 48 | ], 49 | ], 50 | ]); 51 | 52 | $helper->Iblock()->saveProperty($iblockId1, [ 53 | 'NAME' => 'Ссылка', 54 | 'CODE' => 'LINK', 55 | ]); 56 | 57 | $this->outSuccess('Инфоблок создан'); 58 | 59 | } 60 | 61 | /** 62 | * @throws Exceptions\HelperException 63 | * @return bool|void 64 | */ 65 | public function down() 66 | { 67 | $helper = $this->getHelperManager(); 68 | $ok = $helper->Iblock()->deleteIblockIfExists('content_news'); 69 | 70 | if ($ok) { 71 | $this->outSuccess('Инфоблок удален'); 72 | } else { 73 | $this->outError('Ошибка удаления инфоблока'); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /examples/Version20150520000002.php: -------------------------------------------------------------------------------- 1 | out('Примеры вывода сообщений'); 27 | $this->out('Используется [b]sprintf[/], напишем пару чисел %d %d и строку %s', 199, 200, 'hello'); 28 | $this->out('[blue]Но еще можно[/] [red]раскрашивать[/] и делать [b]жирным[/]'); 29 | $this->outSuccess('Все готово на %d%%', 100); 30 | $this->outError('Ошибка'); 31 | $this->outProgress('Прогресс', 10, 100); 32 | } 33 | 34 | /** 35 | * @return bool|void 36 | */ 37 | public function down() 38 | { 39 | //your code ... 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /examples/Version20150520000004.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 18 | 19 | $iblockId = $helper->Iblock()->getIblockIdIfExists('content_news', 'content'); 20 | 21 | //Пример отображения формы редактирования элемента 22 | $helper->UserOptions()->saveElementForm($iblockId, [ 23 | 'Tab1' => [ 24 | 'ACTIVE' => 'Активность', 25 | 'ACTIVE_FROM', 26 | 'ACTIVE_TO', 27 | 'NAME' => 'Название', 28 | 'CODE' => 'Символьный код', 29 | 'SORT', 30 | ], 31 | 'Tab2' => [ 32 | 'PREVIEW_TEXT', 33 | 'PROPERTY_LINK', 34 | ], 35 | ]); 36 | 37 | //Пример отображения списка элементов 38 | $helper->UserOptions()->saveElementList($iblockId, [ 39 | 'order' => 'desc', 40 | 'by' => 'id', 41 | 'page_size' => 10, 42 | 'columns' => [ 43 | 'NAME', 44 | 'SORT', 45 | 'ID', 46 | 'PROPERTY_LINK', 47 | ], 48 | ]); 49 | 50 | //Пример отображения формы редактирования категории 51 | $helper->UserOptions()->saveSectionForm($iblockId, [ 52 | 'Категория' => [ 53 | 'ID' => 'ID', 54 | 'ACTIVE' => 'Раздел активен', 55 | 'IBLOCK_SECTION_ID' => 'Родительский раздел', 56 | 'NAME' => 'Название', 57 | 'USER_FIELDS_ADD' => 'Добавить пользовательское свойство', 58 | ], 59 | ]); 60 | } 61 | 62 | /** 63 | * @return bool|void 64 | */ 65 | public function down() 66 | { 67 | // 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /examples/Version20150520000005.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 18 | 19 | $hlblockId = $helper->Hlblock()->saveHlblock([ 20 | 'NAME' => 'Test', 21 | 'TABLE_NAME' => 'hl_test', 22 | ]); 23 | 24 | $helper->Hlblock()->saveField($hlblockId, [ 25 | 26 | 'USER_TYPE_ID' => 'string', 27 | 'FIELD_NAME' => 'UF_NAME', 28 | ]); 29 | 30 | $helper->Hlblock()->saveField($hlblockId, [ 31 | 'USER_TYPE_ID' => 'string', 32 | 'FIELD_NAME' => 'UF_CODE', 33 | ]); 34 | 35 | } 36 | 37 | /** 38 | * @return bool|void 39 | */ 40 | public function down() 41 | { 42 | //your code ... 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /examples/Version20170213000006.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 17 | $hlblockId = $helper->Hlblock()->saveHlblock([ 18 | 'NAME' => 'Test', 19 | 'TABLE_NAME' => 'hl_test', 20 | ]); 21 | 22 | $helper->UserTypeEntity()->addUserTypeEntitiesIfNotExists( 23 | 'HLBLOCK_' . $hlblockId, 24 | [ 25 | ['FIELD_NAME' => 'UF_NAME', "USER_TYPE_ID" => "string"], 26 | ['FIELD_NAME' => 'UF_PRICE', "USER_TYPE_ID" => "integer"], 27 | ['FIELD_NAME' => 'UF_WEIGHT', "USER_TYPE_ID" => "double"], 28 | ['FIELD_NAME' => 'UF_CREATED_AT', "USER_TYPE_ID" => "datetime"], 29 | ['FIELD_NAME' => 'UF_UPDATED_AT', "USER_TYPE_ID" => "datetime"], 30 | ] 31 | ); 32 | } 33 | 34 | /** 35 | * @throws Exceptions\HelperException 36 | * @return bool|void 37 | */ 38 | public function down() 39 | { 40 | $helper = $this->getHelperManager(); 41 | 42 | $hlblockId = $helper->Hlblock()->getHlblockIdIfExists('Test'); 43 | 44 | $helper->UserTypeEntity()->deleteUserTypeEntitiesIfExists( 45 | 'HLBLOCK_' . $hlblockId, 46 | [ 47 | 'UF_NAME', 48 | 'UF_PRICE', 49 | 'UF_WEIGHT', 50 | 'UF_CREATED_AT', 51 | 'UF_UPDATED_AT', 52 | ] 53 | ); 54 | $helper->Hlblock()->deleteHlblock($hlblockId); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /examples/Version20170213000007.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 17 | 18 | //получить список шаблонов 19 | $helper->Site()->getSiteTemplates('s1'); 20 | 21 | 22 | //задать шаблоны 23 | $helper->Site()->setSiteTemplates('s1', [ 24 | 25 | //Для папки или файла 26 | [ 27 | 'TEMPLATE' => 'main', 28 | 'IN_DIR' => '/auth.php', 29 | ], 30 | 31 | //Период времени 32 | [ 33 | 'TEMPLATE' => 'main', 34 | 'IN_PERIOD' => ['02.03.2017', '02.05.2017'], 35 | ], 36 | 37 | //Для групп пользователей 38 | [ 39 | 'TEMPLATE' => 'main', 40 | 'IN_GROUP' => [1, 2, 3], 41 | ], 42 | 43 | //Параметр в URL 44 | [ 45 | 'TEMPLATE' => 'main', 46 | 'GET_PARAM' => ['print' => 'Y'], 47 | ], 48 | 49 | //Выражение PHP 50 | [ 51 | 'TEMPLATE' => 'main', 52 | 'CONDITION' => 'empty(1)', 53 | ], 54 | 55 | //Без условия 56 | [ 57 | 'TEMPLATE' => 'main', 58 | 'CONDITION' => '', 59 | ], 60 | ]); 61 | 62 | } 63 | 64 | /** 65 | * @return bool|void 66 | */ 67 | public function down() 68 | { 69 | //your code ... 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /examples/Version20170213000008.php: -------------------------------------------------------------------------------- 1 | getStorageManager(); 17 | 18 | $storage1->saveData('var1', '1234567'); 19 | $storage1->saveData('var2', [ 20 | 'bbb' => 'axcx', 21 | 'bbbb' => 'axcx', 22 | ]); 23 | 24 | //получаем данные этой миграции 25 | $var1 = $storage1->getSavedData('var1'); 26 | $var2 = $storage1->getSavedData('var2'); 27 | 28 | //удаляем выбранные данные этой миграции 29 | $storage1->deleteSavedData('var1'); 30 | 31 | //удаляем все данные этой миграции 32 | $storage1->deleteSavedData(); 33 | 34 | //получаем сохраненные данные какой-либо другой миграции 35 | $storage2 = $this->getStorageManager('Version20170213000007'); 36 | $var1 = $storage2->getSavedData('var1'); 37 | } 38 | 39 | /** 40 | * @return bool|void 41 | */ 42 | public function down() 43 | { 44 | //your code ... 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/Version20170213000009.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 18 | 19 | $helper->Event()->saveEventType('NEW_MATERIAL', [ 20 | 'LID' => 'ru', 21 | 'NAME' => 'Добавлен новый материал', 22 | 'DESCRIPTION' => $this->getDesc(), 23 | ]); 24 | 25 | $helper->Event()->saveEventType('NEW_MATERIAL', [ 26 | 'LID' => 'en', 27 | 'NAME' => 'Добавлен новый материал', 28 | 'DESCRIPTION' => $this->getDesc(), 29 | ]); 30 | 31 | 32 | $helper->Event()->saveEventMessage('NEW_MATERIAL', [ 33 | 'ACTIVE' => 'Y', 34 | 'LID' => 's1', 35 | 'EMAIL_FROM' => '#DEFAULT_EMAIL_FROM#', 36 | 'EMAIL_TO' => 'user@example.com', 37 | 'BCC' => '', 38 | 'SUBJECT' => 'Добавлен новый материал', 39 | 'BODY_TYPE' => 'text', 40 | 'MESSAGE' => $this->getMessage(), 41 | ]); 42 | 43 | } 44 | 45 | /** 46 | * @return bool|void 47 | */ 48 | public function down() 49 | { 50 | //your code ... 51 | } 52 | 53 | 54 | private function getDesc() 55 | { 56 | return <<getHelperManager(); 27 | 28 | //выберем группу по коду 29 | $groupId = $helper->UserGroup()->getGroupId('content_editor'); 30 | 31 | //выставим ей права на запись на все инфоблоки 32 | $iblocks = $helper->Iblock()->getIblocks(); 33 | 34 | foreach ($iblocks as $iblock) { 35 | $permissions = $helper->Iblock()->getGroupPermissions($iblock['ID']); 36 | $permissions[$groupId] = 'W'; 37 | $helper->Iblock()->setGroupPermissions($iblock['ID'], $permissions); 38 | } 39 | 40 | //выставим ей права на запись на все хайлоадблоки 41 | $hlblocks = $helper->Hlblock()->getHlblocks(); 42 | 43 | foreach ($hlblocks as $hlblock) { 44 | $permissions = $helper->Hlblock()->getGroupPermissions($hlblock['ID']); 45 | $permissions[$groupId] = 'W'; 46 | $helper->Hlblock()->setGroupPermissions($hlblock['ID'], $permissions); 47 | } 48 | } 49 | 50 | /** 51 | * @return bool|void 52 | */ 53 | public function down() 54 | { 55 | //your code ... 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/Version20190606000012.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 19 | 20 | //Пример работы с транзакциями 21 | $helper->Sql()->transaction(function () use ($helper) { 22 | $iblockId = $helper->Iblock()->getIblockId('content_news'); 23 | 24 | $helper->Iblock()->addElement($iblockId, ['NAME' => 'Новость1']); 25 | }); 26 | 27 | //Пример работы с индексами 28 | $helper->Sql()->addIndexIfNotExists('b_table_123', 'index_name', ['NAME']); 29 | } 30 | 31 | public function down() 32 | { 33 | //your code ... 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/Version20190606000013.php: -------------------------------------------------------------------------------- 1 | getHelperManager(); 16 | 17 | $iblockId = $helper->Iblock()->getIblockIdIfExists('content_news'); 18 | 19 | $helper->Iblock()->addSectionsFromTree($iblockId, [ 20 | [ 21 | 'NAME' => 'Корневая категория 1', 22 | ], 23 | [ 24 | 'NAME' => 'Корневая категория 2', 25 | 'CHILDS' => [ 26 | [ 27 | 'NAME' => 'Подкатегория 2/1', 28 | 'CHILDS' => [ 29 | [ 30 | 'NAME' => 'Подкатегория 2/1/1', 31 | ], 32 | [ 33 | 'NAME' => 'Подкатегория 2/1/2', 34 | ], 35 | ], 36 | ], 37 | [ 38 | 'NAME' => 'Подкатегория 2/2', 39 | ], 40 | ], 41 | ], 42 | ]); 43 | } 44 | 45 | public function down() 46 | { 47 | //your code ... 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/Version20250606000014.php: -------------------------------------------------------------------------------- 1 | checkRequiredVersions(['Version20190606000013', Version20190606000012::class]); 15 | 16 | } 17 | 18 | public function down() 19 | { 20 | //your code ... 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /include.php: -------------------------------------------------------------------------------- 1 | Locale::getMessage('GD_INFO_NAME'), 16 | 'DESCRIPTION' => Locale::getMessage('GD_INFO_DESC'), 17 | 'ICON' => '', 18 | 'TITLE_ICON_CLASS' => 'bx-gadgets-no-padding', 19 | 'GROUP' => ['ID' => 'admin_settings'], 20 | 'NOPARAMS' => 'N', 21 | 'AI_ONLY' => true, 22 | ]; -------------------------------------------------------------------------------- /install/gadgets/sprint.migration/dashboard/.parameters.php: -------------------------------------------------------------------------------- 1 | getList(); 16 | 17 | $configValues = []; 18 | 19 | foreach ($configs as $config) { 20 | $configValues[$config['name']] = $config['title']; 21 | } 22 | 23 | $arParameters = [ 24 | 'USER_PARAMETERS' => [ 25 | 'SELECT_CONFIGS' => [ 26 | 'NAME' => Locale::getMessage('GD_SELECT_CONFIGS'), 27 | 'TYPE' => 'LIST', 28 | 'SIZE' => 10, 29 | 'VALUES' => $configValues, 30 | 'MULTIPLE' => 'Y', 31 | 'DEFAULT' => [], 32 | ], 33 | ], 34 | ]; 35 | -------------------------------------------------------------------------------- /install/gadgets/sprint.migration/dashboard/includes/errors.php: -------------------------------------------------------------------------------- 1 | 4 |
5 | getMessage(); ?> 6 |
-------------------------------------------------------------------------------- /install/gadgets/sprint.migration/dashboard/includes/interface.php: -------------------------------------------------------------------------------- 1 | 4 |
5 | 6 | 7 | 8 | 9 | 12 | 13 | 20 | 21 | 22 |
10 |
11 |
14 | 15 | 16 | 17 | 18 | 19 |
23 |
24 | -------------------------------------------------------------------------------- /install/gadgets/sprint.migration/dashboard/includes/style.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /install/gadgets/sprint.migration/dashboard/index.php: -------------------------------------------------------------------------------- 1 | GetGroupRight('sprint.migration') == 'D') { 24 | Throw new Exception(Locale::getMessage("ACCESS_DENIED")); 25 | } 26 | 27 | Module::checkHealth(); 28 | 29 | $arGadgetParams['SELECT_CONFIGS'] = is_array($arGadgetParams['SELECT_CONFIGS']) ? $arGadgetParams['SELECT_CONFIGS'] : []; 30 | 31 | $results = []; 32 | 33 | $configs = (new VersionConfig())->getList(); 34 | foreach ($configs as $config) { 35 | 36 | if (!empty($arGadgetParams['SELECT_CONFIGS'])) { 37 | if (!in_array($config['name'], $arGadgetParams['SELECT_CONFIGS'])) { 38 | continue; 39 | } 40 | } 41 | 42 | $versionManager = new VersionManager( 43 | new VersionConfig($config['name']) 44 | ); 45 | $hasNewVersions = count($versionManager->getVersions([ 46 | 'status' => VersionEnum::STATUS_NEW, 47 | ])); 48 | 49 | $results[] = [ 50 | 'title' => $config['title'], 51 | 'text' => ($hasNewVersions) ? Locale::getMessage('GD_MIGRATIONS_RED') : Locale::getMessage('GD_MIGRATIONS_GREEN'), 52 | 'state' => ($hasNewVersions) ? 'red' : 'green', 53 | 'buttons' => [ 54 | [ 55 | 'text' => Locale::getMessage('GD_SHOW'), 56 | 'title' => Locale::getMessage('GD_SHOW_MIGRATIONS'), 57 | 'url' => '/bitrix/admin/sprint_migrations.php?' . http_build_query([ 58 | 'config' => $config['name'], 59 | 'lang' => LANGUAGE_ID, 60 | ]), 61 | ], 62 | ], 63 | ]; 64 | } 65 | 66 | include __DIR__ . '/includes/style.php'; 67 | include __DIR__ . '/includes/interface.php'; 68 | 69 | } catch (Throwable $e) { 70 | include __DIR__ . '/includes/style.php'; 71 | include __DIR__ . '/includes/errors.php'; 72 | } 73 | -------------------------------------------------------------------------------- /install/index.php: -------------------------------------------------------------------------------- 1 | MODULE_VERSION = $arModuleVersion["VERSION"]; 23 | $this->MODULE_VERSION_DATE = $arModuleVersion["VERSION_DATE"]; 24 | 25 | include(__DIR__ . '/../locale/ru.php'); 26 | include(__DIR__ . '/../locale/en.php'); 27 | 28 | $this->MODULE_NAME = GetMessage("SPRINT_MIGRATION_RU_MODULE_NAME"); 29 | $this->MODULE_DESCRIPTION = GetMessage("SPRINT_MIGRATION_RU_MODULE_DESCRIPTION"); 30 | $this->PARTNER_NAME = GetMessage("SPRINT_MIGRATION_RU_PARTNER_NAME"); 31 | $this->PARTNER_URI = GetMessage("SPRINT_MIGRATION_RU_PARTNER_URI"); 32 | } 33 | 34 | public function DoInstall() 35 | { 36 | RegisterModule($this->MODULE_ID); 37 | 38 | CopyDirFiles(__DIR__ . "/admin", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/admin"); 39 | $this->installGadgets(); 40 | } 41 | 42 | public function DoUninstall() 43 | { 44 | DeleteDirFiles(__DIR__ . "/admin", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/admin"); 45 | $this->unnstallGadgets(); 46 | 47 | UnRegisterModule($this->MODULE_ID); 48 | } 49 | 50 | public function installGadgets() 51 | { 52 | CopyDirFiles(__DIR__ . "/gadgets", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/gadgets", true, true); 53 | } 54 | 55 | public function unnstallGadgets() 56 | { 57 | DeleteDirFiles(__DIR__ . "/gadgets", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/gadgets"); 58 | } 59 | 60 | public function GetModuleRightList() 61 | { 62 | $arr = [ 63 | "reference_id" => ["D", "W"], 64 | "reference" => [ 65 | "[D] " . Locale::getMessage("RIGHT_D"), 66 | "[W] " . Locale::getMessage("RIGHT_W"), 67 | ], 68 | ]; 69 | return $arr; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /install/version.php: -------------------------------------------------------------------------------- 1 | "5.0.2", 5 | "VERSION_DATE" => "2025-05-02 15:30:30", 6 | ]; 7 | -------------------------------------------------------------------------------- /lib/builders/agentbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_AgentExport1')); 19 | $this->setDescription(Locale::getMessage('BUILDER_AgentExport2')); 20 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Main')); 21 | 22 | $this->addVersionFields(); 23 | } 24 | 25 | protected function execute() 26 | { 27 | $helper = $this->getHelperManager(); 28 | 29 | $allAgents = array_map(function ($item) { 30 | $item['MODULE_ID'] = $item['MODULE_ID'] ?: Locale::getMessage('BUILDER_AgentExport_empty_module'); 31 | return $item; 32 | }, $this->getHelperManager()->Agent()->getList()); 33 | 34 | $moduleIds = $this->addFieldAndReturn('module_id', [ 35 | 'title' => Locale::getMessage('BUILDER_AgentExport_module_id'), 36 | 'placeholder' => '', 37 | 'multiple' => 1, 38 | 'value' => [], 39 | 'width' => 250, 40 | 'select' => $this->createSelect($allAgents, 'MODULE_ID', 'MODULE_ID'), 41 | ]); 42 | 43 | $selectAgents = array_filter($allAgents, function ($item) use ($moduleIds) { 44 | return in_array($item['MODULE_ID'], $moduleIds); 45 | }); 46 | 47 | $agentIds = $this->addFieldAndReturn('agent_id', [ 48 | 'title' => Locale::getMessage('BUILDER_AgentExport_agent_id'), 49 | 'placeholder' => '', 50 | 'multiple' => 1, 51 | 'value' => [], 52 | 'width' => 250, 53 | 'items' => $this->createSelectWithGroups($selectAgents, 'ID', 'NAME', 'MODULE_ID'), 54 | ]); 55 | 56 | $items = []; 57 | foreach ($agentIds as $agentId) { 58 | $agent = $helper->Agent()->exportAgentById($agentId); 59 | if (!empty($agent)) { 60 | $items[] = $agent;; 61 | } 62 | } 63 | 64 | if (empty($items)) { 65 | $this->rebuildField('agent_id'); 66 | } 67 | 68 | $this->createVersionFile( 69 | Module::getModuleTemplateFile('AgentExport'), 70 | [ 71 | 'items' => $items, 72 | ] 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/builders/blankbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_Version1')); 19 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Tools')); 20 | 21 | $this->addVersionFields(); 22 | } 23 | 24 | protected function execute() 25 | { 26 | $template = $this->getVersionConfig()->getVal('migration_template'); 27 | if ($template && is_file(Module::getDocRoot() . $template)) { 28 | $template = Module::getDocRoot() . $template; 29 | } else { 30 | $template = Module::getModuleTemplateFile('version'); 31 | } 32 | 33 | $this->createVersionFile($template, [], false); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/builders/cachecleanerbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_CacheCleaner1')); 19 | $this->setDescription(Locale::getMessage('BUILDER_CacheCleaner2')); 20 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Tools')); 21 | } 22 | 23 | protected function execute() 24 | { 25 | BXClearCache(true); 26 | $this->outSuccess('Success'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/builders/eventbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_EventExport1')); 22 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Main')); 23 | 24 | $this->addVersionFields(); 25 | } 26 | 27 | /** 28 | * @throws RebuildException 29 | * @throws MigrationException 30 | * @throws HelperException 31 | */ 32 | protected function execute() 33 | { 34 | $helper = $this->getHelperManager(); 35 | 36 | $eventTypes = $this->addFieldAndReturn('event_types', [ 37 | 'title' => Locale::getMessage('BUILDER_EventExport_event_types'), 38 | 'width' => 350, 39 | 'select' => $this->getEventTypesSelect(), 40 | 'multiple' => 1, 41 | ]); 42 | 43 | $result = []; 44 | foreach ($eventTypes as $eventName) { 45 | $types = $helper->Event()->exportEventTypes($eventName); 46 | 47 | $messages = $helper->Event()->exportEventMessages($eventName); 48 | $smstemplates = $helper->Event()->exportEventSmsTemplates($eventName); 49 | 50 | $result[$eventName] = [ 51 | 'types' => $types, 52 | 'email' => $messages, 53 | 'sms' => $smstemplates, 54 | ]; 55 | } 56 | 57 | $this->createVersionFile( 58 | Module::getModuleTemplateFile('EventExport'), 59 | [ 60 | 'result' => $result, 61 | ] 62 | ); 63 | } 64 | 65 | protected function getEventTypesSelect(): array 66 | { 67 | $items = $this->getHelperManager()->Event()->getEventTypes([ 68 | 'LID' => LANGUAGE_ID, 69 | ]); 70 | 71 | $items = array_map(function ($item) { 72 | $item['NAME'] = '[' . $item['EVENT_NAME'] . '] ' . $item['NAME']; 73 | return $item; 74 | }, $items); 75 | 76 | return $this->createSelect($items, 'EVENT_NAME', 'NAME'); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/builders/hlblockbuilder.php: -------------------------------------------------------------------------------- 1 | getHelperManager()->Hlblock()->isEnabled(); 17 | } 18 | 19 | protected function initialize() 20 | { 21 | $this->setTitle(Locale::getMessage('BUILDER_HlblockExport1')); 22 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Hlblock')); 23 | 24 | $this->addVersionFields(); 25 | } 26 | 27 | /** 28 | * @throws HelperException 29 | * @throws RebuildException 30 | * @throws MigrationException 31 | */ 32 | protected function execute() 33 | { 34 | $helper = $this->getHelperManager(); 35 | 36 | $hlblockId = $this->addFieldAndReturn( 37 | 'hlblock_id', 38 | [ 39 | 'title' => Locale::getMessage('BUILDER_HlblockExport_HlblockId'), 40 | 'placeholder' => '', 41 | 'width' => 250, 42 | 'select' => $this->getHelperManager()->HlblockExchange()->getHlblocksStructure(), 43 | ] 44 | ); 45 | 46 | $hlblock = $helper->Hlblock()->exportHlblock($hlblockId); 47 | if (empty($hlblockId)) { 48 | $this->rebuildField('hlblock_id'); 49 | } 50 | 51 | $what = $this->addFieldAndReturn( 52 | 'what', [ 53 | 'title' => Locale::getMessage('BUILDER_HlblockExport_What'), 54 | 'width' => 250, 55 | 'multiple' => 1, 56 | 'value' => [], 57 | 'select' => [ 58 | [ 59 | 'title' => Locale::getMessage('BUILDER_HlblockExport_WhatHlblock'), 60 | 'value' => 'hlblock', 61 | ], 62 | [ 63 | 'title' => Locale::getMessage('BUILDER_HlblockExport_WhatHlblockFields'), 64 | 'value' => 'hlblockFields', 65 | ], 66 | [ 67 | 'title' => Locale::getMessage('BUILDER_HlblockExport_WhatHlblockUserOptions'), 68 | 'value' => 'hlblockUserOptions', 69 | ], 70 | [ 71 | 'title' => Locale::getMessage('BUILDER_HlblockExport_WhatHlblockPermissions'), 72 | 'value' => 'hlblockPermissions', 73 | ], 74 | ], 75 | ] 76 | ); 77 | 78 | $hlblockExport = false; 79 | $hlblockFields = []; 80 | $hlblockPermissions = []; 81 | $exportElementForm = []; 82 | $exportElementList = []; 83 | if (in_array('hlblock', $what)) { 84 | $hlblockExport = true; 85 | } 86 | 87 | if (in_array('hlblockFields', $what)) { 88 | $hlblockFields = $helper->Hlblock()->exportFields($hlblockId); 89 | } 90 | 91 | if (in_array('hlblockPermissions', $what)) { 92 | $hlblockPermissions = $helper->Hlblock()->exportGroupPermissions($hlblockId); 93 | } 94 | 95 | if (in_array('hlblockUserOptions', $what)) { 96 | $exportElementForm = $helper->UserOptions()->exportHlblockForm($hlblockId); 97 | $exportElementList = $helper->UserOptions()->exportHlblockList($hlblockId); 98 | } 99 | 100 | $this->createVersionFile( 101 | Module::getModuleTemplateFile('HlblockExport'), 102 | [ 103 | 'hlblockExport' => $hlblockExport, 104 | 'hlblock' => $hlblock, 105 | 'hlblockFields' => $hlblockFields, 106 | 'hlblockPermissions' => $hlblockPermissions, 107 | 'exportElementForm' => $exportElementForm, 108 | 'exportElementList' => $exportElementList, 109 | ] 110 | ); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /lib/builders/hlblockelementsbuilder.php: -------------------------------------------------------------------------------- 1 | getHelperManager()->Hlblock()->isEnabled(); 25 | } 26 | 27 | protected function initialize() 28 | { 29 | $this->setTitle(Locale::getMessage('BUILDER_HlblockElementsExport1')); 30 | $this->setDescription(Locale::getMessage('BUILDER_HlblockElementsExport2')); 31 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Hlblock')); 32 | 33 | $this->addVersionFields(); 34 | } 35 | 36 | /** 37 | * @throws MigrationException 38 | * @throws HelperException 39 | * @throws RebuildException 40 | * @throws RestartException 41 | */ 42 | protected function execute(): void 43 | { 44 | $exhelper = $this->getHelperManager()->HlblockExchange(); 45 | 46 | $hlblockId = $this->addFieldAndReturn( 47 | 'hlblock_id', 48 | [ 49 | 'title' => Locale::getMessage('BUILDER_HlblockElementsExport_HlblockId'), 50 | 'placeholder' => '', 51 | 'width' => 250, 52 | 'select' => $exhelper->getHlblocksStructure(), 53 | ] 54 | ); 55 | 56 | $fields = $exhelper->getHlblockFieldsCodes($hlblockId); 57 | 58 | $updateMode = $this->getFieldValueUpdateMode(); 59 | 60 | if ($updateMode == self::UPDATE_MODE_XML_ID) { 61 | if (!in_array('UF_XML_ID', $fields)) { 62 | throw new HelperException('Field UF_XML_ID not found'); 63 | } 64 | } 65 | 66 | (new RestartableWriter($this, $this->getVersionExchangeDir())) 67 | ->setExchangeResource('hlblock_elements.xml') 68 | ->execute( 69 | attributesFn: fn() => $exhelper->getWriterAttributes($hlblockId), 70 | totalCountFn: fn() => $exhelper->getWriterRecordsCount($hlblockId), 71 | recordsFn: fn($offset, $limit) => $exhelper->getWriterRecordsTag( 72 | $offset, 73 | $limit, 74 | $hlblockId, 75 | $fields 76 | ) 77 | ); 78 | 79 | 80 | $this->createVersionFile( 81 | Module::getModuleTemplateFile('HlblockElementsExport'), 82 | [ 83 | 'updateMode' => $updateMode, 84 | ] 85 | ); 86 | } 87 | 88 | /** 89 | * @throws RebuildException 90 | */ 91 | protected function getFieldValueUpdateMode() 92 | { 93 | return $this->addFieldAndReturn( 94 | 'update_mode', 95 | [ 96 | 'title' => Locale::getMessage('BUILDER_IblockElementsExport_UpdateMode'), 97 | 'placeholder' => '', 98 | 'width' => 250, 99 | 'select' => [ 100 | [ 101 | 'title' => Locale::getMessage('BUILDER_IblockElementsExport_NotUpdate'), 102 | 'value' => self::UPDATE_MODE_NOT, 103 | ], 104 | [ 105 | 'title' => Locale::getMessage('BUILDER_IblockElementsExport_UpdateByXmlId'), 106 | 'value' => self::UPDATE_MODE_XML_ID, 107 | ], 108 | ], 109 | ] 110 | ); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /lib/builders/iblockcategorybuilder.php: -------------------------------------------------------------------------------- 1 | getHelperManager()->Iblock()->isEnabled(); 20 | } 21 | 22 | protected function initialize() 23 | { 24 | $this->setTitle(Locale::getMessage('BUILDER_IblockCategoryExport1')); 25 | $this->setDescription(Locale::getMessage('BUILDER_IblockCategoryExport2')); 26 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Iblock')); 27 | 28 | $this->addVersionFields(); 29 | } 30 | 31 | /** 32 | * @throws HelperException 33 | * @throws RebuildException 34 | * @throws MigrationException 35 | */ 36 | protected function execute() 37 | { 38 | $helper = $this->getHelperManager(); 39 | 40 | $iblockId = $this->addFieldAndReturn( 41 | 'iblock_id', 42 | [ 43 | 'title' => Locale::getMessage('BUILDER_IblockCategoryExport_IblockId'), 44 | 'placeholder' => '', 45 | 'width' => 250, 46 | 'items' => $this->getHelperManager()->IblockExchange()->getIblocksStructure(), 47 | ] 48 | ); 49 | 50 | $iblock = $helper->Iblock()->exportIblock($iblockId); 51 | if (empty($iblock)) { 52 | $this->rebuildField('iblock_id'); 53 | } 54 | 55 | $sectionTree = $helper->Iblock()->exportSectionsTree($iblockId); 56 | 57 | $this->createVersionFile( 58 | Module::getModuleTemplateFile('IblockCategoryExport'), 59 | [ 60 | 'iblock' => $iblock, 61 | 'sectionTree' => $sectionTree, 62 | ] 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/builders/iblockdeletebuilder.php: -------------------------------------------------------------------------------- 1 | getHelperManager()->Iblock()->isEnabled(); 14 | } 15 | 16 | protected function initialize() 17 | { 18 | $this->setTitle(Locale::getMessage('BUILDER_IblockDelete')); 19 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Iblock')); 20 | 21 | $this->addVersionFields(); 22 | } 23 | 24 | protected function execute() 25 | { 26 | $helper = $this->getHelperManager(); 27 | 28 | $iblockTypes = $helper->IblockExchange()->getIblockTypes(); 29 | 30 | $iblocks = $helper->IblockExchange()->getIblocks(); 31 | 32 | $itemsForSelect = $helper->IblockExchange()->createIblocksStructure( 33 | $iblockTypes, 34 | $iblocks 35 | ); 36 | 37 | $iblockIds = $this->addFieldAndReturn( 38 | 'iblock_ids', [ 39 | 'title' => Locale::getMessage('BUILDER_IblockExport_IblockId'), 40 | 'placeholder' => '', 41 | 'width' => 250, 42 | 'items' => $itemsForSelect, 43 | 'multiple' => 1, 44 | 'value' => [], 45 | ] 46 | ); 47 | 48 | if (empty($iblockIds)) { 49 | $this->rebuildField('iblock_ids'); 50 | } 51 | 52 | $selectedIblocks = []; 53 | foreach ($iblocks as $iblock) { 54 | if (in_array($iblock['ID'], $iblockIds)) { 55 | $selectedIblocks[] = $iblock; 56 | } 57 | } 58 | 59 | $this->createVersionFile( 60 | Module::getModuleTemplateFile('IblockDelete'), 61 | [ 62 | 'iblocks' => $selectedIblocks, 63 | ], 64 | false 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/builders/markerbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('MARK')); 20 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Tools')); 21 | 22 | $this->addField('mark_version', [ 23 | 'title' => Locale::getMessage('MARK_FIELD1'), 24 | 'placeholder' => Locale::getMessage('MARK_VERSION'), 25 | 'width' => 250, 26 | ]); 27 | 28 | $this->addField('mark_status', [ 29 | 'title' => Locale::getMessage('MARK_FIELD2'), 30 | 'placeholder' => '', 31 | 'width' => 250, 32 | 'select' => [ 33 | [ 34 | 'title' => Locale::getMessage('MARK_AS_INSTALLED'), 35 | 'value' => VersionEnum::STATUS_INSTALLED, 36 | ], 37 | [ 38 | 'title' => Locale::getMessage('MARK_AS_NEW'), 39 | 'value' => VersionEnum::STATUS_NEW, 40 | ], 41 | ], 42 | ]); 43 | } 44 | 45 | protected function execute() 46 | { 47 | $version = $this->getFieldValue('mark_version'); 48 | $status = $this->getFieldValue('mark_status'); 49 | 50 | $versionManager = new VersionManager( 51 | $this->getVersionConfig() 52 | ); 53 | 54 | $markresult = $versionManager->markMigration( 55 | $version, 56 | $status 57 | ); 58 | 59 | $this->outMessages($markresult); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/builders/medialibelementsbuilder.php: -------------------------------------------------------------------------------- 1 | getHelperManager()->Medialib()->isEnabled(); 22 | } 23 | 24 | protected function initialize() 25 | { 26 | $this->setTitle(Locale::getMessage('BUILDER_MedialibElements1')); 27 | $this->setDescription(Locale::getMessage('BUILDER_MedialibElements2')); 28 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Medialib')); 29 | 30 | $this->addVersionFields(); 31 | } 32 | 33 | /** 34 | * @throws MigrationException 35 | * @throws RebuildException 36 | * @throws RestartException 37 | * @throws HelperException 38 | */ 39 | protected function execute() 40 | { 41 | $exhelper = $this->getHelperManager()->MedialibExchange(); 42 | 43 | $collectionIds = $this->addFieldAndReturn( 44 | 'collection_id', 45 | [ 46 | 'title' => Locale::getMessage('BUILDER_MedialibElements_CollectionId'), 47 | 'placeholder' => '', 48 | 'width' => 250, 49 | 'select' => $exhelper->getCollectionStructure( 50 | $exhelper::TYPE_IMAGE 51 | ), 52 | 'multiple' => true, 53 | ] 54 | ); 55 | 56 | $exportFields = [ 57 | 'NAME', 58 | 'DESCRIPTION', 59 | 'KEYWORDS', 60 | 'COLLECTION_ID', 61 | 'SOURCE_ID', 62 | ]; 63 | 64 | (new RestartableWriter($this, $this->getVersionExchangeDir())) 65 | ->setExchangeResource('medialib_elements.xml') 66 | ->execute( 67 | attributesFn: fn() => $exhelper->getWriterAttributes(), 68 | totalCountFn: fn() => $exhelper->getWriterRecordsCount($collectionIds), 69 | recordsFn: fn($offset, $limit) => $exhelper->getWriterRecordsTag( 70 | $offset, 71 | $limit, 72 | $collectionIds, 73 | $exportFields 74 | ), 75 | ); 76 | 77 | $this->createVersionFile( 78 | Module::getModuleTemplateFile('MedialibElementsExport') 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/builders/optionbuilder.php: -------------------------------------------------------------------------------- 1 | getHelperManager()->Option()->isEnabled(); 19 | } 20 | 21 | protected function initialize() 22 | { 23 | $this->setTitle(Locale::getMessage('BUILDER_OptionExport1')); 24 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Main')); 25 | 26 | $this->addVersionFields(); 27 | } 28 | 29 | /** 30 | * @throws RebuildException 31 | * @throws HelperException 32 | * @throws MigrationException 33 | */ 34 | protected function execute() 35 | { 36 | $helper = $this->getHelperManager(); 37 | 38 | $moduleIds = $this->addFieldAndReturn( 39 | 'module_id', 40 | [ 41 | 'title' => Locale::getMessage('BUILDER_OptionExport_module_id'), 42 | 'placeholder' => '', 43 | 'multiple' => 1, 44 | 'value' => [], 45 | 'width' => 250, 46 | 'select' => $this->createSelect( 47 | $helper->Option()->getModules(), 48 | 'ID', 49 | 'ID' 50 | ), 51 | ] 52 | ); 53 | 54 | $items = []; 55 | foreach ($moduleIds as $moduleId) { 56 | $options = $helper->Option()->getOptions( 57 | [ 58 | 'MODULE_ID' => $moduleId, 59 | ] 60 | ); 61 | 62 | foreach ($options as $option) { 63 | $items[] = $option; 64 | } 65 | } 66 | 67 | if (empty($items)) { 68 | $this->rebuildField('module_id'); 69 | } 70 | 71 | $this->createVersionFile( 72 | Module::getModuleTemplateFile('OptionExport'), 73 | [ 74 | 'items' => $items, 75 | ] 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/builders/transferbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_Transfer1')); 23 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Tools')); 24 | 25 | $this->addField('transfer_filter', [ 26 | 'title' => Locale::getMessage('BUILDER_TransferSelect'), 27 | 'placeholder' => '', 28 | 'width' => 250, 29 | 'select' => $this->getFilters(), 30 | 'value' => VersionEnum::STATUS_UNKNOWN, 31 | ]); 32 | 33 | $this->addField('transfer_to', [ 34 | 'title' => Locale::getMessage('BUILDER_TransferTo'), 35 | 'placeholder' => '', 36 | 'width' => 250, 37 | 'select' => $this->getConfigs(), 38 | ]); 39 | } 40 | 41 | /** 42 | * @throws MigrationException 43 | * @throws RebuildException 44 | */ 45 | protected function execute() 46 | { 47 | $transferFilter = $this->getFieldValue('transfer_filter'); 48 | $transferTo = $this->getFieldValue('transfer_to'); 49 | 50 | if (!$transferFilter || !$transferTo) { 51 | $this->rebuildField('transfer_to'); 52 | } 53 | 54 | $vmFrom = new VersionManager( 55 | $this->getVersionConfig() 56 | ); 57 | 58 | $vmTo = new VersionManager( 59 | new VersionConfig($transferTo) 60 | ); 61 | 62 | $transferresult = $vmFrom->transferMigration( 63 | $transferFilter, 64 | $vmTo 65 | ); 66 | 67 | $cnt = 0; 68 | foreach ($transferresult as $item) { 69 | if ($item['success']) { 70 | $cnt++; 71 | } 72 | } 73 | 74 | $this->outSuccess( 75 | Locale::getMessage( 76 | 'TRANSFER_OK_CNT', 77 | [ 78 | '#CNT#' => $cnt, 79 | ] 80 | ) 81 | ); 82 | } 83 | 84 | protected function getConfigs(): array 85 | { 86 | $structure = []; 87 | $configFrom = $this->getVersionConfig()->getName(); 88 | foreach ($this->getVersionConfig()->getList() as $item) { 89 | if ($item['name'] != $configFrom) { 90 | $structure[] = [ 91 | 'title' => $item['title'], 92 | 'value' => $item['name'], 93 | ]; 94 | } 95 | } 96 | return $structure; 97 | } 98 | 99 | private function getFilters(): array 100 | { 101 | return [ 102 | [ 103 | 'title' => Locale::getMessage('BUILDER_TransferInstalled'), 104 | 'value' => VersionEnum::STATUS_INSTALLED, 105 | ], 106 | [ 107 | 'title' => Locale::getMessage('BUILDER_TransferNew'), 108 | 'value' => VersionEnum::STATUS_NEW, 109 | ], 110 | [ 111 | 'title' => Locale::getMessage('BUILDER_TransferUnknown'), 112 | 'value' => VersionEnum::STATUS_UNKNOWN, 113 | ], 114 | [ 115 | 'title' => Locale::getMessage('BUILDER_TransferAll'), 116 | 'value' => 'all', 117 | ], 118 | ]; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/builders/usergroupbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_UserGroupExport1')); 22 | $this->setDescription(Locale::getMessage('BUILDER_UserGroupExport2')); 23 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Main')); 24 | 25 | $this->addVersionFields(); 26 | } 27 | 28 | /** 29 | * @throws RebuildException 30 | * @throws HelperException 31 | * @throws MigrationException 32 | */ 33 | protected function execute() 34 | { 35 | $helper = $this->getHelperManager(); 36 | 37 | $userGroups = $this->addFieldAndReturn( 38 | 'user_group', 39 | [ 40 | 'title' => Locale::getMessage('BUILDER_UserGroupExport_user_group'), 41 | 'placeholder' => '', 42 | 'multiple' => 1, 43 | 'value' => [], 44 | 'width' => 250, 45 | 'select' => $this->getUserGroupsSelect(), 46 | ] 47 | ); 48 | 49 | $items = []; 50 | foreach ($userGroups as $groupId) { 51 | if ($item = $helper->UserGroup()->exportGroup($groupId)) { 52 | $fields = $item; 53 | unset($fields['STRING_ID']); 54 | $items[] = [ 55 | 'STRING_ID' => $item['STRING_ID'], 56 | 'FIELDS' => $fields, 57 | ]; 58 | } 59 | } 60 | 61 | if (empty($items)) { 62 | $this->rebuildField('user_group'); 63 | } 64 | 65 | $this->createVersionFile( 66 | Module::getModuleTemplateFile('UserGroupExport'), 67 | [ 68 | 'items' => $items, 69 | ] 70 | ); 71 | } 72 | 73 | protected function getUserGroupsSelect(): array 74 | { 75 | $helper = $this->getHelperManager(); 76 | 77 | $items = array_filter($helper->UserGroup()->getGroups(), function ($item) { 78 | return !empty($item['STRING_ID']); 79 | }); 80 | 81 | $items = array_map(function ($item) { 82 | $item['NAME'] = '[' . $item['STRING_ID'] . '] ' . $item['NAME']; 83 | return $item; 84 | }, $items); 85 | 86 | return $this->createSelect( 87 | $items, 88 | 'ID', 89 | 'NAME' 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/builders/useroptionsbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_UserOptionsExport_Title')); 22 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Main')); 23 | 24 | $this->addVersionFields(); 25 | } 26 | 27 | /** 28 | * @throws RebuildException 29 | * @throws HelperException 30 | * @throws MigrationException 31 | */ 32 | protected function execute() 33 | { 34 | $helper = $this->getHelperManager(); 35 | 36 | $what = $this->addFieldAndReturn( 37 | 'what', 38 | [ 39 | 'title' => Locale::getMessage('BUILDER_UserOptionsExport_What'), 40 | 'width' => 250, 41 | 'multiple' => 1, 42 | 'value' => [], 43 | 'select' => [ 44 | [ 45 | 'title' => Locale::getMessage('BUILDER_UserOptionsExport_WhatUserForm'), 46 | 'value' => 'userForm', 47 | ], 48 | [ 49 | 'title' => Locale::getMessage('BUILDER_UserOptionsExport_WhatUserList'), 50 | 'value' => 'userList', 51 | ], 52 | [ 53 | 'title' => Locale::getMessage('BUILDER_UserOptionsExport_WhatGroupList'), 54 | 'value' => 'groupList', 55 | ], 56 | ], 57 | ] 58 | ); 59 | 60 | $exportUserForm = []; 61 | $exportUserList = []; 62 | $exportUserGroupList = []; 63 | $exportUserGrid = []; 64 | $exportUserGroupGrid = []; 65 | 66 | if (in_array('userForm', $what)) { 67 | $exportUserForm = $helper->UserOptions()->exportUserForm(); 68 | } 69 | if (in_array('userList', $what)) { 70 | $exportUserList = $helper->UserOptions()->exportUserList(); 71 | $exportUserGrid = $helper->UserOptions()->exportGrid( 72 | $helper->UserOptions()->getUserGridId() 73 | ); 74 | } 75 | if (in_array('groupList', $what)) { 76 | $exportUserGroupList = $helper->UserOptions()->exportUserGroupList(); 77 | $exportUserGroupGrid = $helper->UserOptions()->exportGrid( 78 | $helper->UserOptions()->getUserGroupGridId() 79 | ); 80 | } 81 | 82 | $this->createVersionFile( 83 | Module::getModuleTemplateFile('UserOptionsExport'), 84 | [ 85 | 'exportUserForm' => $exportUserForm, 86 | 'exportUserList' => $exportUserList, 87 | 'exportUserGroupList' => $exportUserGroupList, 88 | 'exportUserGrid' => $exportUserGrid, 89 | 'exportUserGroupGrid' => $exportUserGroupGrid, 90 | ] 91 | ); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/builders/usertypeentitiesbuilder.php: -------------------------------------------------------------------------------- 1 | setTitle(Locale::getMessage('BUILDER_UserTypeEntities1')); 22 | $this->setGroup(Locale::getMessage('BUILDER_GROUP_Main')); 23 | 24 | $this->addVersionFields(); 25 | } 26 | 27 | /** 28 | * @throws RebuildException 29 | * @throws HelperException 30 | * @throws MigrationException 31 | */ 32 | protected function execute() 33 | { 34 | $helper = $this->getHelperManager(); 35 | 36 | $allFields = $helper->UserTypeEntity()->getList(); 37 | foreach ($allFields as $index => $field) { 38 | $allFields[$index]['TITLE'] = $helper->UserTypeEntity()->getEntityTitle($field['ENTITY_ID']); 39 | } 40 | 41 | 42 | $entityIds = $this->addFieldAndReturn( 43 | 'entity_id', 44 | [ 45 | 'title' => Locale::getMessage('BUILDER_UserTypeEntities_EntityIds'), 46 | 'placeholder' => '', 47 | 'width' => 250, 48 | 'select' => $this->createSelect($allFields, 'ENTITY_ID', 'TITLE'), 49 | 'multiple' => 1, 50 | 'value' => [], 51 | ] 52 | ); 53 | 54 | $selectFields = array_filter($allFields, function ($item) use ($entityIds) { 55 | return in_array($item['ENTITY_ID'], $entityIds); 56 | }); 57 | 58 | $items = $this->addFieldAndReturn( 59 | 'entity_fields', 60 | [ 61 | 'title' => Locale::getMessage('BUILDER_UserTypeEntities_EntityFields'), 62 | 'placeholder' => '', 63 | 'width' => 250, 64 | 'multiple' => 1, 65 | 'items' => $this->createSelectWithGroups($selectFields, 'ID', 'FIELD_NAME', 'TITLE'), 66 | 'value' => [], 67 | ] 68 | ); 69 | 70 | $entities = []; 71 | foreach ($items as $fieldId) { 72 | $entity = $helper->UserTypeEntity()->exportUserTypeEntity($fieldId); 73 | if (!empty($entity)) { 74 | $entities[] = $entity; 75 | } 76 | } 77 | 78 | $this->createVersionFile( 79 | Module::getModuleTemplateFile('UserTypeEntities'), 80 | [ 81 | 'entities' => $entities, 82 | ] 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/controller/main.php: -------------------------------------------------------------------------------- 1 | restartable, 25 | $this->getHelperManager()->IblockExchange(), 26 | $this->directory 27 | 28 | ))->setExchangeResource('iblock_elements.xml'); 29 | } 30 | 31 | public function HlblockElementsImport(): RestartableReader 32 | { 33 | return (new RestartableReader( 34 | $this->restartable, 35 | $this->getHelperManager()->HlblockExchange(), 36 | $this->directory 37 | 38 | ))->setExchangeResource('hlblock_elements.xml'); 39 | } 40 | 41 | public function MedialibElementsImport(): RestartableReader 42 | { 43 | return (new RestartableReader( 44 | $this->restartable, 45 | $this->getHelperManager()->MedialibExchange(), 46 | $this->directory 47 | 48 | ))->setExchangeResource('medialib_elements.xml'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/exchange/restartablereader.php: -------------------------------------------------------------------------------- 1 | setExchangeFile($this->directory . $exchangeResource); 31 | } 32 | 33 | public function setExchangeFile(string $filePath): RestartableReader 34 | { 35 | $this->file = $filePath; 36 | return $this; 37 | } 38 | 39 | public function setLimit(int $limit): RestartableReader 40 | { 41 | $this->limit = $limit; 42 | return $this; 43 | } 44 | 45 | /** 46 | * @throws MigrationException 47 | * @throws RestartException 48 | */ 49 | public function execute(Closure $userFn): void 50 | { 51 | $this->reader = new Reader($this->file); 52 | 53 | $this->attributes = $this->restartable->restartOnce('step1', fn() => $this->reader->getAttributes()); 54 | 55 | $this->totalCount = $this->restartable->restartOnce('step2', fn() => $this->reader->getRecordsCount()); 56 | 57 | $this->restartable->restartWhile('step3', fn(int $offset) => $this->read($offset, $userFn)); 58 | } 59 | 60 | private function read(int $offset, Closure $userfunc): int 61 | { 62 | $records = $this->helper->convertReaderRecords( 63 | $this->attributes, 64 | $this->reader->readRecords($offset, $this->limit) 65 | ); 66 | 67 | array_map($userfunc, $records); 68 | 69 | $readCount = count($records); 70 | 71 | $offset += $readCount; 72 | 73 | Out::outProgress('Progress: ', $offset, $this->totalCount); 74 | 75 | return ($readCount >= $this->limit) ? $offset : 0; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /lib/exchange/restartablewriter.php: -------------------------------------------------------------------------------- 1 | setExchangeFile($this->directory . $exchangeResource); 30 | } 31 | 32 | public function setExchangeFile(string $filePath): RestartableWriter 33 | { 34 | $this->file = $filePath; 35 | return $this; 36 | } 37 | 38 | public function setLimit(int $limit): RestartableWriter 39 | { 40 | $this->limit = $limit; 41 | return $this; 42 | } 43 | 44 | public function setCopyFiles(bool $copyFiles): RestartableWriter 45 | { 46 | $this->copyFiles = $copyFiles; 47 | return $this; 48 | } 49 | 50 | /** 51 | * @throws MigrationException 52 | * @throws RestartException 53 | */ 54 | public function execute( 55 | Closure $attributesFn, 56 | Closure $totalCountFn, 57 | Closure $recordsFn, 58 | ): void 59 | { 60 | $this->writer = new Writer($this->file); 61 | 62 | $this->writer->setCopyFiles($this->copyFiles); 63 | 64 | $this->restartable->restartOnce('step1', fn() => $this->writer->createFile($attributesFn())); 65 | 66 | $this->totalCount = $this->restartable->restartOnce('step2', fn() => $totalCountFn()); 67 | 68 | $this->restartable->restartWhile('step3', fn(int $offset) => $this->write($offset, $recordsFn)); 69 | 70 | $this->restartable->restartOnce('step4', fn() => $this->writer->closeFile()); 71 | 72 | } 73 | 74 | /** 75 | * @throws MigrationException 76 | */ 77 | private function write(int $offset, Closure $recordsFn): int 78 | { 79 | /** @var WriterTag $tags */ 80 | $tags = $recordsFn($offset, $this->limit); 81 | 82 | $fetchedCount = $this->writer->appendTagsToFile($tags); 83 | 84 | $offset += $fetchedCount; 85 | 86 | Out::outProgress('Progress: ', $offset, $this->totalCount); 87 | 88 | return ($fetchedCount >= $this->limit) ? $offset : 0; 89 | } 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /lib/exchange/writer.php: -------------------------------------------------------------------------------- 1 | file = $file; 21 | 22 | if (!class_exists('XMLWriter')) { 23 | throw new MigrationException( 24 | Locale::getMessage( 25 | 'ERR_EXCHANGE_DISABLED_XML' 26 | ) 27 | ); 28 | } 29 | } 30 | 31 | /** 32 | * @throws MigrationException 33 | */ 34 | public function createFile(array $attributes): void 35 | { 36 | Module::createDir($this->getFileDir()); 37 | 38 | $this->appendToFile(''); 39 | $this->appendToFile('makeAttributes($attributes) . '>'); 40 | } 41 | 42 | public function closeFile(): void 43 | { 44 | $this->appendToFile(''); 45 | } 46 | 47 | /** 48 | * @throws MigrationException 49 | */ 50 | public function appendTagsToFile(WriterTag $tag): int 51 | { 52 | $writer = new XMLWriter(); 53 | $writer->openMemory(); 54 | $writer->setIndent(true); 55 | /** @var WriterTag $child */ 56 | foreach ($tag->getChilds() as $child) { 57 | $this->appendTagsToXml($writer, $child); 58 | } 59 | 60 | $this->appendToFile($writer->flush()); 61 | 62 | if ($this->copyFiles) { 63 | $this->copyTagsFiles($tag); 64 | } 65 | 66 | return $tag->countChilds(); 67 | } 68 | 69 | /** 70 | * @throws MigrationException 71 | */ 72 | private function copyTagsFiles(WriterTag $tag): void 73 | { 74 | foreach ($tag->getFiles() as $file) { 75 | $filePath = Module::getDocRoot() . $file['SRC']; 76 | if (file_exists($filePath)) { 77 | $newPath = $this->getFileDir() . '/' . $file['SUBDIR'] . '/' . $file['FILE_NAME']; 78 | Module::createDir(dirname($newPath)); 79 | copy($filePath, $newPath); 80 | } 81 | } 82 | 83 | } 84 | 85 | private function appendTagsToXml(XMLWriter $writer, WriterTag $tag): void 86 | { 87 | $writer->startElement($tag->getName()); 88 | 89 | foreach ($tag->getAttributes() as $atname => $atval) { 90 | $writer->writeAttribute($atname, $atval); 91 | } 92 | /** @var WriterTag $child */ 93 | foreach ($tag->getChilds() as $child) { 94 | $this->appendTagsToXml($writer, $child); 95 | } 96 | 97 | if ($tag->getText()) { 98 | if ($tag->isCdata()) { 99 | $writer->writeCdata($tag->getText()); 100 | } else { 101 | $writer->text($tag->getText()); 102 | } 103 | } 104 | 105 | $writer->endElement(); 106 | } 107 | 108 | private function appendToFile($content): void 109 | { 110 | file_put_contents($this->file, $content . PHP_EOL, FILE_APPEND); 111 | } 112 | 113 | private function getFileDir(): string 114 | { 115 | return dirname($this->file); 116 | } 117 | 118 | private function makeAttributes(array $attrs): string 119 | { 120 | $attrs['exchangeVersion'] = Module::EXCHANGE_VERSION; 121 | 122 | $str = ''; 123 | foreach ($attrs as $k => $v) { 124 | $str .= $k . '="' . $v . '" '; 125 | } 126 | return $str; 127 | } 128 | 129 | public function setCopyFiles(bool $copyFiles): Writer 130 | { 131 | $this->copyFiles = $copyFiles; 132 | return $this; 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /lib/exchange/writertag.php: -------------------------------------------------------------------------------- 1 | name = $name; 20 | 21 | foreach ($attributes as $key => $value) { 22 | $this->setAttribute($key, $value); 23 | } 24 | } 25 | 26 | public function getName(): string 27 | { 28 | return $this->name; 29 | } 30 | 31 | public function getAttributes(): array 32 | { 33 | return $this->attributes; 34 | } 35 | 36 | public function getText(): string 37 | { 38 | return $this->text; 39 | } 40 | 41 | public function addChild(WriterTag $child): void 42 | { 43 | $this->childs[] = $child; 44 | 45 | foreach ($child->forgetFiles() as $file) { 46 | $this->files[] = $file; 47 | } 48 | } 49 | 50 | public function getChilds(): array 51 | { 52 | return $this->childs; 53 | } 54 | 55 | public function setAttribute(string $name, $value): void 56 | { 57 | if ($name && $value) { 58 | $this->attributes[$name] = $value; 59 | } 60 | 61 | } 62 | 63 | public function countChilds(): int 64 | { 65 | return count($this->childs); 66 | } 67 | 68 | public function setText(string $text): void 69 | { 70 | $this->text = htmlspecialchars_decode($text); 71 | $this->cdata = $this->text != $text; 72 | } 73 | 74 | public function setJson(array $text): void 75 | { 76 | $this->text = json_encode($text, JSON_UNESCAPED_UNICODE); 77 | $this->cdata = true; 78 | $this->setAttribute('type', 'json'); 79 | } 80 | 81 | public function isCdata(): bool 82 | { 83 | return $this->cdata; 84 | } 85 | 86 | 87 | public function addFile(mixed $val, bool $multiple): void 88 | { 89 | if ($multiple) { 90 | foreach ($val as $val1) { 91 | $this->addFileTag($val1); 92 | } 93 | } elseif ($val) { 94 | $this->addFileTag($val); 95 | } 96 | } 97 | 98 | public function addValue(mixed $val, bool $multiple): void 99 | { 100 | if ($multiple) { 101 | foreach ($val as $val1) { 102 | $this->addValueTag($val1); 103 | } 104 | } else { 105 | $this->addValueTag($val); 106 | } 107 | } 108 | 109 | 110 | public function addValueTag($val, $attributes = []): void 111 | { 112 | if (empty($val)) { 113 | return; 114 | } 115 | 116 | $tag = new WriterTag('value', $attributes); 117 | if (is_array($val)) { 118 | $tag->setJson($val); 119 | } else { 120 | $tag->setText($val); 121 | } 122 | 123 | $this->addChild($tag); 124 | } 125 | 126 | public function addFileTag(int $fileId): void 127 | { 128 | $file = CFile::GetFileArray($fileId); 129 | if (empty($file)) { 130 | return; 131 | } 132 | 133 | $this->addValueTag( 134 | $file['SUBDIR'] . '/' . $file['FILE_NAME'], 135 | [ 136 | 'name' => $file['ORIGINAL_NAME'], 137 | 'description' => $file['DESCRIPTION'], 138 | 'type' => 'file', 139 | ] 140 | ); 141 | 142 | $this->files[] = $file; 143 | } 144 | 145 | public function getFiles(): array 146 | { 147 | return $this->files; 148 | } 149 | 150 | public function forgetFiles(): array 151 | { 152 | $tmp = $this->files; 153 | 154 | $this->files = []; 155 | 156 | return $tmp; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /lib/helpermanager.php: -------------------------------------------------------------------------------- 1 | callHelper($name); 69 | } 70 | 71 | public function registerHelper($name, $class) 72 | { 73 | $this->registered[$name] = $class; 74 | } 75 | 76 | /** 77 | * @throws HelperException 78 | */ 79 | protected function callHelper(string $name): Helper 80 | { 81 | if (isset($this->cache[$name])) { 82 | return $this->cache[$name]; 83 | } 84 | 85 | $default = '\\Sprint\\Migration\\Helpers\\' . $name . 'Helper'; 86 | 87 | $class = $this->registered[$name] ?? $default; 88 | 89 | if (class_exists($class)) { 90 | $ob = new $class; 91 | if ($ob instanceof Helper) { 92 | $this->cache[$name] = $ob; 93 | return $ob; 94 | } 95 | } 96 | 97 | throw new HelperException("Helper \"$name\" in \"$class\" not found"); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/helpers/iblockhelper.php: -------------------------------------------------------------------------------- 1 | checkModules(['iblock']); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lib/helpers/langhelper.php: -------------------------------------------------------------------------------- 1 | 'Y'])->Fetch(); 23 | 24 | if ($item) { 25 | return $item['LID']; 26 | } 27 | 28 | throw new HelperException( 29 | Locale::getMessage( 30 | 'ERR_DEFAULT_LANGUAGE_NOT_FOUND' 31 | ) 32 | ); 33 | } 34 | 35 | /** 36 | * @param array $filter 37 | * @return array 38 | */ 39 | public function getLangs($filter = []) 40 | { 41 | $by = 'def'; 42 | $order = 'desc'; 43 | 44 | $lids = []; 45 | /** @noinspection PhpDynamicAsStaticMethodCallInspection */ 46 | $dbres = CLanguage::GetList($by, $order, $filter); 47 | while ($item = $dbres->Fetch()) { 48 | $lids[] = $item; 49 | } 50 | 51 | return $lids; 52 | } 53 | 54 | /** 55 | * @throws HelperException 56 | * @return array 57 | */ 58 | public function getLangsIfExists() 59 | { 60 | $items = $this->getLangs(['ACTIVE' => 'Y']); 61 | if (!empty($items)) { 62 | return $items; 63 | } 64 | 65 | throw new HelperException( 66 | Locale::getMessage( 67 | 'ERR_ACTIVE_LANGUAGES_NOT_FOUND' 68 | ) 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/helpers/sitehelper.php: -------------------------------------------------------------------------------- 1 | 'Y'])->Fetch(); 24 | 25 | if ($item) { 26 | return $item['LID']; 27 | } 28 | throw new HelperException( 29 | Locale::getMessage( 30 | 'ERR_DEFAULT_SITE_NOT_FOUND' 31 | ) 32 | ); 33 | } 34 | 35 | /** 36 | * @param array $filter 37 | * @return array 38 | */ 39 | public function getSites($filter = []) 40 | { 41 | $by = 'def'; 42 | $order = 'desc'; 43 | 44 | $sids = []; 45 | $dbres = CSite::GetList($by, $order, $filter); 46 | while ($item = $dbres->Fetch()) { 47 | $sids[] = $item; 48 | } 49 | 50 | return $sids; 51 | } 52 | 53 | /** 54 | * @throws HelperException 55 | * @return array 56 | */ 57 | public function getSitesIfExists() 58 | { 59 | $items = $this->getSites(['ACTIVE' => 'Y']); 60 | if (!empty($items)) { 61 | return $items; 62 | } 63 | throw new HelperException( 64 | Locale::getMessage( 65 | 'ERR_ACTIVE_SITES_NOT_FOUND' 66 | ) 67 | ); 68 | } 69 | 70 | /** 71 | * @param $siteId 72 | * @return array 73 | */ 74 | public function getSiteTemplates($siteId) 75 | { 76 | $templates = []; 77 | 78 | $dbres = CSite::GetTemplateList($siteId); 79 | while ($item = $dbres->Fetch()) { 80 | $templates[] = [ 81 | "TEMPLATE" => $item['TEMPLATE'], 82 | "SORT" => $item['SORT'], 83 | "CONDITION" => $item['CONDITION'], 84 | ]; 85 | } 86 | 87 | return $templates; 88 | } 89 | 90 | /** 91 | * Устанавливает шаблоны сайта 92 | * @param $siteId 93 | * @param array $templates 94 | * @return bool 95 | */ 96 | public function setSiteTemplates($siteId, $templates = []) 97 | { 98 | $sort = 150; 99 | 100 | $validTemplates = []; 101 | foreach ($templates as $template) { 102 | if (!empty($template['IN_DIR'])) { 103 | $template['CONDITION'] = sprintf('CSite::InDir(\'%s\')', 104 | $template['IN_DIR'] 105 | ); 106 | } elseif (!empty($template['IN_PERIOD']) && is_array($template['IN_PERIOD'])) { 107 | list($t1, $t2) = $template['IN_PERIOD']; 108 | $t1 = is_numeric($t1) ? $t1 : strtotime($t1); 109 | $t2 = is_numeric($t2) ? $t2 : strtotime($t2); 110 | $template['CONDITION'] = sprintf('CSite::InPeriod(%s,%s)', 111 | $t1, 112 | $t2 113 | ); 114 | } elseif (!empty($template['IN_GROUP']) && is_array($template['IN_GROUP'])) { 115 | $template['CONDITION'] = sprintf('CSite::InGroup(array(%s))', 116 | implode(',', $template['IN_GROUP']) 117 | ); 118 | } elseif (!empty($template['GET_PARAM']) && is_array($template['GET_PARAM'])) { 119 | $val = reset($template['GET_PARAM']); 120 | $key = key($template['GET_PARAM']); 121 | $template['CONDITION'] = sprintf('$_GET[\'%s\']==\'%s\'', 122 | $key, 123 | $val 124 | ); 125 | } 126 | 127 | if (empty($template['TEMPLATE'])) { 128 | continue; 129 | } 130 | 131 | if (!isset($template['CONDITION'])) { 132 | continue; 133 | } 134 | 135 | $validTemplates[] = [ 136 | 'TEMPLATE' => $template['TEMPLATE'], 137 | 'CONDITION' => $template['CONDITION'], 138 | 'SORT' => $sort, 139 | ]; 140 | 141 | $sort++; 142 | } 143 | 144 | $langs = new CLang; 145 | return $langs->Update($siteId, [ 146 | 'TEMPLATE' => $validTemplates, 147 | ]); 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /lib/helpers/texthelper.php: -------------------------------------------------------------------------------- 1 | $value) { 13 | $data[$key] = $this->htmlspecialcharsDecodeRecursive($value); 14 | } 15 | } else { 16 | $data = htmlspecialchars_decode($data); 17 | } 18 | return $data; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/helpers/traits/iblock/iblockfieldtrait.php: -------------------------------------------------------------------------------- 1 | prepareExportIblockFields($exists); 28 | $fields = $this->prepareExportIblockFields($fields); 29 | 30 | $fields = array_replace_recursive($exportExists, $fields); 31 | 32 | if (empty($exists)) { 33 | $ok = $this->updateIblockFields($iblockId, $fields); 34 | $this->outNoticeIf( 35 | $ok, 36 | Locale::getMessage( 37 | 'IB_FIELDS_CREATED', 38 | [ 39 | '#NAME#' => $iblockId, 40 | ] 41 | ) 42 | ); 43 | return $ok; 44 | } 45 | 46 | if ($this->hasDiff($exportExists, $fields)) { 47 | $ok = $this->updateIblockFields($iblockId, $fields); 48 | $this->outNoticeIf( 49 | $ok, 50 | Locale::getMessage( 51 | 'IB_FIELDS_UPDATED', 52 | [ 53 | '#NAME#' => $iblockId, 54 | ] 55 | ) 56 | ); 57 | $this->outDiffIf($ok, $exportExists, $fields); 58 | return $ok; 59 | } 60 | 61 | return true; 62 | } 63 | 64 | /** 65 | * Получает список полей инфоблока 66 | * Данные подготовлены для экспорта в миграцию или схему 67 | */ 68 | public function exportIblockFields(int $iblockId): array 69 | { 70 | return $this->prepareExportIblockFields( 71 | $this->getIblockFields($iblockId) 72 | ); 73 | } 74 | 75 | /** 76 | * Обновляет поля инфоблока 77 | */ 78 | public function updateIblockFields(int $iblockId, array $fields): bool 79 | { 80 | if ($iblockId && !empty($fields)) { 81 | CIBlock::SetFields($iblockId, $fields); 82 | return true; 83 | } 84 | return false; 85 | } 86 | 87 | public function exportIblockElementFields(int $iblockId): array 88 | { 89 | return $this->prepareExportIblockElementFields( 90 | $this->getIblockFields($iblockId) 91 | ); 92 | } 93 | 94 | protected function prepareExportIblockFields(array $fields): array 95 | { 96 | return array_filter($fields, function ($field) { 97 | return ($field['VISIBLE'] != 'N'); 98 | }); 99 | } 100 | 101 | protected function prepareExportIblockElementFields(array $fields): array 102 | { 103 | return array_filter($fields, function ($field, $code) { 104 | return !($field['VISIBLE'] == 'N' || preg_match('/^(SECTION_|LOG_)/', $code)); 105 | }, ARRAY_FILTER_USE_BOTH); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /lib/helpers/traits/useroptions/hlblocktrait.php: -------------------------------------------------------------------------------- 1 | getHlblockTableName($hlblockId); 16 | 17 | if (empty($tableName)) { 18 | throw new HelperException( 19 | sprintf('Highload-block "%s" not found', $hlblockId) 20 | ); 21 | } 22 | 23 | return 'tbl_' . $tableName; 24 | } 25 | 26 | /** 27 | * @throws HelperException 28 | */ 29 | public function getHlblockFormId($hlblockId): string 30 | { 31 | if (empty($hlblockId)) { 32 | throw new HelperException( 33 | sprintf('Highload-block "%s" not found', $hlblockId) 34 | ); 35 | } 36 | 37 | return 'hlrow_edit_' . $hlblockId; 38 | } 39 | 40 | /** 41 | * @throws HelperException 42 | */ 43 | public function exportHlblockList($hlblockId) 44 | { 45 | return $this->exportList([ 46 | 'name' => $this->getHlblockGridId($hlblockId), 47 | ]); 48 | } 49 | 50 | /** 51 | * @throws HelperException 52 | */ 53 | public function buildHlblockList($hlblockId, $listData = []) 54 | { 55 | return $this->buildList($listData, [ 56 | 'name' => $this->getHlblockGridId($hlblockId), 57 | ]); 58 | } 59 | 60 | public function saveHlblockList($hlblockId, $listData = []) 61 | { 62 | return $this->saveList($listData, [ 63 | 'name' => $this->getHlblockGridId($hlblockId), 64 | ]); 65 | } 66 | 67 | /** 68 | * @throws HelperException 69 | */ 70 | public function exportHlblockForm($hlblockId) 71 | { 72 | return $this->exportForm([ 73 | 'name' => $this->getHlblockFormId($hlblockId), 74 | ]); 75 | } 76 | 77 | /** 78 | * @throws HelperException 79 | */ 80 | public function buildHlblockForm($hlblockId, $formData = []) 81 | { 82 | $this->buildForm($formData, [ 83 | 'name' => $this->getHlblockFormId($hlblockId), 84 | ]); 85 | } 86 | 87 | /** 88 | * @throws HelperException 89 | */ 90 | public function saveHlblockForm($hlblockId, $formData = []) 91 | { 92 | $this->saveForm($formData, [ 93 | 'name' => $this->getHlblockFormId($hlblockId), 94 | ]); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/helpers/traits/useroptions/usergrouptrait.php: -------------------------------------------------------------------------------- 1 | exportList([ 16 | 'name' => $this->getUserGroupGridId(), 17 | ]); 18 | } 19 | 20 | public function buildUserGroupList($params = []) 21 | { 22 | return $this->buildList($params, [ 23 | 'name' => $this->getUserGroupGridId(), 24 | ]); 25 | } 26 | 27 | public function saveUserGroupList($params = []) 28 | { 29 | return $this->saveList($params, [ 30 | 'name' => $this->getUserGroupGridId(), 31 | ]); 32 | } 33 | 34 | public function saveUserGroupGrid($params = []) 35 | { 36 | return $this->saveGrid($this->getUserGroupGridId(), $params); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /lib/helpers/traits/useroptions/usertrait.php: -------------------------------------------------------------------------------- 1 | exportList([ 20 | 'name' => $this->getUserGridId(), 21 | ]); 22 | } 23 | 24 | /** 25 | * @throws HelperException 26 | */ 27 | public function buildUserList($listData = []) 28 | { 29 | return $this->buildList($listData, [ 30 | 'name' => $this->getUserGridId(), 31 | ]); 32 | } 33 | 34 | /** 35 | * @throws HelperException 36 | */ 37 | public function saveUserList($listData = []) 38 | { 39 | return $this->saveList($listData, [ 40 | 'name' => $this->getUserGridId(), 41 | ]); 42 | } 43 | 44 | public function saveUserGrid($params = []) 45 | { 46 | return $this->saveGrid($this->getUserGridId(), $params); 47 | } 48 | 49 | /** 50 | * @throws HelperException 51 | */ 52 | public function exportUserForm() 53 | { 54 | return $this->exportForm([ 55 | 'name' => 'user_edit', 56 | ]); 57 | } 58 | 59 | /** 60 | * @throws HelperException 61 | */ 62 | public function buildUserForm($formData = []) 63 | { 64 | $this->buildForm($formData, [ 65 | 'name' => 'user_edit', 66 | ]); 67 | } 68 | 69 | /** 70 | * @throws HelperException 71 | */ 72 | public function saveUserForm($formData = []) 73 | { 74 | $this->saveForm($formData, [ 75 | 'name' => 'user_edit', 76 | ]); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/installer.php: -------------------------------------------------------------------------------- 1 | versionManager = new VersionManager( 23 | new VersionConfig('installer', $configValues) 24 | ); 25 | } 26 | 27 | /** 28 | * @throws MigrationException 29 | */ 30 | public function up() 31 | { 32 | $this->executeAll([], VersionEnum::ACTION_UP); 33 | } 34 | 35 | /** 36 | * @throws MigrationException 37 | */ 38 | public function down() 39 | { 40 | $this->executeAll([], VersionEnum::ACTION_DOWN); 41 | } 42 | 43 | /** 44 | * @throws MigrationException 45 | */ 46 | protected function executeAll($filter, $action) 47 | { 48 | $versionNames = $this->versionManager->getListForExecute($filter, $action); 49 | 50 | foreach ($versionNames as $versionName) { 51 | $this->executeVersion($versionName, $action); 52 | } 53 | } 54 | 55 | /** 56 | * @param string $version 57 | * @param string $action 58 | * 59 | * @throws MigrationException 60 | * @return bool 61 | */ 62 | protected function executeVersion($version, $action = VersionEnum::ACTION_UP) 63 | { 64 | $params = []; 65 | do { 66 | $exec = 0; 67 | 68 | $success = $this->versionManager->startMigration( 69 | $version, 70 | $action, 71 | $params 72 | ); 73 | 74 | $restart = $this->versionManager->needRestart(); 75 | 76 | if ($restart) { 77 | $params = $this->versionManager->getRestartParams(); 78 | $exec = 1; 79 | } 80 | 81 | if (!$success && !$restart) { 82 | if ($this->versionManager->getLastException()) { 83 | throw $this->versionManager->getLastException(); 84 | } 85 | } 86 | } while ($exec == 1); 87 | 88 | return $success; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/interfaces/readerhelperinterface.php: -------------------------------------------------------------------------------- 1 | $msg) { 13 | $MESS[self::getMessageName($shortName, $lang)] = $msg; 14 | } 15 | } 16 | 17 | public static function getMessageName($shortName, $lang = false): string 18 | { 19 | $lang = ($lang) ?: self::getLang(); 20 | 21 | return strtoupper('SPRINT_MIGRATION_' . $lang . '_' . $shortName); 22 | } 23 | 24 | public static function getLang() 25 | { 26 | return defined('LANGUAGE_ID') ? LANGUAGE_ID : 'ru'; 27 | } 28 | 29 | public static function getMessage($shortName, $replaces = [], $default = '') 30 | { 31 | $msg = GetMessage(self::getMessageName($shortName), $replaces); 32 | return ($msg) ?: ($default ?: $shortName); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/module.php: -------------------------------------------------------------------------------- 1 | $dir, 83 | ] 84 | ) 85 | ); 86 | } 87 | 88 | return $dir; 89 | } 90 | 91 | public static function deletePath($dir): void 92 | { 93 | if (is_dir($dir)) { 94 | $files = scandir($dir); 95 | foreach ($files as $file) { 96 | if ($file != "." && $file != "..") { 97 | self::deletePath("$dir/$file"); 98 | } 99 | } 100 | rmdir($dir); 101 | } elseif (file_exists($dir)) { 102 | unlink($dir); 103 | } 104 | } 105 | 106 | public static function movePath(string $from, string $to): void 107 | { 108 | rename($from, $to); 109 | } 110 | 111 | public static function getVersion(): string 112 | { 113 | if (!self::$version) { 114 | $arModuleVersion = []; 115 | include self::getModuleDir() . '/install/version.php'; 116 | self::$version = (string)($arModuleVersion['VERSION'] ?? ''); 117 | } 118 | return self::$version; 119 | } 120 | 121 | /** 122 | * @throws MigrationException 123 | */ 124 | public static function checkHealth(): void 125 | { 126 | if (!function_exists('json_encode')) { 127 | throw new MigrationException( 128 | Locale::getMessage( 129 | 'ERR_JSON_NOT_SUPPORTED' 130 | ) 131 | ); 132 | } 133 | 134 | if (version_compare(PHP_VERSION, '8.1', '<')) { 135 | throw new MigrationException( 136 | Locale::getMessage( 137 | 'ERR_PHP_NOT_SUPPORTED', 138 | [ 139 | '#NAME#' => PHP_VERSION, 140 | ] 141 | ) 142 | ); 143 | } 144 | 145 | if ( 146 | is_file($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/' . Module::ID . '/include.php') 147 | && is_file($_SERVER['DOCUMENT_ROOT'] . '/local/modules/' . Module::ID . '/include.php') 148 | ) { 149 | throw new MigrationException('module installed to bitrix and local folder'); 150 | } 151 | } 152 | } 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /lib/storagemanager.php: -------------------------------------------------------------------------------- 1 | setName('sprint:migration') 18 | ->setDescription('Migration console'); 19 | 20 | foreach ($this->getArguments() as $name) { 21 | $this->addArgument($name); 22 | } 23 | 24 | foreach ($this->getOptionsWithoutValues() as $name) { 25 | $this->addOption($name); 26 | } 27 | foreach ($this->getOptionsWithValues() as $name) { 28 | $this->addOption($name, null, InputOption::VALUE_REQUIRED); 29 | } 30 | } 31 | 32 | protected function execute(InputInterface $input, OutputInterface $output): int 33 | { 34 | $args = []; 35 | foreach ($input->getArguments() as $val) { 36 | if ($val) { 37 | $args[] = $val; 38 | } 39 | } 40 | 41 | foreach ($input->getOptions() as $key => $val) { 42 | if ($val) { 43 | if (in_array($key, $this->getOptionsWithValues())) { 44 | $args[] = '--' . $key . '=' . $val; 45 | } else { 46 | $args[] = '--' . $key; 47 | } 48 | } 49 | } 50 | try { 51 | Module::checkHealth(); 52 | $console = new Console($args); 53 | $console->executeConsoleCommand(); 54 | return self::SUCCESS; 55 | } catch (Throwable $e) { 56 | return self::FAILURE; 57 | } 58 | } 59 | 60 | protected function getOptionsWithValues(): array 61 | { 62 | return [ 63 | 'desc', 64 | 'config', 65 | 'prefix', 66 | 'name', 67 | 'from', 68 | 'as', 69 | 'search', 70 | 'tag', 71 | 'add-tag', 72 | ]; 73 | } 74 | 75 | protected function getOptionsWithoutValues(): array 76 | { 77 | return [ 78 | 'new', 79 | 'installed', 80 | 'modified', 81 | 'older', 82 | 'down', 83 | 'force', 84 | 'skip-errors', 85 | 'stop-on-errors', 86 | ]; 87 | } 88 | 89 | protected function getArguments(): array 90 | { 91 | return [ 92 | 'arg1', 93 | 'arg2', 94 | 'arg3', 95 | 'arg4', 96 | 'arg5', 97 | ]; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/symfonybundle/sprintmigrationbundle.php: -------------------------------------------------------------------------------- 1 | add(new ConsoleCommand()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/tables/formgroup.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'data_type' => 'string', 19 | 'primary' => true, 20 | ], 21 | 'FORM_ID' => [ 22 | 'data_type' => 'string', 23 | ], 24 | 'GROUP_ID' => [ 25 | 'data_type' => 'string', 26 | ], 27 | 'PERMISSION' => [ 28 | 'data_type' => 'string', 29 | ], 30 | 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/tables/option.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'data_type' => 'string', 19 | 'primary' => true, 20 | ], 21 | 'NAME' => [ 22 | 'data_type' => 'string', 23 | 'primary' => true, 24 | ], 25 | 'VALUE' => [ 26 | 'data_type' => 'string', 27 | 'required' => false, 28 | ], 29 | 'DESCRIPTION' => [ 30 | 'data_type' => 'string', 31 | 'required' => false, 32 | ], 33 | 'SITE_ID' => [ 34 | 'data_type' => 'string', 35 | 'required' => false, 36 | ], 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/tables/smstemplatesite.php: -------------------------------------------------------------------------------- 1 | array( 25 | 'data_type' => 'integer', 26 | 'primary' => true, 27 | ), 28 | 29 | 'SITE_ID' => array( 30 | 'data_type' => 'string', 31 | 'primary' => true, 32 | ), 33 | ); 34 | } 35 | 36 | /** 37 | * @throws ObjectPropertyException 38 | * @throws SystemException 39 | * @throws ArgumentException 40 | * @throws Exception 41 | */ 42 | public static function updateSites(int $templateId, array $siteIds): void 43 | { 44 | self::deleteByFilter(['=TEMPLATE_ID' => $templateId]); 45 | 46 | $dbres = SiteTable::getList([ 47 | 'select' => ['LID'], 48 | 'filter' => ['=LID' => $siteIds], 49 | ]); 50 | 51 | while ($arResultSite = $dbres->fetch()) { 52 | self::add([ 53 | 'TEMPLATE_ID' => $templateId, 54 | 'SITE_ID' => $arResultSite['LID'], 55 | ]); 56 | } 57 | } 58 | 59 | /** 60 | * @throws ObjectPropertyException 61 | * @throws SystemException 62 | * @throws ArgumentException 63 | */ 64 | public static function getSites(int $templateId): array 65 | { 66 | $sites = self::getList([ 67 | 'select' => ['*', '' => 'SITE.*'], 68 | 'filter' => ['=TEMPLATE_ID' => $templateId], 69 | 'runtime' => [ 70 | 'SITE' => [ 71 | 'data_type' => 'Bitrix\Main\Site', 72 | 'reference' => ['=this.SITE_ID' => 'ref.LID'], 73 | ], 74 | ], 75 | ])->fetchAll(); 76 | 77 | return array_filter(array_column($sites, 'LID')); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/tables/storage.php: -------------------------------------------------------------------------------- 1 | category = $category; 26 | 27 | if (empty($category)) { 28 | throw new MigrationException('Need storage category'); 29 | } 30 | } 31 | 32 | /** 33 | * @throws MigrationException 34 | */ 35 | public function saveData(string $name, $value = '') 36 | { 37 | if (empty($name)) { 38 | throw new MigrationException('Need name for saved data'); 39 | } 40 | 41 | $row = $this->getOnce([ 42 | 'category' => $this->category, 43 | 'name' => $name, 44 | ]); 45 | 46 | if ($row) { 47 | $this->update($row['id'], [ 48 | 'data' => $value, 49 | ]); 50 | } else { 51 | $this->add([ 52 | 'category' => $this->category, 53 | 'name' => $name, 54 | 'data' => $value, 55 | ]); 56 | } 57 | } 58 | 59 | /** 60 | * @throws MigrationException 61 | */ 62 | public function getSavedData(string $name, $default = '') 63 | { 64 | if (empty($name)) { 65 | throw new MigrationException('Need name for saved data'); 66 | } 67 | 68 | $row = $this->getOnce([ 69 | 'category' => $this->category, 70 | 'name' => $name, 71 | ]); 72 | 73 | return ($row) ? $row['data'] : $default; 74 | } 75 | 76 | /** 77 | * @throws MigrationException 78 | */ 79 | public function deleteSavedData(string $name = '') 80 | { 81 | if ($name) { 82 | $rows = $this->getAll([ 83 | 'category' => $this->category, 84 | 'name' => $name, 85 | ]); 86 | } else { 87 | $rows = $this->getAll([ 88 | 'category' => $this->category, 89 | ]); 90 | } 91 | 92 | foreach ($rows as $row) { 93 | $this->delete($row['id']); 94 | } 95 | } 96 | 97 | public function getMap(): array 98 | { 99 | return [ 100 | new IntegerField('id', [ 101 | 'primary' => true, 102 | 'autocomplete' => true, 103 | ]), 104 | new StringField('category', [ 105 | 'size' => 255, 106 | ]), 107 | new StringField('name', [ 108 | 'size' => 255, 109 | ]), 110 | new TextField('data', [ 111 | 'long' => true, 112 | 'serialized' => true, 113 | ]), 114 | ]; 115 | } 116 | 117 | 118 | protected function createDbTable() 119 | { 120 | parent::createDbTable(); 121 | 122 | $helper = HelperManager::getInstance(); 123 | 124 | $helper->Sql()->addIndexIfNotExists( 125 | $this->getTableName(), 126 | 'category', 127 | ['category'] 128 | ); 129 | 130 | $helper->Sql()->addIndexIfNotExists( 131 | $this->getTableName(), 132 | 'fullname', 133 | ['category', 'name'] 134 | ); 135 | } 136 | } 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /lib/tables/version.php: -------------------------------------------------------------------------------- 1 | getAll(); 23 | } 24 | 25 | /** 26 | * @throws MigrationException 27 | */ 28 | public function getRecord(string $versionName): array 29 | { 30 | return $this->getOnce(['version' => $versionName]) ?: []; 31 | } 32 | 33 | /** 34 | * @throws MigrationException 35 | */ 36 | public function addRecord(array $record) 37 | { 38 | $record['meta'] = [ 39 | 'created_by' => $this->getCurrentUserLogin(), 40 | 'created_at' => date(VersionTable::DATE_FORMAT), 41 | ]; 42 | 43 | $this->add($record); 44 | } 45 | 46 | /** 47 | * @throws MigrationException 48 | */ 49 | public function removeRecord(array $record) 50 | { 51 | $row = $this->getOnce(['version' => $record['version']]); 52 | if ($row) { 53 | $this->delete($row['id']); 54 | } 55 | } 56 | 57 | /** 58 | * @throws MigrationException 59 | */ 60 | public function updateTag(string $versionName, string $tag = '') 61 | { 62 | $row = $this->getOnce(['version' => $versionName]); 63 | if ($row) { 64 | $this->update($row['id'], ['tag' => $tag]); 65 | } 66 | } 67 | 68 | public function getMap(): array 69 | { 70 | return [ 71 | new IntegerField('id', [ 72 | 'primary' => true, 73 | 'autocomplete' => true, 74 | ]), 75 | new StringField('version', [ 76 | 'size' => 255, 77 | 'unique' => true, 78 | ]), 79 | new StringField('hash', [ 80 | 'size' => 255, 81 | ]), 82 | new StringField('tag', [ 83 | 'size' => 50, 84 | ]), 85 | new TextField('meta', [ 86 | 'long' => true, 87 | 'serialized' => true, 88 | ]), 89 | ]; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/traits/currentusertrait.php: -------------------------------------------------------------------------------- 1 | GetLogin(); 11 | } 12 | return ''; 13 | } 14 | 15 | public function getCurrentUserId(): string 16 | { 17 | if (isset($GLOBALS['USER'])) { 18 | return $GLOBALS['USER']->GetId(); 19 | } 20 | return ''; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/traits/helpermanagertrait.php: -------------------------------------------------------------------------------- 1 | params; 24 | } 25 | 26 | public function setRestartParams(array $params = []): void 27 | { 28 | $this->params = $params; 29 | } 30 | 31 | /** 32 | * @throws RestartException 33 | */ 34 | public function restartIterator(string $name, array $array, Closure $callback): void 35 | { 36 | $index = (int)($this->params[$name] ?? 0); 37 | 38 | if (isset($array[$index])) { 39 | $callback($array[$index], $index); 40 | $this->params[$name] = $index + 1; 41 | $this->restart(); 42 | } 43 | } 44 | 45 | /** 46 | * @throws RestartException 47 | */ 48 | public function restartOnce(string $name, Closure $callback): mixed 49 | { 50 | if (!array_key_exists($name, $this->params)) { 51 | $res = $callback(); 52 | $this->params[$name] = serialize($res); 53 | $this->restart(); 54 | } 55 | return unserialize($this->params[$name]); 56 | } 57 | 58 | /** 59 | * @throws RestartException 60 | */ 61 | public function restartWhile(string $name, Closure $callback): void 62 | { 63 | $index = $this->params[$name] ?? 0; 64 | 65 | if ($index !== 'finish') { 66 | $index = (int)$callback((int)$index); 67 | if ($index > 0) { 68 | $this->params[$name] = $index; 69 | $this->restart(); 70 | } else { 71 | $this->params[$name] = 'finish'; 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/traits/versionconfigtrait.php: -------------------------------------------------------------------------------- 1 | versionConfig; 14 | } 15 | 16 | public function setVersionConfig(VersionConfig $versionConfig): void 17 | { 18 | $this->versionConfig = $versionConfig; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib/version.php: -------------------------------------------------------------------------------- 1 | requiredVersions = ['Version1','Version1'] 27 | * или 28 | * $this->requiredVersions = [Version1::class,Version2::class] 29 | */ 30 | protected $requiredVersions = []; 31 | 32 | /** 33 | * @throws MigrationException 34 | */ 35 | public function up() 36 | { 37 | throw new MigrationException(Locale::getMessage('WRITE_UP_CODE')); 38 | } 39 | 40 | /** 41 | * @throws MigrationException 42 | */ 43 | public function down() 44 | { 45 | throw new MigrationException(Locale::getMessage('WRITE_DOWN_CODE')); 46 | } 47 | 48 | public function getDescription(): string 49 | { 50 | return $this->description; 51 | } 52 | 53 | public function getAuthor(): string 54 | { 55 | return $this->author; 56 | } 57 | 58 | public function getModuleVersion(): string 59 | { 60 | return $this->moduleVersion; 61 | } 62 | 63 | public function getRequiredVersions(): array 64 | { 65 | return $this->requiredVersions; 66 | } 67 | 68 | public function getVersionName(): string 69 | { 70 | return (new ReflectionClass($this))->getShortName(); 71 | } 72 | 73 | /** 74 | * @throws MigrationException 75 | */ 76 | public function checkRequiredVersions($versionNames): void 77 | { 78 | (new VersionManager( 79 | $this->getVersionConfig() 80 | ))->checkRequiredVersions($versionNames); 81 | } 82 | 83 | /** 84 | * @throws MigrationException 85 | */ 86 | protected function getStorageManager($versionName = ''): StorageManager 87 | { 88 | if (empty($versionName)) { 89 | $versionName = $this->getVersionName(); 90 | } 91 | 92 | return new StorageManager('sprint_storage_default', $versionName); 93 | } 94 | 95 | protected function getExchangeManager(): ExchangeManager 96 | { 97 | $dir = $this->getVersionConfig()->getVersionExchangeDir( 98 | $this->getVersionName() 99 | ); 100 | 101 | return new ExchangeManager($this, $dir); 102 | } 103 | } 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /options.php: -------------------------------------------------------------------------------- 1 | GetGroupRight('sprint.migration') == 'D') { 16 | Throw new Exception(Locale::getMessage("ACCESS_DENIED")); 17 | } 18 | 19 | Module::checkHealth(); 20 | 21 | include __DIR__ . '/admin/includes/options.php'; 22 | include __DIR__ . '/admin/assets/style.php'; 23 | 24 | } catch (Throwable $e) { 25 | $sperrors = []; 26 | $sperrors[] = $e->getMessage(); 27 | 28 | include __DIR__ . '/admin/includes/errors.php'; 29 | include __DIR__ . '/admin/includes/help.php'; 30 | include __DIR__ . '/admin/assets/style.php'; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /templates/AgentExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | /** 30 | * @throws Exceptions\HelperException 31 | * @return bool|void 32 | */ 33 | public function up() 34 | { 35 | $helper = $this->getHelperManager(); 36 | 37 | $helper->Agent()->saveAgent(); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /templates/EventExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | /** 30 | * @throws Exceptions\HelperException 31 | * @return bool|void 32 | */ 33 | public function up() 34 | { 35 | $helper = $this->getHelperManager(); 36 | $item) { ?> 37 | 38 | $helper->Event()->saveEventType('', ); 39 | 40 | 41 | $helper->Event()->saveEventMessage('', ); 42 | 43 | 44 | $helper->Event()->saveEventSmsTemplate('', ); 45 | 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /templates/FormExport.php: -------------------------------------------------------------------------------- 1 | 18 | 19 | namespace Sprint\Migration; 20 | 21 | 22 | 23 | class extends 24 | 25 | { 26 | protected $author = ""; 27 | 28 | protected $description = ""; 29 | 30 | protected $moduleVersion = ""; 31 | 32 | /** 33 | * @throws Exceptions\HelperException 34 | * @return bool|void 35 | */ 36 | public function up() 37 | { 38 | $helper = $this->getHelperManager(); 39 | 40 | $formId = $helper->Form()->saveForm(); 41 | 42 | $formId = $helper->Form()->getFormIdIfExists(''); 43 | 44 | 45 | $helper->Form()->saveStatuses($formId, ); 46 | 47 | 48 | $helper->Form()->saveFields($formId, ); 49 | 50 | 51 | 52 | $helper->Form()->saveField($formId, ); 53 | 54 | 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /templates/HlblockElementsExport.php: -------------------------------------------------------------------------------- 1 | 17 | 18 | namespace Sprint\Migration; 19 | 20 | 21 | 22 | class extends 23 | 24 | { 25 | protected $author = ""; 26 | 27 | protected $description = ""; 28 | 29 | protected $moduleVersion = ""; 30 | 31 | /** 32 | * @throws Exceptions\MigrationException 33 | * @throws Exceptions\RestartException 34 | * @throws Exceptions\HelperException 35 | * @return bool|void 36 | */ 37 | public function up() 38 | { 39 | $this->getExchangeManager() 40 | ->HlblockElementsImport() 41 | ->setLimit(20) 42 | ->execute(function ($item) { 43 | 44 | $this->getHelperManager() 45 | ->Hlblock() 46 | ->saveElementByXmlId( 47 | $item['hlblock_id'], 48 | $item['fields'] 49 | ); 50 | 51 | $this->getHelperManager() 52 | ->Hlblock() 53 | ->addElement( 54 | $item['hlblock_id'], 55 | $item['fields'] 56 | ); 57 | 58 | }); 59 | } 60 | 61 | /** 62 | * @throws Exceptions\MigrationException 63 | * @throws Exceptions\RestartException 64 | * @throws Exceptions\HelperException 65 | * @return bool|void 66 | */ 67 | public function down() 68 | { 69 | 70 | $this->getExchangeManager() 71 | ->HlblockElementsImport() 72 | ->setLimit(20) 73 | ->execute(function ($item) { 74 | $this->getHelperManager() 75 | ->Hlblock() 76 | ->deleteElementByXmlId( 77 | $item['hlblock_id'], 78 | $item['fields']['UF_XML_ID'] 79 | ); 80 | }); 81 | 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /templates/HlblockExport.php: -------------------------------------------------------------------------------- 1 | 20 | 21 | namespace Sprint\Migration; 22 | 23 | 24 | 25 | class extends 26 | 27 | { 28 | protected $author = ""; 29 | 30 | protected $description = ""; 31 | 32 | protected $moduleVersion = ""; 33 | 34 | /** 35 | * @throws Exceptions\HelperException 36 | * @return bool|void 37 | */ 38 | public function up() 39 | { 40 | $helper = $this->getHelperManager(); 41 | 42 | $hlblockId = $helper->Hlblock()->saveHlblock(); 43 | 44 | $hlblockId = $helper->Hlblock()->getHlblockIdIfExists(''); 45 | 46 | 47 | $helper->Hlblock()->saveGroupPermissions($hlblockId, ); 48 | 49 | 50 | 51 | $helper->Hlblock()->saveField($hlblockId, ); 52 | 53 | 54 | 55 | $helper->UserOptions()->saveHlblockForm($hlblockId, ); 56 | 57 | 58 | $helper->UserOptions()->saveHlblockList($hlblockId, ); 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /templates/IblockCategoryExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | /** 30 | * @throws Exceptions\HelperException 31 | * @return bool|void 32 | */ 33 | public function up() 34 | { 35 | $helper = $this->getHelperManager(); 36 | 37 | $iblockId = $helper->Iblock()->getIblockIdIfExists( 38 | '', 39 | '' 40 | ); 41 | 42 | $helper->Iblock()->addSectionsFromTree( 43 | $iblockId, 44 | 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /templates/IblockDelete.php: -------------------------------------------------------------------------------- 1 | 16 | 17 | namespace Sprint\Migration; 18 | 19 | 20 | 21 | class extends 22 | 23 | { 24 | protected $author = ""; 25 | 26 | protected $description = ""; 27 | 28 | protected $moduleVersion = ""; 29 | 30 | public function up() 31 | { 32 | $helper = $this->getHelperManager(); 33 | 34 | 35 | $helper->Iblock()->deleteIblockIfExists('', ''); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /templates/IblockElementsExport.php: -------------------------------------------------------------------------------- 1 | 17 | 18 | namespace Sprint\Migration; 19 | 20 | 21 | class extends 22 | 23 | { 24 | protected $author = ""; 25 | 26 | protected $description = ""; 27 | 28 | protected $moduleVersion = ""; 29 | 30 | /** 31 | * @throws Exceptions\MigrationException 32 | * @throws Exceptions\RestartException 33 | * @return bool|void 34 | */ 35 | public function up() 36 | { 37 | $this->getExchangeManager() 38 | ->IblockElementsImport() 39 | ->setLimit(20) 40 | ->execute(function ($item) { 41 | 42 | $this->getHelperManager() 43 | ->Iblock() 44 | ->saveElement( 45 | $item['iblock_id'], 46 | $item['fields'], 47 | $item['properties'] 48 | ); 49 | 50 | $this->getHelperManager() 51 | ->Iblock() 52 | ->saveElementByXmlId( 53 | $item['iblock_id'], 54 | $item['fields'], 55 | $item['properties'] 56 | ); 57 | 58 | $this->getHelperManager() 59 | ->Iblock() 60 | ->addElement( 61 | $item['iblock_id'], 62 | $item['fields'], 63 | $item['properties'] 64 | ); 65 | 66 | }); 67 | } 68 | 69 | /** 70 | * @throws Exceptions\MigrationException 71 | * @throws Exceptions\RestartException 72 | * @return bool|void 73 | */ 74 | public function down() 75 | { 76 | 77 | $this->getExchangeManager() 78 | ->IblockElementsImport() 79 | ->setLimit(10) 80 | ->execute(function ($item) { 81 | $this->getHelperManager() 82 | ->Iblock() 83 | ->deleteElementByCode( 84 | $item['iblock_id'], 85 | $item['fields']['CODE'] 86 | ); 87 | }); 88 | 89 | $this->getExchangeManager() 90 | ->IblockElementsImport() 91 | ->setLimit(10) 92 | ->execute(function ($item) { 93 | $this->getHelperManager() 94 | ->Iblock() 95 | ->deleteElementByXmlId( 96 | $item['iblock_id'], 97 | $item['fields']['XML_ID'] 98 | ); 99 | }); 100 | 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /templates/IblockExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | /** 30 | * @throws Exceptions\HelperException 31 | * @return bool|void 32 | */ 33 | public function up() 34 | { 35 | $helper = $this->getHelperManager(); 36 | 37 | $helper->Iblock()->saveIblockType(); 38 | 39 | 40 | $iblockId = $helper->Iblock()->saveIblock(); 41 | 42 | $iblockId = $helper->Iblock()->getIblockIdIfExists('', ''); 43 | 44 | 45 | $helper->Iblock()->saveIblockFields($iblockId, ); 46 | 47 | 48 | $helper->Iblock()->saveGroupPermissions($iblockId, ); 49 | 50 | 51 | 52 | $helper->Iblock()->saveProperty($iblockId, ); 53 | 54 | 55 | 56 | $helper->UserOptions()->saveElementForm($iblockId, ); 57 | 58 | 59 | $helper->UserOptions()->saveSectionForm($iblockId, ); 60 | 61 | 62 | $helper->UserOptions()->saveElementList($iblockId, ); 63 | 64 | 65 | $helper->UserOptions()->saveSectionList($iblockId, ); 66 | 67 | 68 | $helper->UserOptions()->saveElementGrid($iblockId, ); 69 | 70 | 71 | $helper->UserOptions()->saveSectionGrid($iblockId, ); 72 | 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /templates/MedialibElementsExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | 24 | protected $author = ""; 25 | 26 | protected $description = ""; 27 | 28 | protected $moduleVersion = ""; 29 | 30 | /** 31 | * @throws Exceptions\MigrationException 32 | * @throws Exceptions\RestartException 33 | * @throws Exceptions\HelperException 34 | * @return bool|void 35 | */ 36 | public function up() 37 | { 38 | $this->getExchangeManager() 39 | ->MedialibElementsImport() 40 | ->setLimit(20) 41 | ->execute( 42 | function ($item) { 43 | $this->getHelperManager() 44 | ->Medialib() 45 | ->saveElement($item); 46 | } 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /templates/OptionExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | public function up() 30 | { 31 | $helper = $this->getHelperManager(); 32 | 33 | $helper->Option()->saveOption(); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /templates/UserGroupExport.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | /** 30 | * @throws Exceptions\HelperException 31 | * @return bool|void 32 | */ 33 | public function up() 34 | { 35 | $helper = $this->getHelperManager(); 36 | 37 | 38 | $helper->UserGroup()->saveGroup('',); 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /templates/UserOptionsExport.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | namespace Sprint\Migration; 16 | 17 | 18 | 19 | class extends 20 | 21 | { 22 | protected $author = ""; 23 | 24 | protected $description = ""; 25 | 26 | protected $moduleVersion = ""; 27 | 28 | public function up() 29 | { 30 | $helper = $this->getHelperManager(); 31 | 32 | $helper->UserOptions()->saveUserForm(); 33 | 34 | 35 | $helper->UserOptions()->saveUserList(); 36 | 37 | 38 | $helper->UserOptions()->saveUserGroupList(); 39 | 40 | 41 | $helper->UserOptions()->saveUserGrid(); 42 | 43 | 44 | $helper->UserOptions()->saveUserGroupGrid(); 45 | 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /templates/UserTypeEntities.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | namespace Sprint\Migration; 17 | 18 | 19 | 20 | class extends 21 | 22 | { 23 | protected $author = ""; 24 | 25 | protected $description = ""; 26 | 27 | protected $moduleVersion = ""; 28 | 29 | /** 30 | * @throws Exceptions\HelperException 31 | * @return bool|void 32 | */ 33 | public function up() 34 | { 35 | $helper = $this->getHelperManager(); 36 | 37 | $helper->UserTypeEntity()->saveUserTypeEntity(); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /templates/version.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | namespace Sprint\Migration; 16 | 17 | 18 | 19 | class extends 20 | 21 | { 22 | protected $author = ""; 23 | 24 | protected $description = ""; 25 | 26 | protected $moduleVersion = ""; 27 | 28 | public function up() 29 | { 30 | $helper = $this->getHelperManager(); 31 | //your code ... 32 | } 33 | 34 | public function down() 35 | { 36 | //your code ... 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tools/migrate.php: -------------------------------------------------------------------------------- 1 | DoInstall(); 32 | } 33 | } 34 | 35 | if (!Loader::includeModule('sprint.migration')) { 36 | Throw new Exception('need to install module sprint.migration'); 37 | } 38 | 39 | Sprint\Migration\Module::checkHealth(); 40 | 41 | $console = new Sprint\Migration\Console($argv); 42 | $console->executeConsoleCommand(); 43 | 44 | require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_after.php"); 45 | 46 | } catch (Throwable $exception) { 47 | fwrite(STDOUT, sprintf( 48 | "[%s] %s (%s) in %s:%d \n", 49 | get_class($exception), 50 | $exception->getMessage(), 51 | $exception->getCode(), 52 | $exception->getFile(), 53 | $exception->getLine() 54 | )); 55 | 56 | die(1); 57 | } 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /updater.php: -------------------------------------------------------------------------------- 1 | CopyFiles("install/gadgets/", "gadgets/"); 68 | } 69 | 70 | //v 4.12.4 71 | } 72 | --------------------------------------------------------------------------------