├── .gitignore
├── LICENSE
├── README.md
├── admin
├── applyError.php
├── changeversion.php
├── cli.php
├── controller.php
├── createScenario.php
├── detail.php
├── diagnostic.php
├── entitiesVersions.php
├── log.php
├── main.php
├── menu.php
└── newChangesList.php
├── data
├── apply_scheme.png
├── change_analyze.png
├── change_event.png
├── classes_scheme.png
├── cli_apply.png
├── cli_help.png
├── cli_list.png
├── cli_rollback.png
├── create_dump.png
├── create_scenario.png
├── create_scenario_was_success.png
├── development_scheme.png
├── export.png
├── import.png
├── init_module_params.png
├── item_changes_list.png
├── main.png
├── main_with_scenario.png
├── scenarioTemplate.tpl
├── scenario_code.png
├── settings_page.png
├── update_scenario.png
├── updatelog.png
├── versions_demo.png
└── versions_developer.png
├── description.ru
├── docs
├── auto.md
├── cli.md
├── scripts.md
├── setup.md
├── start.md
└── update.md
├── include.php
├── install
├── admin
│ └── ws_migrations.php
├── db
│ ├── install.sql
│ └── uninstall.sql
├── form.php
├── index.php
├── tools
│ └── ws_migrations.php
├── uninstall.php
├── upload
│ └── ws.migrations
│ │ └── .htaccess
└── version.php
├── lang
├── en
│ ├── admin.php
│ ├── handlers.php
│ ├── info.php
│ ├── menu.php
│ ├── processes.php
│ ├── setup.php
│ ├── tests.php
│ └── uninstall.php
└── ru
│ ├── admin.php
│ ├── handlers.php
│ ├── info.php
│ ├── menu.php
│ ├── processes.php
│ ├── setup.php
│ ├── tests.php
│ └── uninstall.php
├── lib
├── applyresult.php
├── builder
│ ├── agentbuilder.php
│ ├── builderexception.php
│ ├── entity
│ │ ├── agent.php
│ │ ├── base.php
│ │ ├── enumvariant.php
│ │ ├── eventmessage.php
│ │ ├── eventtype.php
│ │ ├── form.php
│ │ ├── formanswer.php
│ │ ├── formfield.php
│ │ ├── formstatus.php
│ │ ├── highloadblock.php
│ │ ├── iblock.php
│ │ ├── iblocksection.php
│ │ ├── iblocktype.php
│ │ ├── property.php
│ │ └── userfield.php
│ ├── eventsbuilder.php
│ ├── formbuilder.php
│ ├── highloadblockbuilder.php
│ └── iblockbuilder.php
├── callback.php
├── changedatacollector
│ ├── collector.php
│ └── collectorfix.php
├── console
│ ├── command
│ │ ├── applycommand.php
│ │ ├── basecommand.php
│ │ ├── createscenariocommand.php
│ │ ├── helpcommand.php
│ │ ├── lastcommand.php
│ │ ├── listcommand.php
│ │ └── rollbackcommand.php
│ ├── console.php
│ ├── consoleexception.php
│ ├── formatter
│ │ └── output.php
│ ├── runtimecounter.php
│ └── runtimefixcounter.php
├── diagnostic
│ ├── diagnosticresult.php
│ ├── diagnostictester.php
│ └── errormessage.php
├── entities
│ ├── appliedchangeslog.php
│ ├── appliedchangeslogmodel.php
│ ├── baseentity.php
│ ├── dbversionreferences.php
│ ├── eventmessage.php
│ ├── setuplog.php
│ └── setuplogmodel.php
├── factories
│ └── datetimefactory.php
├── localization.php
├── module.php
├── moduleoptions.php
├── options.php
├── platformversion.php
├── processes
│ ├── addprocess.php
│ ├── baseprocess.php
│ ├── deleteprocess.php
│ └── updateprocess.php
├── reference
│ ├── referencecontroller.php
│ └── referenceitem.php
├── scriptscenario.php
├── subjecthandlers
│ ├── basesubjecthandler.php
│ ├── iblockhandler.php
│ ├── iblockpropertyhandler.php
│ └── iblocksectionhandler.php
└── tests
│ ├── abstractcase.php
│ ├── cases
│ ├── agentbuildercase.php
│ ├── errorexception.php
│ ├── eventsbuildercase.php
│ ├── fixtestcase.php
│ ├── formbuildercase.php
│ ├── highloadblockbuildercase.php
│ ├── iblockbuildercase.php
│ ├── installtestcase.php
│ ├── rollbacktestcase.php
│ └── updatetestcase.php
│ ├── fixtures
│ ├── add_collection.json
│ ├── delete_iblock.json
│ ├── delete_property.json
│ ├── delete_section.json
│ └── update_collection.json
│ ├── result.php
│ └── starter.php
├── options.php
├── prolog.php
└── updater.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 WorkSolutions
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Модуль миграций
2 | ===============
3 |
4 | Модуль для CMS "1С-Битрикс", помогает реализовать быстрые изменения схемы данных проекта.
5 |
6 | ### Предупреждение об ограниченной поддержке
7 |
8 | __Данный модуль больше не имеет активной поддержки, рекомендуем вам ознакомиться с [новым модулем миграций](https://github.com/worksolutions/bitrix-reduce-migrations)__
9 |
10 | ### Введение
11 |
12 | Как известно, исходный код плотно взаимодействует со структурой данных в проекте. С появлением новых функциональных требований исходный код изменяется,
13 | он требует новые поля для хранения даных, либо определяет новые сущности, которые отражаются в отдельных таблицах,
14 | а в проектах основанных на CMS "1С-Битрикс" данные в основном отражены в инфоблоках.
15 |
16 | Основная структура хранения данных проекта, написанного на Битриксе, отличается от общепринятой.
17 | Сущности хранятся не в отдельных таблицах, а абстрагированы в виде инфоблоков в разных местах, поэтому стандартные
18 | инструменты работы с данными, в таких проектах, не всегда справляются со своими задачами.
19 |
20 | Модуль миграций основан на исходном коде ядра CMS и поэтому позволяет в наиболее удобной форме осуществлять синхронизацию. Идея состоит в том,
21 | что проект имеет специальный каталог для хранения файлов, описывающих преобразование данных; этот каталог обновляется вместе с исходным кодом проекта.
22 | При обновлении исходного кода можно обновить базу данных проекта, чтобы она соответствовала новому функционалу.
23 |
24 | Модуль имеет два типа синхронизации:
25 |
26 | 1. Автоматическая - синхронизируются базовые данные инфоблоков, свойств, секций
27 | 2. Сценарии миграции - этап обновления реализуется разработчиком согласно требуемого алгоритма
28 |
29 | ### Разделы описания
30 |
31 | * [Установка и настройка](docs/setup.md)
32 | * [Начало работы](docs/start.md)
33 | * [Обновление площадки](docs/update.md)
34 | * [Интерфейс командной строки](docs/cli.md)
35 | * [Как происходит автоматический учет изменений](docs/auto.md)
36 | * [Скрипты миграций](docs/scripts.md)
37 |
--------------------------------------------------------------------------------
/admin/applyError.php:
--------------------------------------------------------------------------------
1 | array('=id' => $id)));
7 | if (!$model) {
8 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php");
9 | ShowError($localization->message('error.modelNotExists', array(
10 | ':id:' => $id
11 | )));
12 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin_js.php");
13 | }
14 | /** @var CMain $APPLICATION */
15 | $errorData = \WS\Migrations\jsonToArray($model->description) ?: array('message' => $model->description);
16 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php");
17 | ?>
18 |
19 |
20 |
21 | =$localization->message('message')?>
22 | |
23 |
24 |
25 | |
26 |
27 |
30 |
31 |
32 | =$localization->message('data')?>
33 | |
34 |
35 |
36 | |
37 |
38 |
41 |
44 |
45 |
46 | =$localization->message('trace')?>
47 | |
48 |
49 |
50 | $value):
52 | ?>
53 | -
54 | ='('.$k.') '.$value['file'].':'.$value['line']?>
55 |
56 | =$value['class'].$value['type'].$value['function']?>
57 |
58 | =$localization->message('arguments')?>
59 |
60 |
61 |
64 |
65 | |
66 |
67 |
70 |
71 |
86 | getRequest();
6 |
7 | /** @var \WS\Migrations\PlatformVersion $platformVersion */
8 | $platformVersion = \WS\Migrations\Module::getInstance()->getPlatformVersion();
9 | if ($request->isPost()) {
10 | $post = $request->getPostList()->toArray();
11 | $post = \Bitrix\Main\Text\Encoding::convertEncodingArray($post, "UTF-8", $context->getCulture()->getCharset());
12 | if ($post['changeversion']) {
13 | \WS\Migrations\Module::getInstance()->runRefreshVersion();
14 | }
15 | if ($post['ownersetup']) {
16 | $platformVersion->setOwner($post['ownersetup']['owner']);
17 | $options = \WS\Migrations\Module::getInstance()->getOptions();
18 | exit();
19 | }
20 | }
21 | /** @var $localization \WS\Migrations\Localization */
22 | $localization;
23 | $APPLICATION->SetTitle($localization->getDataByPath('pageTitle'));
24 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");
25 | ?>
91 |
129 |
--------------------------------------------------------------------------------
/admin/cli.php:
--------------------------------------------------------------------------------
1 | Authorize(1);
19 |
20 | $module = \WS\Migrations\Module::getInstance();
21 | $console = new Console($argv);
22 |
23 | $getShowProgress = function () use ($console) {
24 | $counter = new \WS\Migrations\Console\RuntimeCounter();
25 | return function ($data, $type) use ($console, $counter) {
26 | if ($type == 'setCount') {
27 | $counter->migrationCount = $data;
28 | $counter->start = microtime(true);
29 | }
30 | if ($type == 'start') {
31 | $counter->migrationNumber++;
32 | $console->printLine("{$data['name']}({$counter->migrationNumber}/$counter->migrationCount)", Console::OUTPUT_PROGRESS);
33 | }
34 | if ($type == 'end') {
35 | /**@var \WS\Migrations\Entities\AppliedChangesLogModel $log */
36 | $log = $data['log'];
37 | $time = round($data['time'], 2);
38 | $message = '';
39 | if (!empty($data['error'])) {
40 | $message .= $data['error'] . '. ';
41 | }
42 | $overallTime = round(microtime(true) - $counter->start, 2);
43 | $message .= "$time sec ($overallTime sec)";
44 | $console->printLine($message, $log->success ? Console::OUTPUT_SUCCESS: Console::OUTPUT_ERROR);
45 | }
46 | };
47 | };
48 | try {
49 | $console->printLine("");
50 | $command = $console->getCommand();
51 | $command->execute($getShowProgress());
52 | $module->commitDutyChanges();
53 | } catch (\WS\Migrations\Console\ConsoleException $e) {
54 | $console->printLine($e->getMessage());
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/admin/controller.php:
--------------------------------------------------------------------------------
1 | isAdmin()) {
7 | return ;
8 | }
9 |
10 | CModule::IncludeModule('ws.migrations');
11 | CModule::IncludeModule('iblock');
12 |
13 | $request = $_REQUEST;
14 | $action = $request['q'];
15 | $fAction = function ($file) use ($action) {
16 | global
17 | $USER, $DB, $APPLICATION, $adminPage, $adminMenu, $adminChain;
18 | $localization = \WS\Migrations\Module::getInstance()->getLocalization('admin')->fork($action);
19 | include $file;
20 | };
21 |
22 | $actionFile = __DIR__.DIRECTORY_SEPARATOR.$request['q'].'.php';
23 | if (file_exists($actionFile)) {
24 | $fAction($actionFile);
25 | } else {
26 | /* @var $APPLICATION CMain */
27 | $APPLICATION->ThrowException("Action `$actionFile` not exists");
28 | }
29 | require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_admin_after.php");
30 | ?>
--------------------------------------------------------------------------------
/admin/createScenario.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/admin/createScenario.php
--------------------------------------------------------------------------------
/admin/diagnostic.php:
--------------------------------------------------------------------------------
1 | getRequest();
6 |
7 | $tester = \WS\Migrations\Module::getInstance()->useDiagnostic();
8 | if ($request->isPost()) {
9 | $post = $request->getPostList()->toArray();
10 | $run = (bool)$post['run'];
11 | $run && $tester->run();
12 | }
13 | $lastResult = $tester->getLastResult();
14 | /** @var $localization \WS\Migrations\Localization */
15 | $localization;
16 |
17 | $APPLICATION->SetTitle($localization->getDataByPath('title'));
18 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");
19 | ?>
--------------------------------------------------------------------------------
/admin/entitiesVersions.php:
--------------------------------------------------------------------------------
1 | SetTitle($localization->getDataByPath('title'));
10 | $sTableID = "ws_migrations_versions_table";
11 | $oSort = new CAdminSorting($sTableID, "date", "asc");
12 | $lAdmin = new CAdminList($sTableID, $oSort);
13 |
14 | $arHeaders = array(
15 | array("id" => "reference", "content" => $localization->getDataByPath('fields.reference'), "default"=>true),
16 | array("id" => "versions", "content" => $localization->getDataByPath('fields.versions'), "default" => true),
17 | array("id" => "destination", "content" => $localization->getDataByPath('fields.destination'), "default" => true),
18 | );
19 | $platformVersion = $module->getPlatformVersion();
20 | $lAdmin->AddHeaders($arHeaders);
21 |
22 | $rsData = \WS\Migrations\Entities\DbVersionReferencesTable::getList(array('limit' => 500));
23 | $arData = array();
24 | while ($iData = $rsData->fetch()) {
25 | !$arData[$iData['REFERENCE']] && $arData[$iData['REFERENCE']] = array(
26 | 'reference' => $iData['REFERENCE'],
27 | 'versions' => array()
28 | );
29 |
30 | $arData[$iData['REFERENCE']]['versions'][] = array(
31 | 'id' => $iData['ITEM_ID'],
32 | 'version' => $iData['DB_VERSION']
33 | );
34 |
35 | $iData['DB_VERSION'] == $platformVersion->getValue() && $arData[$iData['REFERENCE']]['data'] = array(
36 | 'id' => $iData['ITEM_ID'],
37 | 'subject' => $iData['GROUP']
38 | );
39 | }
40 | $rsData = new CAdminResult($arData, $sTableID);
41 | $rsData->NavStart();
42 |
43 | $lAdmin->NavText($rsData->GetNavPrint($localization->getDataByPath('messages.pages')));
44 |
45 | $versionsList = $platformVersion->getMapVersions();
46 |
47 | $fCreateUrlFromEntity = function ($type, $id) {
48 | $urlTemplate = '';
49 | switch ($type) {
50 | case 'iblock':
51 | $arIblock = CIBlock::GetArrayByID($id);
52 | $type = $arIblock['IBLOCK_TYPE_ID'];
53 | $urlTemplate = '/bitrix/admin/iblock_edit.php?type='.$type.'&ID='.$id. '&lang=' . LANGUAGE_ID;
54 | break;
55 | case 'iblockProperty':
56 | $arProperty = CIBlockProperty::GetByID($id)->Fetch();
57 | $iblockId = $arProperty['IBLOCK_ID'];
58 | $arIblock = CIBlock::GetArrayByID($iblockId);
59 | $type = $arIblock['IBLOCK_TYPE_ID'];
60 | $urlTemplate = '/bitrix/admin/iblock_edit.php?type='.$type.'&ID='.$iblockId. '&lang=' . LANGUAGE_ID;
61 | break;
62 | case 'iblockSection':
63 | $arSection = CIBlockSection::GetByID($id)->Fetch();
64 | $iblockId = $arSection['IBLOCK_ID'];
65 | $urlTemplate = '/bitrix/admin/iblock_section_edit.php?IBLOCK_ID='.$iblockId.'&ID='.$id. '&lang=' . LANGUAGE_ID;
66 | break;
67 | }
68 | return $urlTemplate;
69 | };
70 |
71 | $fGetVersionsHtml = function ($versions) use (& $versionsList) {
72 |
73 | $strings = array_map(function ($version) use ($versionsList) {
74 | return "({$version['id']}) - ". ($versionsList[$version['version']] ?: $version['version']);
75 | }, $versions);
76 |
77 | return implode('
', $strings);
78 | };
79 |
80 | while ($rowData = $rsData->NavNext()) {
81 | $row = $lAdmin->AddRow($rowData['reference']);
82 | $row->AddField('reference', $rowData['reference']);
83 | $row->AddViewField('versions', $fGetVersionsHtml($rowData['versions']));
84 | $row->AddViewField('destination',
85 | '['
86 | .$rowData['data']['id'].'] '.$localization->message('subjects.'.$rowData['data']['subject'])
87 | .''
88 | );
89 | }
90 |
91 | if ($_REQUEST["mode"] == "list") {
92 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php");
93 | } else {
94 | require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");
95 | }
96 |
97 | $lAdmin->CheckListMode();
98 | $lAdmin->DisplayList();
99 |
100 | if ($_REQUEST["mode"] == "list") {
101 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin_js.php");
102 | } else {
103 | require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php");
104 | }
105 |
--------------------------------------------------------------------------------
/admin/log.php:
--------------------------------------------------------------------------------
1 | SetTitle($localization->getDataByPath('title'));
13 | $sTableID = "ws_migrations_log_table";
14 | $oSort = new CAdminSorting($sTableID, "date", "asc");
15 | $lAdmin = new CAdminList($sTableID, $oSort);
16 |
17 | $arHeaders = array(
18 | array("id" => "updateDate", "content" => $localization->getDataByPath('fields.updateDate'), "default"=>true),
19 | array("id" => "description", "content" => $localization->getDataByPath('fields.description'), "default" => true),
20 | array("id" => "source", "content" => $localization->getDataByPath('fields.source'), "default" => true),
21 | array("id" => "dispatcher", "content" => $localization->getDataByPath('fields.dispatcher'), "default" => true)
22 | );
23 | $lAdmin->AddHeaders($arHeaders);
24 |
25 | $models = AppliedChangesLogModel::find(array(
26 | 'limit' => 500,
27 | 'order' => array(
28 | 'groupLabel' => 'desc'
29 | )
30 | ));
31 |
32 | $rowsData = array();
33 | $versions = $module->getPlatformVersion()->getMapVersions();
34 | array_walk($models, function (AppliedChangesLogModel $model) use (& $rowsData, $versions) {
35 | if (in_array($model->description, array('Insert reference', 'References updates'))) {
36 | return;
37 | }
38 | $row = & $rowsData[$model->groupLabel];
39 | if(!$row) {
40 | $row = array(
41 | 'label' => $model->groupLabel,
42 | 'updateDate' => $model->date->format('d.m.Y H:i:s'),
43 | 'source' => $versions[$model->source] ?: $model->source,
44 | 'dispatcher' => $model->getSetupLog() ? $model->getSetupLog()->shortUserInfo() : ''
45 | );
46 | }
47 | $row['description'] = $row['description'] ? implode("
", array($row['description'], $model->description)) : $model->description;
48 | if (!$model->success) {
49 | $row['error'][] = array(
50 | 'data' => \WS\Migrations\jsonToArray($model->description) ?: array('message' => $model->description),
51 | 'id' => $model->id
52 | );
53 | }
54 | });
55 |
56 | $rsData = new CAdminResult(null, $sTableID);
57 | $rsData->InitFromArray($rowsData);
58 | $rsData->NavStart();
59 |
60 | $lAdmin->NavText($rsData->GetNavPrint($localization->getDataByPath('messages.pages')));
61 | while ($rowData = $rsData->NavNext()) {
62 | $row = $lAdmin->AddRow($rowData['label'], $rowData);
63 | $description = $rowData['description'];
64 | if ($rowData['error']) {
65 | $description = array();
66 | foreach ($rowData['error'] as $rowErrorData) {
67 | $description[] = ''.$rowErrorData['data']['message'].'';
68 | }
69 | $description = implode('
', $description);
70 | }
71 |
72 | $row->AddViewField('description', $description);
73 | $row->AddActions(array(
74 | array(
75 | "ICON" => "view",
76 | "TEXT" => $localization->message('messages.view'),
77 | "ACTION" => $lAdmin->ActionRedirect("ws_migrations.php?q=detail&label=".$rowData['label'].'&type=applied'. '&lang=' . LANGUAGE_ID),
78 | "DEFAULT" => true
79 | )
80 | ));
81 | }
82 | if ($_REQUEST["mode"] == "list") {
83 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php");
84 | } else {
85 | require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");
86 | }
87 |
88 | $lAdmin->CheckListMode();
89 | $lAdmin->DisplayList();
90 | ?>
91 |
107 | isAdmin()) {
4 | return array();
5 | }
6 | $loc = \WS\Migrations\Module::getInstance()->getLocalization('menu');
7 | $inputUri = '/bitrix/admin/ws_migrations.php?lang=' . LANGUAGE_ID . '&q=';
8 | return array(
9 | array(
10 | 'parent_menu' => 'global_menu_settings',
11 | 'sort' => 500,
12 | 'text' => $loc->getDataByPath('title'),
13 | 'title' => $loc->getDataByPath('title'),
14 | 'module_id' => 'ws.migrations',
15 | 'icon' => '',
16 | 'items_id' => 'ws_migrations_menu',
17 | 'items' => array(
18 | array(
19 | 'text' => $loc->getDataByPath('apply'),
20 | 'url' => $inputUri.'main',
21 | ),
22 | array(
23 | 'text' => $loc->getDataByPath('automigrations'),
24 | 'items_id' => 'ws_migrations_menu_auto',
25 | 'items' => array(
26 | array(
27 | 'text' => $loc->getDataByPath('changeversion'),
28 | 'url' => $inputUri.'changeversion',
29 | ),
30 | array(
31 | 'text' => $loc->getDataByPath('entitiesVersions'),
32 | 'url' => $inputUri.'entitiesVersions'
33 | ),
34 | ),
35 | ),
36 | array(
37 | 'text' => $loc->getDataByPath('createScenario'),
38 | 'url' => $inputUri.'createScenario'
39 | ),
40 | array(
41 | 'text' => $loc->getDataByPath('diagnostic'),
42 | 'url' => $inputUri.'diagnostic'
43 | ),
44 | array(
45 | 'text' => $loc->getDataByPath('log'),
46 | 'url' => $inputUri.'log',
47 | 'more_url' => array($inputUri.'detail')
48 | )
49 | )
50 | )
51 | );
52 |
--------------------------------------------------------------------------------
/admin/newChangesList.php:
--------------------------------------------------------------------------------
1 | "date", "content" => $localization->getDataByPath('fields.date'), "default"=>true),
15 | array("id" => "description", "content" => $localization->getDataByPath('fields.description'), "default" => true),
16 | array("id" => "source", "content" => $localization->getDataByPath('fields.source'), "default" => true),
17 | );
18 | $lAdmin->AddHeaders($arHeaders);
19 |
20 | /** @var CollectorFix[] $fixes */
21 | $fixes = $module->getNotAppliedFixes();
22 |
23 | $rowsData = array();
24 | array_walk($fixes, function (CollectorFix $fix) use (& $rowsData, $localization) {
25 | if (in_array($fix->getName(), array('Insert reference', 'References updates', 'Reference fix'))) {
26 | return;
27 | }
28 | $row = & $rowsData[$fix->getLabel()];
29 | if(!$row) {
30 | $time = str_replace(".json", "", $fix->getLabel());
31 | $row = array(
32 | 'label' => $fix->getLabel(),
33 | 'date' => FormatDate("Q " . $localization->message("message.ago"), $time),
34 | 'source' => $fix->getOwner() ?: $fix->getDbVersion()
35 | );
36 | }
37 | $row['description'] = $row['description'] ? implode("
", array($row['description'], $fix->getName())) : $fix->getName();
38 | });
39 |
40 | $rsData = new CAdminResult(null, $sTableID);
41 | $rsData->InitFromArray($rowsData);
42 | $rsData->NavStart(500);
43 |
44 | while ($rowData = $rsData->NavNext()) {
45 | $row = $lAdmin->AddRow($rowData['label'], $rowData);
46 | $row->AddViewField('description', $rowData['description']);
47 | $row->AddActions(array(
48 | array(
49 | "ICON" => "view",
50 | "TEXT" => $localization->message('message.view'),
51 | "ACTION" => $lAdmin->ActionRedirect("ws_migrations.php?q=detail&label=".$rowData['label'].'&type=new'. '&lang=' . LANGUAGE_ID),
52 | "DEFAULT" => true
53 | )
54 | ));
55 | }
56 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php");
57 |
58 | $lAdmin->CheckListMode();
59 | $lAdmin->DisplayList();
60 |
61 | require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin_js.php");
62 |
--------------------------------------------------------------------------------
/data/apply_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/apply_scheme.png
--------------------------------------------------------------------------------
/data/change_analyze.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/change_analyze.png
--------------------------------------------------------------------------------
/data/change_event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/change_event.png
--------------------------------------------------------------------------------
/data/classes_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/classes_scheme.png
--------------------------------------------------------------------------------
/data/cli_apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/cli_apply.png
--------------------------------------------------------------------------------
/data/cli_help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/cli_help.png
--------------------------------------------------------------------------------
/data/cli_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/cli_list.png
--------------------------------------------------------------------------------
/data/cli_rollback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/cli_rollback.png
--------------------------------------------------------------------------------
/data/create_dump.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/create_dump.png
--------------------------------------------------------------------------------
/data/create_scenario.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/create_scenario.png
--------------------------------------------------------------------------------
/data/create_scenario_was_success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/create_scenario_was_success.png
--------------------------------------------------------------------------------
/data/development_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/development_scheme.png
--------------------------------------------------------------------------------
/data/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/export.png
--------------------------------------------------------------------------------
/data/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/import.png
--------------------------------------------------------------------------------
/data/init_module_params.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/init_module_params.png
--------------------------------------------------------------------------------
/data/item_changes_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/item_changes_list.png
--------------------------------------------------------------------------------
/data/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/main.png
--------------------------------------------------------------------------------
/data/main_with_scenario.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/data/main_with_scenario.png
--------------------------------------------------------------------------------
/data/scenarioTemplate.tpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/install/db/install.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `ws_migrations_apply_changes_log` (
2 | `ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
3 | `SETUP_LOG_ID` INT (11),
4 | `GROUP_LABEL` VARCHAR (128),
5 | `SOURCE` VARCHAR(50),
6 | `DATE` DATETIME NOT NULL,
7 | `PROCESS` VARCHAR (128) NOT NULL,
8 | `SUBJECT` VARCHAR (128) DEFAULT NULL,
9 | `UPDATE_DATA` MEDIUMTEXT NOT NULL,
10 | `ORIGINAL_DATA` MEDIUMTEXT DEFAULT NULL,
11 | `SUCCESS` INT (1),
12 | `DESCRIPTION` TEXT NOT NULL
13 | );
14 | CREATE TABLE IF NOT EXISTS `ws_migrations_setups_log` (
15 | `ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
16 | `USER_ID` INT,
17 | `DATE` DATETIME NOT NULL
18 | );
19 |
20 | CREATE TABLE IF NOT EXISTS `ws_migrations_db_version_references` (
21 | `ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
22 | `REFERENCE` VARCHAR (40),
23 | `DB_VERSION` VARCHAR(64),
24 | `GROUP` VARCHAR (64),
25 | `ITEM_ID` VARCHAR (32)
26 | );
27 |
--------------------------------------------------------------------------------
/install/db/uninstall.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE if exists ws_migrations_apply_changes_log;
2 | DROP TABLE if exists ws_migrations_setups_log;
3 | DROP TABLE if exists ws_migrations_db_version_references;
--------------------------------------------------------------------------------
/install/form.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/install/form.php
--------------------------------------------------------------------------------
/install/tools/ws_migrations.php:
--------------------------------------------------------------------------------
1 | "1.6.3",
4 | "VERSION_DATE" => "2016-05-10 11:00:00"
5 | );
6 | ?>
7 |
--------------------------------------------------------------------------------
/lang/en/admin.php:
--------------------------------------------------------------------------------
1 | array(
4 | 'title' => 'Migrations management',
5 | 'list' => array(
6 | 'auto' => 'New auto migrations',
7 | 'scenarios' => 'New scenarios'
8 | ),
9 | 'version' => 'The current version of the database',
10 | 'change_link' => 'change version',
11 | 'errorList' => 'Unsuccessful applied migrations',
12 | 'appliedList' => 'Successful applied migrations',
13 | 'btnRollback' => 'Undo last change',
14 | 'btnApply' => 'Apply',
15 | 'lastSetup' => array(
16 | 'sectionName' => 'Last update :time: - :user:'
17 | ),
18 | 'common' => array(
19 | 'listEmpty' => 'List is empty',
20 | 'reference-fix' => 'References synchronizing',
21 | 'pageEmpty' => 'Data for update don`t exists yet'
22 | ),
23 | 'newChangesDetail' => 'Changes list',
24 | 'newChangesTitle' => 'New changes',
25 | 'errorWindow' => 'Error info',
26 | 'diagnostic' => 'Errors diagnosis, the use of the migration is possible only after the correction',
27 | 'platformVersion' => array(
28 | 'ok' => 'Platform version',
29 | 'error' => 'Incorrect platform version'
30 | )
31 | ),
32 | 'changeversion' => array(
33 | 'pageTitle' => 'Platform versions',
34 | 'title' => 'Current platform version',
35 | 'version' => 'HASH',
36 | 'setup' => 'setup',
37 | 'owner' => 'Signature',
38 | 'button_change' => 'Change HASH',
39 | 'description' => "Each project area has a unique identifier (HASH) to synchronize data.",
40 | 'dialog' => array(
41 | 'title' => 'Set the name of the project owner\'s version'
42 | ),
43 | 'otherVersions' => array(
44 | 'tab' => 'Other versions of the project'
45 | )
46 | ),
47 | 'newChangesList' => array(
48 | 'fields' => array(
49 | 'date' => 'Date create',
50 | 'description' => 'Description',
51 | 'source' => 'Source',
52 | ),
53 | 'message' => array(
54 | "ago" => 'back',
55 | 'view' => 'detail'
56 | )
57 | ),
58 | 'applyError' => array(
59 | 'message' => 'Message',
60 | 'data' => 'Data',
61 | 'trace' => 'Call stack',
62 | 'error' => array(
63 | 'modelNotExists' => 'Data for record id =: id: does not exist'
64 | )
65 | ),
66 | 'entitiesVersions' => array(
67 | 'title' => 'References list',
68 | 'fields' => array(
69 | 'reference' => 'HASH',
70 | 'versions' => 'Other versions Ids',
71 | 'destination' => 'Reference'
72 | ),
73 | 'messages' => array(
74 | 'pages' => 'Pages'
75 | ),
76 | 'subjects' => array(
77 | 'iblock' => 'Information block',
78 | 'iblockProperty' => 'Information block property',
79 | 'iblockSection' => 'Information block section',
80 | )
81 | ),
82 | 'createScenario' => array(
83 | 'title' => 'The script scenario',
84 | 'field' => array(
85 | 'name' => 'Title',
86 | 'description' => 'Description'
87 | ),
88 | 'path-to-file' => 'Class file migration is #path#',
89 | 'save-file-error' => 'An error occured save file',
90 | 'button' => array(
91 | 'create' => 'Create migration scenario'
92 | )
93 | ),
94 | 'diagnostic' => array(
95 | 'title' => 'Platform diagnostic',
96 | 'description' => 'Diagnostics status, problem-solving tips',
97 | 'last' => array(
98 | 'description' => 'Description',
99 | 'result' => 'Result',
100 | 'success' => 'Success',
101 | 'fail' => 'Fail'
102 | ),
103 | 'run' => 'Run diagnostic',
104 | ),
105 | 'log' => array(
106 | 'title' => 'Updates log',
107 | 'fields' => array(
108 | 'updateDate' => 'Date',
109 | 'description' => 'Update features',
110 | 'source' => 'Source',
111 | 'dispatcher' => 'Update by'
112 | ),
113 | 'messages' => array(
114 | 'InsertReference' => 'Insert other reference',
115 | 'view' => 'Analysis of changes',
116 | 'pages' => 'Pages',
117 | 'actualization' => 'Actualization sources',
118 | 'descriptionMoreLink' => 'detail',
119 | 'errorWindow' => 'Error information'
120 | )
121 | ),
122 | 'detail' => array(
123 | 'title' => '#date. #source. Update by - #deployer',
124 | 'tabs' => array(
125 | 'diff' => 'Features',
126 | 'final' => 'Update result',
127 | 'merge' => 'Data before update'
128 | ),
129 | 'message' => array(
130 | 'nobody' => 'The site is not updated',
131 | 'show' => 'show data',
132 | 'hide' => 'hide data',
133 | ),
134 | 'serviceLabels' => array(
135 | '~reference' => 'HASH',
136 | '~property_list_values' => 'VALUES',
137 | 'Reference fix' => 'Register links with the essence of the platform',
138 | 'Insert reference' => 'The new entity reference',
139 | 'reference' => 'HASH',
140 | 'group' => 'Group entity ( the handler )',
141 | 'dbVersion' => 'Platform version'
142 | )
143 | ),
144 | 'cli' => array(
145 | 'common' => array(
146 | 'reference-fix' => 'References synchronizing'
147 | ),
148 | ),
149 | );
--------------------------------------------------------------------------------
/lang/en/handlers.php:
--------------------------------------------------------------------------------
1 | array(
4 | 'name' => 'Information block'
5 | ),
6 | 'iblockProperty' => array(
7 | 'name' => 'The property information block',
8 | 'errors' => array(
9 | 'iblockNotExists' => 'Information block with id `:id:` does not exist'
10 | )
11 | ),
12 | 'iblockSection' => array(
13 | 'name' => 'Section information block'
14 | )
15 | );
--------------------------------------------------------------------------------
/lang/en/info.php:
--------------------------------------------------------------------------------
1 | 'Data migrations',
4 | 'description' => 'Allows you to synchronize data from different copies of site',
5 | 'partner' => array(
6 | 'name' => 'WorkSolutions',
7 | 'url' => 'http://www.worksolutions.ru'
8 | )
9 | );
--------------------------------------------------------------------------------
/lang/en/menu.php:
--------------------------------------------------------------------------------
1 | 'Data migrations',
4 | 'changeversion' => 'Platform versions',
5 | 'apply' => 'Update',
6 | 'automigrations' => 'Auto migrations',
7 | 'log' => 'Log',
8 | 'entitiesVersions' => 'References',
9 | 'createScenario' => 'Scenario',
10 | 'diagnostic' => 'Diagnostic'
11 | );
--------------------------------------------------------------------------------
/lang/en/processes.php:
--------------------------------------------------------------------------------
1 | 'Addition',
4 | 'update' => 'Update',
5 | 'delete' => 'Remove'
6 | );
--------------------------------------------------------------------------------
/lang/en/setup.php:
--------------------------------------------------------------------------------
1 | 'Installing the Data migrations module',
4 | 'tab' => 'Settings',
5 | 'description' => 'You must specify the directory location of the migration file. relative to the root directory of the project. ($ SERVER [\'DOCUMENT_ROOT\']) ',
6 | 'fields' => array(
7 | 'catalog' => 'Directory path',
8 | 'useAutotests' => 'Use auto-tests (for developers)',
9 | 'apply' => 'Set Up'
10 | ),
11 | 'errors' => array(
12 | 'notCreateDir' => 'Unable to create directory',
13 | 'catalogFieldEmpty' => 'Catalog field is empty'
14 | ),
15 | 'section' => array(
16 | 'disableHandlers' => 'Use synchronization'
17 | )
18 | );
--------------------------------------------------------------------------------
/lang/en/uninstall.php:
--------------------------------------------------------------------------------
1 | 'Deleting data migration module',
4 | 'tab' => 'Delete options',
5 | 'description' => "When you delete data , the project will not be able to work with the current migrations.\n"
6 | ."You will need to initialize the mechanism of migration once again , starting with the current version .\n"
7 | ."Information to remove : tables migration , customization , migration catalog (if used versioning system"
8 | ."should register changes )",
9 | 'fields' => array(
10 | 'removeAll' => 'Erase migration data'
11 | )
12 | );
--------------------------------------------------------------------------------
/lang/ru/admin.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/admin.php
--------------------------------------------------------------------------------
/lang/ru/handlers.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/handlers.php
--------------------------------------------------------------------------------
/lang/ru/info.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/info.php
--------------------------------------------------------------------------------
/lang/ru/menu.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/menu.php
--------------------------------------------------------------------------------
/lang/ru/processes.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/processes.php
--------------------------------------------------------------------------------
/lang/ru/setup.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/setup.php
--------------------------------------------------------------------------------
/lang/ru/uninstall.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lang/ru/uninstall.php
--------------------------------------------------------------------------------
/lib/applyresult.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations;
7 |
8 |
9 | class ApplyResult {
10 | private $_success;
11 | private $_message;
12 | private $_id;
13 |
14 | /**
15 | * @param string $value
16 | * @return $this
17 | */
18 | public function setMessage($value) {
19 | $this->_message = $value;
20 | return $this;
21 | }
22 |
23 | /**
24 | * @return string
25 | */
26 | public function getMessage() {
27 | return $this->_message;
28 | }
29 |
30 | /**
31 | * @return boolean
32 | */
33 | public function isSuccess() {
34 | return $this->_success;
35 | }
36 |
37 | /**
38 | * @param boolean $value
39 | * @return $this
40 | */
41 | public function setSuccess($value) {
42 | $this->_success = $value;
43 | return $this;
44 | }
45 |
46 | /**
47 | * @return mixed
48 | */
49 | public function getId() {
50 | return $this->_id;
51 | }
52 |
53 | /**
54 | * @param mixed $id
55 | * @return $this
56 | */
57 | public function setId($id) {
58 | $this->_id = $id;
59 | return $this;
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/lib/builder/agentbuilder.php:
--------------------------------------------------------------------------------
1 | agent = null;
15 | }
16 |
17 | /**
18 | * @param $callback
19 | * @return Agent
20 | * @throws BuilderException
21 | */
22 | public function addAgent($callback) {
23 | if ($this->agent) {
24 | throw new BuilderException('reset builder data for continue');
25 | }
26 | $this->agent = new Agent($callback);
27 | return $this->agent;
28 | }
29 |
30 | /**
31 | * @param $callback
32 | * @return Agent
33 | * @throws BuilderException
34 | */
35 | public function getAgent($callback) {
36 | if ($this->agent) {
37 | throw new BuilderException('reset builder data for continue');
38 | }
39 | $data = $this->findAgent($callback);
40 | $this->agent = new Agent($callback, $data);
41 | return $this->agent;
42 | }
43 |
44 | /**
45 | * @throws BuilderException
46 | */
47 | public function commit() {
48 | global $DB, $APPLICATION;
49 | $DB->StartTransaction();
50 | try {
51 | $agent = $this->agent;
52 | if ($agent->getId() > 0) {
53 | $res = \CAgent::Update($agent->getId(), $agent->getSaveData());
54 | if (!$res) {
55 | throw new BuilderException("Agent wasn't updated");
56 | }
57 | } else {
58 | $res = \CAgent::AddAgent(
59 | $agent->callback,
60 | $agent->module,
61 | $agent->isPeriod,
62 | $agent->interval,
63 | '',
64 | $agent->active,
65 | $agent->nextExec,
66 | $agent->sort,
67 | $agent->userId
68 | );
69 | if (!$res) {
70 | throw new BuilderException("Agent wasn't created: " . $APPLICATION->GetException()->GetString());
71 | }
72 | $agent->setId($res);
73 | }
74 |
75 | } catch (BuilderException $e) {
76 | $DB->Rollback();
77 | throw new BuilderException($e->getMessage());
78 | }
79 | $DB->Commit();
80 | }
81 |
82 | /**
83 | * @return Agent
84 | */
85 | public function getCurrentAgent() {
86 | return $this->agent;
87 | }
88 |
89 | /**
90 | * @param $callback
91 | * @return array
92 | * @throws BuilderException
93 | */
94 | private function findAgent($callback) {
95 | $agent = \CAgent::GetList(null, array(
96 | 'NAME' => $callback,
97 | ))->Fetch();
98 | if (empty($agent)) {
99 | throw new BuilderException("Agent {$callback} not found");
100 | }
101 | return $agent;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/lib/builder/builderexception.php:
--------------------------------------------------------------------------------
1 | callback = $callback;
23 | $this->setDefault();
24 | $this->setSaveData($data);
25 | }
26 |
27 | public function getMap() {
28 | return array(
29 | 'id' => 'ID',
30 | 'sort' => 'SORT',
31 | 'active' => 'ACTIVE',
32 | 'module' => 'MODULE_ID',
33 | 'callback' => 'NAME',
34 | 'userId' => 'USER_ID',
35 | 'isPeriod' => 'IS_PERIOD',
36 | 'interval' => 'AGENT_INTERVAL',
37 | 'nextExec' => 'NEXT_EXEC',
38 | );
39 | }
40 |
41 | /**
42 | * @param int $id
43 | * @return Agent
44 | */
45 | public function setId($id) {
46 | $this->id = $id;
47 | return $this;
48 | }
49 |
50 | /**
51 | * @param int $sort
52 | * @return Agent
53 | */
54 | public function setSort($sort) {
55 | $this->sort = $sort;
56 | return $this;
57 | }
58 |
59 | /**
60 | * @return int
61 | */
62 | public function getId() {
63 | return $this->id;
64 | }
65 |
66 | private function setDefault() {
67 | $this
68 | ->setSort(100)
69 | ->setActive(true)
70 | ->setInterval(86400)
71 | ->setIsPeriod(false)
72 | ->setNextExec(new DateTime());
73 | }
74 |
75 | /**
76 | * @param int $userId
77 | * @return Agent
78 | */
79 | public function setUserId($userId) {
80 | $this->userId = $userId;
81 | return $this;
82 | }
83 |
84 | /**
85 | * @param int $interval
86 | * @return Agent
87 | */
88 | public function setInterval($interval) {
89 | $this->interval = $interval;
90 | return $this;
91 | }
92 |
93 | /**
94 | * @param bool $active
95 | * @return Agent
96 | */
97 | public function setActive($active) {
98 | $this->active = $active ? 'Y' : 'N';
99 | return $this;
100 | }
101 |
102 | /**
103 | * @param string $module
104 | * @return Agent
105 | */
106 | public function setModule($module) {
107 | $this->module = $module;
108 | return $this;
109 | }
110 |
111 | /**
112 | * @param string $callback
113 | * @return Agent
114 | */
115 | public function setCallback($callback) {
116 | $this->callback = $callback;
117 | return $this;
118 | }
119 |
120 | /**
121 | * @param bool $isPeriod
122 | * @return Agent
123 | */
124 | public function setIsPeriod($isPeriod) {
125 | $this->isPeriod = $isPeriod ? 'Y' : 'N';
126 | return $this;
127 | }
128 |
129 | /**
130 | * @param DateTime $nextExec
131 | * @return Agent
132 | */
133 | public function setNextExec($nextExec) {
134 | $this->nextExec = $nextExec->format('d.m.Y H:i:s');
135 | return $this;
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/lib/builder/entity/base.php:
--------------------------------------------------------------------------------
1 | data[$prop];
12 | }
13 |
14 | public function __set($prop, $value) {
15 | $this->data[$prop] = $value;
16 | return $value;
17 | }
18 |
19 | public function getSaveData() {
20 | $map = $this->getMap();
21 | $fields = array();
22 | foreach ($this->data as $key => $value) {
23 | if (!isset($map[$key])) {
24 | $fields[$key] = $value;
25 | continue;
26 | }
27 | $fields[$map[$key]] = $value;
28 | }
29 | return $fields;
30 | }
31 |
32 | public function setSaveData($data) {
33 | $map = array_flip($this->getMap());
34 | foreach ($data as $key => $val) {
35 | if (!isset($map[$key])) {
36 | $this->{$key} = $val;
37 | continue;
38 | }
39 | $this->{$map[$key]} = $val;
40 | }
41 | }
42 |
43 | /**
44 | * @return array
45 | */
46 | public abstract function getMap();
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/lib/builder/entity/enumvariant.php:
--------------------------------------------------------------------------------
1 | value = $value;
19 | $this->setSaveData($data);
20 | }
21 |
22 | public function getMap() {
23 | return array(
24 | 'id' => 'ID',
25 | 'value' => 'VALUE',
26 | 'xmlId' => 'XML_ID',
27 | 'sort' => 'SORT',
28 | 'default' => 'DEF',
29 | 'del' => 'DEL',
30 | );
31 | }
32 |
33 | /**
34 | * @param int $id
35 | * @return IblockType
36 | */
37 | public function setId($id) {
38 | $this->id = $id;
39 | return $this;
40 | }
41 |
42 | /**
43 | * @return int
44 | */
45 | public function getId() {
46 | return $this->id;
47 | }
48 |
49 | /**
50 | * @param string $value
51 | * @return EnumVariant
52 | */
53 | public function setValue($value) {
54 | $this->value = $value;
55 | return $this;
56 | }
57 |
58 | /**
59 | * @param string $xmlId
60 | * @return EnumVariant
61 | */
62 | public function setXmlId($xmlId) {
63 | $this->xmlId = $xmlId;
64 | return $this;
65 | }
66 |
67 | /**
68 | * @param int $sort
69 | * @return EnumVariant
70 | */
71 | public function setSort($sort) {
72 | $this->sort = $sort;
73 | return $this;
74 | }
75 |
76 | /**
77 | * @param bool $default
78 | * @return EnumVariant
79 | */
80 | public function setDefault($default) {
81 | $this->default = $default ? 'Y' : 'N';
82 | return $this;
83 | }
84 | }
--------------------------------------------------------------------------------
/lib/builder/entity/eventmessage.php:
--------------------------------------------------------------------------------
1 | setEmailFrom($from)
27 | ->setEmailTo($to)
28 | ->setSiteId($siteId);
29 |
30 | $this->setSaveData($data);
31 | $this->dateUpdate = new DateTime();
32 | }
33 |
34 | public function getMap() {
35 | return array(
36 | 'id' => 'ID',
37 | 'siteId' => 'LID',
38 | 'active' => 'ACTIVE',
39 | 'emailFrom' => 'EMAIL_FROM',
40 | 'emailTo' => 'EMAIL_TO',
41 | 'subject' => 'SUBJECT',
42 | 'message' => 'MESSAGE',
43 | 'bodyType' => 'BODY_TYPE',
44 | 'bcc' => 'BCC',
45 | 'dateUpdate' => 'TIMESTAMP_X',
46 | );
47 | }
48 |
49 | /**
50 | * @param int $id
51 | * @return EventMessage
52 | */
53 | public function setId($id) {
54 | $this->id = $id;
55 | return $this;
56 | }
57 |
58 | /**
59 | * @return int
60 | */
61 | public function getId() {
62 | return $this->id;
63 | }
64 |
65 | /**
66 | * @param string $siteId
67 | * @return EventMessage
68 | */
69 | public function setSiteId($siteId) {
70 | $this->siteId = $siteId;
71 | return $this;
72 | }
73 |
74 | /**
75 | * @param bool $active
76 | * @return EventMessage
77 | */
78 | public function setActive($active) {
79 | $this->active = $active ? 'Y' : 'N';
80 | return $this;
81 | }
82 |
83 | /**
84 | * @param string $emailFrom
85 | * @return EventMessage
86 | */
87 | public function setEmailFrom($emailFrom) {
88 | $this->emailFrom = $emailFrom;
89 | return $this;
90 | }
91 |
92 | /**
93 | * @param string $emailTo
94 | * @return EventMessage
95 | */
96 | public function setEmailTo($emailTo) {
97 | $this->emailTo = $emailTo;
98 | return $this;
99 | }
100 |
101 | /**
102 | * @param string $subject
103 | * @return EventMessage
104 | */
105 | public function setSubject($subject) {
106 | $this->subject = $subject;
107 | return $this;
108 | }
109 |
110 | /**
111 | * @param string $message
112 | * @return EventMessage
113 | */
114 | public function setMessage($message) {
115 | $this->message = $message;
116 | return $this;
117 | }
118 |
119 | /**
120 | * @param string $bodyType
121 | * @return EventMessage
122 | */
123 | public function setBodyType($bodyType) {
124 | $this->bodyType = $bodyType;
125 | return $this;
126 | }
127 |
128 | /**
129 | * @param string $bcc
130 | * @return EventMessage
131 | */
132 | public function setBcc($bcc) {
133 | $this->bcc = $bcc;
134 | return $this;
135 | }
136 |
137 | public function remove() {
138 | $this->forRemove = true;
139 | }
140 |
141 | public function isRemoved() {
142 | return $this->forRemove;
143 | }
144 |
145 | }
--------------------------------------------------------------------------------
/lib/builder/entity/eventtype.php:
--------------------------------------------------------------------------------
1 | eventName = $eventName;
19 | $this->lid = $lid;
20 | $this->setSaveData($data);
21 | }
22 |
23 | public function getMap() {
24 | return array(
25 | 'id' => 'ID',
26 | 'sort' => 'SORT',
27 | 'eventName' => 'EVENT_NAME',
28 | 'lid' => 'LID',
29 | 'name' => 'NAME',
30 | 'description' => 'DESCRIPTION',
31 | );
32 | }
33 |
34 | /**
35 | * @param int $id
36 | * @return EventType
37 | */
38 | public function setId($id) {
39 | $this->id = $id;
40 | return $this;
41 | }
42 |
43 | /**
44 | * @return int
45 | */
46 | public function getId() {
47 | return $this->id;
48 | }
49 |
50 | /**
51 | * @param int $sort
52 | * @return EventType
53 | */
54 | public function setSort($sort) {
55 | $this->sort = $sort;
56 | return $this;
57 | }
58 |
59 | /**
60 | * @param string $eventName
61 | * @return EventType
62 | */
63 | public function setEventName($eventName) {
64 | $this->eventName = $eventName;
65 | return $this;
66 | }
67 |
68 | /**
69 | * @param string $lid
70 | * @return EventType
71 | */
72 | public function setLid($lid) {
73 | $this->lid = $lid;
74 | return $this;
75 | }
76 |
77 | /**
78 | * @param string $name
79 | * @return EventType
80 | */
81 | public function setName($name) {
82 | $this->name = $name;
83 | return $this;
84 | }
85 |
86 | /**
87 | * @param string $description
88 | * @return EventType
89 | */
90 | public function setDescription($description) {
91 | $this->description = $description;
92 | return $this;
93 | }
94 |
95 | }
--------------------------------------------------------------------------------
/lib/builder/entity/formanswer.php:
--------------------------------------------------------------------------------
1 | message = $message;
32 | $this->setSaveData($data);
33 | }
34 |
35 | public function getMap() {
36 | return array(
37 | 'id' => 'ID',
38 | 'sort' => 'C_SORT',
39 | 'message' => 'MESSAGE',
40 | 'value' => 'VALUE',
41 | 'active' => 'ACTIVE',
42 | 'fieldType' => 'FIELD_TYPE',
43 | 'fieldWidth' => 'FIELD_WIDTH',
44 | 'fieldHeight' => 'FIELD_HEIGHT',
45 | 'fieldParam' => 'FIELD_PARAM',
46 | 'del' => 'DEL',
47 | );
48 | }
49 |
50 | /**
51 | * @param int $id
52 | * @return FormAnswer
53 | */
54 | public function setId($id) {
55 | $this->id = $id;
56 | return $this;
57 | }
58 |
59 | /**
60 | * @return int
61 | */
62 | public function getId() {
63 | return $this->id;
64 | }
65 |
66 | /**
67 | * @param int $sort
68 | * @return FormAnswer
69 | */
70 | public function setSort($sort) {
71 | $this->sort = $sort;
72 | return $this;
73 | }
74 |
75 | /**
76 | * @param bool $active
77 | * @return FormAnswer
78 | */
79 | public function setActive($active) {
80 | $this->active = $active ? 'Y' : 'N';
81 | return $this;
82 | }
83 |
84 | /**
85 | * @param string $message
86 | * @return FormAnswer
87 | */
88 | public function setMessage($message) {
89 | $this->message = $message;
90 | return $this;
91 | }
92 |
93 | /**
94 | * @param string $value
95 | * @return FormAnswer
96 | */
97 | public function setValue($value) {
98 | $this->value = $value;
99 | return $this;
100 | }
101 |
102 | /**
103 | * @param string $fieldType
104 | * @return FormAnswer
105 | */
106 | public function setFieldType($fieldType) {
107 | $this->fieldType = $fieldType;
108 | return $this;
109 | }
110 |
111 | /**
112 | * @param string $fieldWidth
113 | * @return FormAnswer
114 | */
115 | public function setFieldWidth($fieldWidth) {
116 | $this->fieldWidth = $fieldWidth;
117 | return $this;
118 | }
119 |
120 | /**
121 | * @param string $fieldHeight
122 | * @return FormAnswer
123 | */
124 | public function setFieldHeight($fieldHeight) {
125 | $this->fieldHeight = $fieldHeight;
126 | return $this;
127 | }
128 |
129 | /**
130 | * @param string $fieldParam
131 | * @return FormAnswer
132 | */
133 | public function setFieldParam($fieldParam) {
134 | $this->fieldParam = $fieldParam;
135 | return $this;
136 | }
137 |
138 | public function needDelete() {
139 | return $this->del == 'Y';
140 | }
141 |
142 |
143 | }
--------------------------------------------------------------------------------
/lib/builder/entity/formstatus.php:
--------------------------------------------------------------------------------
1 | title = $title;
27 | $this->setSaveData($data);
28 | $this->dateUpdate = new DateTime();
29 | }
30 |
31 | public function getMap() {
32 | return array(
33 | 'id' => 'ID',
34 | 'sort' => 'C_SORT',
35 | 'dateUpdate' => 'TIMESTAMP_X',
36 | 'active' => 'ACTIVE',
37 | 'title' => 'TITLE',
38 | 'description' => 'DESCRIPTION',
39 | 'isDefault' => 'DEFAULT_VALUE',
40 | 'css' => 'CSS',
41 | 'handlerOut' => 'HANDLER_OUT',
42 | 'handlerIn' => 'HANDLER_IN',
43 | 'arGroupCanView' => 'arPERMISSION_VIEW',
44 | 'arGroupCanMove' => 'arPERMISSION_MOVE',
45 | 'arGroupCanEdit' => 'arPERMISSION_EDIT',
46 | 'arGroupCanDelete' => 'arPERMISSION_DELETE',
47 | );
48 | }
49 |
50 | /**
51 | * @param int $id
52 | * @return FormStatus
53 | */
54 | public function setId($id) {
55 | $this->id = $id;
56 | return $this;
57 | }
58 |
59 | /**
60 | * @return int
61 | */
62 | public function getId() {
63 | return $this->id;
64 | }
65 |
66 | /**
67 | * @param int $sort
68 | * @return FormStatus
69 | */
70 | public function setSort($sort) {
71 | $this->sort = $sort;
72 | return $this;
73 | }
74 |
75 | /**
76 | * @param bool $active
77 | * @return FormStatus
78 | */
79 | public function setActive($active) {
80 | $this->active = $active ? 'Y' : 'N';
81 | return $this;
82 | }
83 |
84 | /**
85 | * @param string $title
86 | * @return FormStatus
87 | */
88 | public function setTitle($title) {
89 | $this->title = $title;
90 | return $this;
91 | }
92 |
93 | /**
94 | * @param string $description
95 | * @return FormStatus
96 | */
97 | public function setDescription($description) {
98 | $this->description = $description;
99 | return $this;
100 | }
101 |
102 | /**
103 | * @param bool $isDefault
104 | * @return FormStatus
105 | */
106 | public function setIsDefault($isDefault) {
107 | $this->isDefault = $isDefault ? 'Y' : 'N';
108 | return $this;
109 | }
110 |
111 | /**
112 | * @param string $css
113 | * @return FormStatus
114 | */
115 | public function setCss($css) {
116 | $this->css = $css;
117 | return $this;
118 | }
119 |
120 | /**
121 | * @param string $handlerOut
122 | * @return FormStatus
123 | */
124 | public function setHandlerOut($handlerOut) {
125 | $this->handlerOut = $handlerOut;
126 | return $this;
127 | }
128 |
129 | /**
130 | * @param string $handlerIn
131 | * @return FormStatus
132 | */
133 | public function setHandlerIn($handlerIn) {
134 | $this->handlerIn = $handlerIn;
135 | return $this;
136 | }
137 |
138 | /**
139 | * @param array $arGroupCanView
140 | * @return FormStatus
141 | */
142 | public function setArGroupCanView($arGroupCanView) {
143 | $this->arGroupCanView = $arGroupCanView;
144 | return $this;
145 | }
146 |
147 | /**
148 | * @param array $arGroupCanMove
149 | * @return FormStatus
150 | */
151 | public function setArGroupCanMove($arGroupCanMove) {
152 | $this->arGroupCanMove = $arGroupCanMove;
153 | return $this;
154 | }
155 |
156 | /**
157 | * @param array $arGroupCanEdit
158 | * @return FormStatus
159 | */
160 | public function setArGroupCanEdit($arGroupCanEdit) {
161 | $this->arGroupCanEdit = $arGroupCanEdit;
162 | return $this;
163 | }
164 |
165 | /**
166 | * @param array $arGroupCanDelete
167 | * @return FormStatus
168 | */
169 | public function setArGroupCanDelete($arGroupCanDelete) {
170 | $this->arGroupCanDelete = $arGroupCanDelete;
171 | return $this;
172 | }
173 |
174 | }
--------------------------------------------------------------------------------
/lib/builder/entity/highloadblock.php:
--------------------------------------------------------------------------------
1 | name = $name;
16 | $this->tableName = $tableName;
17 | $this->id = $id;
18 | }
19 |
20 | public function getMap() {
21 | return array(
22 | 'id' => 'ID',
23 | 'name' => 'NAME',
24 | 'tableName' => 'TABLE_NAME',
25 | );
26 | }
27 |
28 | /**
29 | * @param int $id
30 | * @return IblockType
31 | */
32 | public function setId($id) {
33 | $this->id = $id;
34 | return $this;
35 | }
36 |
37 | /**
38 | * @return int
39 | */
40 | public function getId() {
41 | return $this->id;
42 | }
43 |
44 | /**
45 | * @param string $name
46 | * @return HighLoadBlock
47 | */
48 | public function setName($name) {
49 | $this->name = $name;
50 | return $this;
51 | }
52 |
53 | /**
54 | * @param string $tableName
55 | * @return HighLoadBlock
56 | */
57 | public function setTableName($tableName) {
58 | $this->tableName = $tableName;
59 | return $this;
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/lib/builder/entity/iblocksection.php:
--------------------------------------------------------------------------------
1 | name = $name;
30 | $this->childs = array();
31 | $this->setSaveData($data);
32 | }
33 |
34 | public function getMap() {
35 | return array(
36 | 'id' => 'ID',
37 | 'iblockId' => 'IBLOCK_ID',
38 | 'code' => 'CODE',
39 | 'xmlId' => 'XML_ID',
40 | 'sort' => 'SORT',
41 | 'name' => 'NAME',
42 | 'active' => 'ACTIVE',
43 | 'picture' => 'PICTURE',
44 | 'description' => 'DESCRIPTION',
45 | 'descriptionType' => 'DESCRIPTION_TYPE',
46 | 'detailPicture' => 'DETAIL_PICTURE',
47 | );
48 | }
49 |
50 | /**
51 | * @param int $id
52 | * @return EventType
53 | */
54 | public function setId($id) {
55 | $this->id = $id;
56 | return $this;
57 | }
58 |
59 | /**
60 | * @return int
61 | */
62 | public function getId() {
63 | return $this->id;
64 | }
65 |
66 | /**
67 | * @param int $sort
68 | * @return EventType
69 | */
70 | public function setSort($sort) {
71 | $this->sort = $sort;
72 | return $this;
73 | }
74 |
75 | /**
76 | * @param string $eventName
77 | * @return EventType
78 | */
79 | public function setEventName($eventName) {
80 | $this->eventName = $eventName;
81 | return $this;
82 | }
83 |
84 | /**
85 | * @param string $lid
86 | * @return EventType
87 | */
88 | public function setLid($lid) {
89 | $this->lid = $lid;
90 | return $this;
91 | }
92 |
93 | /**
94 | * @param string $name
95 | * @return EventType
96 | */
97 | public function setName($name) {
98 | $this->name = $name;
99 | return $this;
100 | }
101 |
102 | /**
103 | * @param string $description
104 | * @return EventType
105 | */
106 | public function setDescription($description) {
107 | $this->description = $description;
108 | return $this;
109 | }
110 |
111 | /**
112 | * @param $name
113 | * @return IblockSection
114 | */
115 | public function getChild($name) {
116 | return $this->findChild($name);
117 | }
118 |
119 | /**
120 | * @param $name
121 | * @param bool $data
122 | * @return IblockSection
123 | */
124 | public function addChild($name, $data = false) {
125 | $child = new IblockSection($name, $data);
126 | $this->children[] = $child;
127 | return $child;
128 | }
129 |
130 | private function findChild($name) {
131 | foreach ($this->children as $child) {
132 | if ($child->name != $name) {
133 | continue;
134 | }
135 | return $child;
136 | }
137 | $child = $this->getChildFromDB($name);
138 | $this->children[] = $child;
139 | return $child;
140 | }
141 | /**
142 | * @return IblockSection[]
143 | */
144 | public function getChildren() {
145 | return $this->children;
146 | }
147 |
148 | /**
149 | * @param $name
150 | * @return IblockSection
151 | * @throws BuilderException
152 | */
153 | private function getChildFromDB($name) {
154 | if (!$this->id) {
155 | throw new BuilderException("Save section for continue");
156 | }
157 | $item = \CIBlockSection::GetList(null, array(
158 | 'IBLOCK_ID' => $this->iblockId,
159 | 'SECTION_ID' => $this->id,
160 | '=NAME' => $name
161 | ))->Fetch();
162 | if (empty($item)) {
163 | throw new BuilderException("Iblock section with name '{$name}' not found");
164 | }
165 | return new IblockSection($name, $item);
166 | }
167 | }
--------------------------------------------------------------------------------
/lib/builder/entity/iblocktype.php:
--------------------------------------------------------------------------------
1 | id = $type;
25 | $this->iblockTypeId = $data['ID'];
26 | $this->setSaveData($data);
27 | }
28 |
29 | public function getMap() {
30 | return array(
31 | 'id' => 'ID',
32 | 'sort' => 'SORT',
33 | 'sections' => 'SECTIONS',
34 | 'inRss' => 'IN_RSS',
35 | 'lang' => 'LANG',
36 | );
37 | }
38 |
39 | /**
40 | * @param int $id
41 | * @return IblockType
42 | */
43 | public function setId($id) {
44 | $this->id = $id;
45 | return $this;
46 | }
47 |
48 | /**
49 | * @param int $sort
50 | * @return IblockType
51 | */
52 | public function setSort($sort) {
53 | $this->sort = $sort;
54 | return $this;
55 | }
56 |
57 | /**
58 | * @return int
59 | */
60 | public function getId() {
61 | return $this->id;
62 | }
63 |
64 | /**
65 | * @param string $sections
66 | * @return IblockType
67 | */
68 | public function setSections($sections) {
69 | $this->sections = $sections;
70 | return $this;
71 | }
72 |
73 | /**
74 | * @param array $lang ['en' => ['NAME'=>'Catalog', 'SECTION_NAME'=>'Sections', 'ELEMENT_NAME'=>'Products']]
75 | * @return IblockType
76 | */
77 | public function setLang($lang) {
78 | $this->lang = $lang;
79 | return $this;
80 | }
81 |
82 | /**
83 | * @param bool $inRss
84 | * @return IblockType
85 | */
86 | public function setInRss($inRss) {
87 | $this->inRss = $inRss ? 'Y' : 'N';
88 | return $this;
89 | }
90 | }
--------------------------------------------------------------------------------
/lib/builder/eventsbuilder.php:
--------------------------------------------------------------------------------
1 | eventType = null;
19 | $this->newMessages = array();
20 | $this->exitsMessages = array();
21 | }
22 |
23 | /**
24 | * @param $type
25 | * @param $lid
26 | * @return EventType
27 | * @throws BuilderException
28 | */
29 | public function addEventType($type, $lid) {
30 | if ($this->eventType) {
31 | throw new BuilderException('EventType already set');
32 | }
33 | $this->eventType = new EventType($type, $lid);
34 | return $this->eventType;
35 | }
36 |
37 | /**
38 | * @param $type
39 | * @param $lid
40 | * @return EventType
41 | * @throws BuilderException
42 | */
43 | public function getEventType($type, $lid) {
44 | if ($this->eventType) {
45 | throw new BuilderException('EventType already set');
46 | }
47 | $this->eventType = new EventType($type, $lid, $this->findEventType($type, $lid));
48 | return $this->eventType;
49 | }
50 |
51 | /**
52 | * @param $from
53 | * @param $to
54 | * @param $siteId
55 | * @return EventMessage
56 | */
57 | public function addEventMessage($from, $to, $siteId) {
58 | $message = new EventMessage($from, $to, $siteId);
59 | $this->newMessages[] = $message;
60 | return $message;
61 | }
62 |
63 | /**
64 | * @return Entity\EventMessage[]
65 | * @throws BuilderException
66 | */
67 | public function getEventMessages() {
68 | foreach ($this->findMessages() as $data) {
69 | $this->exitsMessages[] = new EventMessage(false, false, false, $data);
70 | }
71 | return $this->exitsMessages;
72 | }
73 |
74 | /**
75 | * @return EventType
76 | */
77 | public function getCurrentEventType() {
78 | return $this->eventType;
79 | }
80 |
81 | /**
82 | * @throws BuilderException
83 | */
84 | public function commit() {
85 | global $DB;
86 | $DB->StartTransaction();
87 | try {
88 | $this->commitEventType();
89 | $this->commitNewEventMessages();
90 | $this->commitExistsEventMessages();
91 | } catch (\Exception $e) {
92 | $DB->Rollback();
93 | throw new BuilderException($e->getMessage());
94 | }
95 | $DB->Commit();
96 | }
97 |
98 | /**
99 | * @param $type
100 | * @param $lid
101 | * @return array
102 | * @throws BuilderException
103 | */
104 | private function findEventType($type, $lid) {
105 | $data = \CEventType::GetList(array(
106 | 'TYPE_ID' => $type,
107 | 'LID' => $lid
108 | ))->Fetch();
109 | if (empty($data)) {
110 | throw new BuilderException("EventType '{$type}' not found for lid '{$lid}'");
111 | }
112 | return $data;
113 | }
114 |
115 | /**
116 | * @throws BuilderException
117 | */
118 | private function commitEventType() {
119 | global $APPLICATION;
120 | if (!$this->eventType) {
121 | throw new BuilderException("EventType doesn't set");
122 | }
123 | $gw = new \CEventType();
124 | if ($this->eventType->getId() > 0) {
125 | $gw->Update(['ID' => $this->eventType->getId()], $this->eventType->getSaveData());
126 | } else {
127 | $res = $gw->Add($this->eventType->getSaveData());
128 | if (!$res) {
129 | throw new BuilderException('EventType add failed with error: ' . $APPLICATION->GetException()->GetString());
130 | }
131 | $this->eventType->setId($res);
132 | }
133 | }
134 |
135 | /**
136 | * @throws BuilderException
137 | */
138 | private function commitNewEventMessages() {
139 | global $APPLICATION;
140 | if (!$this->getCurrentEventType()->getId()) {
141 | throw new BuilderException("EventType doesn't set");
142 | }
143 | $gw = new \CEventMessage();
144 | foreach ($this->newMessages as $message) {
145 | $id = $gw->Add(array_merge(
146 | $message->getSaveData(),
147 | array('EVENT_NAME' => $this->getCurrentEventType()->eventName)
148 | ));
149 | if (!$id) {
150 | throw new BuilderException("EventMessage add failed with error: " . $APPLICATION->GetException()->GetString());
151 | }
152 | $message->setId($id);
153 | }
154 | }
155 |
156 | /**
157 | * @throws BuilderException
158 | */
159 | private function commitExistsEventMessages() {
160 | global $APPLICATION;
161 | if (!$this->getCurrentEventType()->getId()) {
162 | throw new BuilderException("EventType doesn't set");
163 | }
164 | $gw = new \CEventMessage();
165 | foreach ($this->exitsMessages as $message) {
166 | if (!$message->isRemoved()) {
167 | continue;
168 | }
169 | if (!$gw->Delete($message->getId())) {
170 | throw new BuilderException("EventType wasn't deleted: ". $APPLICATION->GetException()->GetString());
171 | }
172 | }
173 | foreach ($this->exitsMessages as $message) {
174 | if ($message->isRemoved()) {
175 | continue;
176 | }
177 | if (!$gw->Update($message->getId(), $message->getSaveData())) {
178 | throw new BuilderException("EventType wasn't updated: ". $APPLICATION->GetException()->GetString());
179 | }
180 | }
181 | }
182 |
183 | /**
184 | * @return array
185 | * @throws BuilderException
186 | * @throws \Bitrix\Main\ArgumentException
187 | */
188 | private function findMessages() {
189 | if (!$this->getCurrentEventType()->getId()) {
190 | throw new BuilderException("EventType doesn't set");
191 | }
192 | $res = EventMessageTable::getList(array(
193 | 'filter' => array(
194 | 'EVENT_NAME' => $this->getCurrentEventType()->eventName
195 | )
196 | ));
197 | return $res->fetchAll();
198 | }
199 |
200 |
201 | }
202 |
--------------------------------------------------------------------------------
/lib/builder/highloadblockbuilder.php:
--------------------------------------------------------------------------------
1 | highLoadBlock = null;
22 | $this->fields = array();
23 | }
24 |
25 | /**
26 | * @param $name
27 | * @param $tableName
28 | * @return HighLoadBlock
29 | * @throws BuilderException
30 | */
31 | public function addHLBlock($name, $tableName) {
32 | if ($this->highLoadBlock) {
33 | throw new BuilderException('reset builder data for continue');
34 | }
35 | $this->highLoadBlock = new HighLoadBlock($name, $tableName);
36 | return $this->highLoadBlock;
37 | }
38 |
39 | /**
40 | * @param $tableName
41 | * @return HighLoadBlock
42 | * @throws BuilderException
43 | */
44 | public function getHLBlock($tableName) {
45 | if ($this->highLoadBlock) {
46 | throw new BuilderException('reset builder data for continue');
47 | }
48 | $block = $this->findTable($tableName);
49 | $this->highLoadBlock = new HighLoadBlock($block['NAME'], $tableName, $block['ID']);
50 | return $this->highLoadBlock;
51 | }
52 |
53 | /**
54 | * @param $code
55 | * @return UserField
56 | */
57 | public function addField($code) {
58 | $field = new UserField($code);
59 | $this->fields[] = $field;
60 | return $field;
61 | }
62 |
63 | /**
64 | * @param $code
65 | * @return UserField
66 | * @throws BuilderException
67 | */
68 | public function getField($code) {
69 | $data = $this->findField($code);
70 | $field = new UserField($code, $data);
71 | $this->fields[] = $field;
72 | return $field;
73 | }
74 |
75 | /**
76 | * @throws BuilderException
77 | */
78 | public function commit() {
79 | global $DB;
80 | $DB->StartTransaction();
81 | try {
82 | $this->commitHighLoadBlock();
83 | $this->commitFields();
84 | } catch (BuilderException $e) {
85 | $DB->Rollback();
86 | throw new BuilderException($e->getMessage());
87 | }
88 | $DB->Commit();
89 | }
90 |
91 | /**
92 | * @param $tableName
93 | * @return array|false
94 | * @throws BuilderException
95 | * @throws \Bitrix\Main\ArgumentException
96 | */
97 | public function findTable($tableName) {
98 | $hbRes = HighloadBlockTable::getList(array(
99 | 'filter' => array(
100 | 'TABLE_NAME' => $tableName
101 | )
102 | ));
103 | if (!($table = $hbRes->fetch())){
104 | throw new BuilderException('Cant find block by table name `'.$tableName.'` ');
105 | }
106 | return $table;
107 | }
108 |
109 | /**
110 | * @return HighLoadBlock
111 | */
112 | public function getCurrentHighLoadBlock() {
113 | return $this->highLoadBlock;
114 | }
115 |
116 | /**
117 | * @throws BuilderException
118 | * @throws \Bitrix\Main\SystemException
119 | */
120 | private function commitHighLoadBlock() {
121 | if (!$this->highLoadBlock->getId()) {
122 | $hbRes = HighloadBlockTable::add($this->highLoadBlock->getSaveData());
123 | } else {
124 | $hbRes = HighloadBlockTable::update(
125 | $this->highLoadBlock->getId(),
126 | $this->highLoadBlock->getSaveData()
127 | );
128 | }
129 | if (!$hbRes->isSuccess()) {
130 | throw new BuilderException($this->highLoadBlock->tableName . ' ' . implode(', ', $hbRes->getErrorMessages()));
131 | }
132 | $this->highLoadBlock->setId($hbRes->getId());
133 | }
134 |
135 | /**
136 | * @throws BuilderException
137 | */
138 | private function commitFields() {
139 | global $APPLICATION;
140 | if (!$this->getCurrentHighLoadBlock()->getId()) {
141 | throw new BuilderException('Set highLoadBlock before');
142 | }
143 | $gw = new \CUserTypeEntity();
144 | foreach ($this->fields as $field) {
145 | if ($field->getId() > 0) {
146 | $res = $gw->Update($field->getId(), $field->getSaveData());
147 | } else {
148 | $res = $gw->Add(array_merge($field->getSaveData(), array(
149 | 'ENTITY_ID' => 'HLBLOCK_' . $this->getCurrentHighLoadBlock()->getId()
150 | )));
151 | if ($res) {
152 | $field->setId($res);
153 | }
154 | }
155 |
156 | if (!$res) {
157 | throw new BuilderException($APPLICATION->GetException()->GetString());
158 | }
159 |
160 | $this->commitEnum($field);
161 | }
162 | }
163 |
164 | /**
165 | * @param UserField $field
166 | * @throws BuilderException
167 | */
168 | private function commitEnum($field) {
169 | global $APPLICATION;
170 | $obEnum = new \CUserFieldEnum;
171 | $values = array();
172 | foreach ($field->getEnumVariants() as $key => $variant) {
173 | $key = 'n' . $key;
174 | if ($variant->getId() > 0) {
175 | $key = $variant->getId();
176 | }
177 | $values[$key] = $variant->getSaveData();
178 | }
179 | if (empty($values)) {
180 | return;
181 | }
182 | if (!$obEnum->SetEnumValues($field->getId(), $values)) {
183 | throw new BuilderException($APPLICATION->GetException()->GetString());
184 | }
185 | }
186 |
187 | /**
188 | * @param $code
189 | * @return array
190 | * @throws BuilderException
191 | */
192 | private function findField($code) {
193 | if (!$this->highLoadBlock) {
194 | throw new BuilderException('set higloadBlock for continue');
195 | }
196 | $field = \CUserTypeEntity::GetList(null, array(
197 | 'FIELD_NAME' => $code,
198 | 'ENTITY_ID' => "HLBLOCK_" . $this->getCurrentHighLoadBlock()->getId(),
199 | ))->Fetch();
200 |
201 | if (empty($field)) {
202 | throw new BuilderException('Field for update not found');
203 | }
204 | return $field;
205 | }
206 |
207 | }
208 |
--------------------------------------------------------------------------------
/lib/callback.php:
--------------------------------------------------------------------------------
1 | _function = $f;
31 | if (isset($args) && is_array($args)) {
32 | call_user_func_array(array($this, 'bind'), $args);
33 | }
34 | $this->_number = self::$_count ++;
35 | }
36 |
37 | public function bind() {
38 | if ( ! empty($this->_args)) {
39 | throw new \Exception("Args setup before");
40 | }
41 | $this->_args = func_get_args();
42 | }
43 |
44 | /**
45 | * Параметры для вызова
46 | *
47 | * @param mixed $param1
48 | * @param mixed $param1
49 | *
50 | * @return mixed
51 | */
52 | public function __invoke() {
53 | $args = array_merge($this->_args, func_get_args() ? : array());
54 | return call_user_func_array($this->_function, $args);
55 | }
56 |
57 | public function setCallByToString($bool) {
58 | $this->_callByToString = (bool) $bool;
59 | }
60 |
61 | public function __toString() {
62 | if ($this->_callByToString) {
63 | return $this();
64 | }
65 | return 'CallBackObject_' . $this->_number;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/lib/changedatacollector/collector.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lib/changedatacollector/collector.php
--------------------------------------------------------------------------------
/lib/changedatacollector/collectorfix.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\ChangeDataCollector;
7 |
8 |
9 | use WS\Migrations\Processes\BaseProcess;
10 | use WS\Migrations\SubjectHandlers\BaseSubjectHandler;
11 |
12 | class CollectorFix {
13 | private $_subject;
14 | private $_process;
15 | private $_data;
16 | private $_label;
17 | private $_name;
18 | private $_originalData;
19 | private $_owner;
20 |
21 | private $_isUses = false;
22 |
23 | private $_dbVersion;
24 |
25 | public function __construct($label) {
26 | $this->_label = $label;
27 | }
28 |
29 | /**
30 | * @return $this
31 | */
32 | public function take() {
33 | $this->_isUses = true;
34 | return $this;
35 | }
36 |
37 | /**
38 | * @return bool
39 | */
40 | public function isUses() {
41 | return $this->_isUses;
42 | }
43 |
44 |
45 | /**
46 | * @return BaseProcess
47 | */
48 | public function getProcess() {
49 | return $this->_process;
50 | }
51 |
52 |
53 | /**
54 | * @return BaseSubjectHandler
55 | */
56 | public function getSubject() {
57 | return $this->_subject;
58 | }
59 |
60 | /**
61 | * @return mixed
62 | */
63 | public function getUpdateData() {
64 | return $this->_data;
65 | }
66 |
67 | /**
68 | * @param mixed $subject
69 | * @return $this
70 | */
71 | public function setSubject($subject) {
72 | $this->_subject = $subject;
73 | return $this;
74 | }
75 |
76 | /**
77 | * @param mixed $process
78 | * @return $this
79 | */
80 | public function setProcess($process) {
81 | $this->_process = $process;
82 | return $this;
83 | }
84 |
85 | /**
86 | * @param mixed $data
87 | * @return $this
88 | */
89 | public function setUpdateData($data) {
90 | $this->take();
91 | $this->_data = $data;
92 | return $this;
93 | }
94 |
95 | public function setOriginalData($data) {
96 | $this->_originalData = $data;
97 | return $this;
98 | }
99 |
100 | public function getOriginalData() {
101 | return $this->_originalData;
102 | }
103 |
104 | public function getLabel() {
105 | return $this->_label;
106 | }
107 |
108 | public function setName($value) {
109 | $this->_name = $value;
110 | return $this;
111 | }
112 |
113 | public function getName() {
114 | return $this->_name;
115 | }
116 |
117 | /**
118 | * @param $value
119 | * @return $this
120 | */
121 | public function setDbVersion($value) {
122 | $this->_dbVersion = $value;
123 | return $this;
124 | }
125 |
126 | /**
127 | * @return string
128 | */
129 | public function getDbVersion() {
130 | return $this->_dbVersion ?: $this->_data['dbVersion'];
131 | }
132 |
133 | /**
134 | * @return string
135 | */
136 | public function getOwner() {
137 | return $this->_owner;
138 | }
139 |
140 | /**
141 | * @param string $owner
142 | * @return $this
143 | */
144 | public function setOwner($owner) {
145 | $this->_owner = $owner;
146 | return $this;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/lib/console/command/applycommand.php:
--------------------------------------------------------------------------------
1 | force = in_array('-f', $params);
14 | }
15 |
16 | public function execute($callback = false) {
17 | if (!$this->force) {
18 | $this->console
19 | ->printLine("Are you sure? (yes|no):");
20 | $answer = $this->console->readLine();
21 | if ($answer != 'yes') {
22 | exit();
23 | }
24 | }
25 | $diagnosticTester = $this->module
26 | ->useDiagnostic();
27 |
28 | if (!$diagnosticTester->run()) {
29 | $this->console
30 | ->printLine("Diagnostic is not valid");
31 | exit();
32 | }
33 | $this->console
34 | ->printLine("Applying new fixes started....", Console::OUTPUT_PROGRESS);
35 |
36 | $time = microtime(true);
37 |
38 | $count = (int)$this->module
39 | ->applyNewFixes($callback);
40 |
41 | $interval = round(microtime(true) - $time, 2);
42 |
43 | $this->console
44 | ->printLine("Apply action finished! $count items, time $interval sec", Console::OUTPUT_PROGRESS);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/lib/console/command/basecommand.php:
--------------------------------------------------------------------------------
1 | console = $console;
16 | $this->initParams($params);
17 | $this->module = Module::getInstance();
18 | }
19 |
20 | /**
21 | * @return string
22 | */
23 | static public function className() {
24 | return get_called_class();
25 | }
26 | protected function initParams($params) {}
27 |
28 | abstract public function execute($callback = false);
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/lib/console/command/createscenariocommand.php:
--------------------------------------------------------------------------------
1 | name = false;
22 | $this->description = false;
23 | if ($index = array_search('-n', $params)) {
24 | isset($params[$index + 1]) && !$this->isParam($params[$index + 1]) && $this->name = trim($params[$index + 1]);
25 | }
26 | if ($index = array_search('-d', $params)) {
27 | isset($params[$index + 1]) && !$this->isParam($params[$index + 1]) && $this->description = trim($params[$index + 1]);
28 | }
29 | }
30 |
31 | private function getName() {
32 | if ($this->name) {
33 | return $this->name;
34 | }
35 | $this->console
36 | ->printLine('Enter name:');
37 | $name = $this->console
38 | ->readLine();
39 | while (!strlen(trim($name))) {
40 | $this->console
41 | ->printLine("Name mustn't be empty. Enter name:");
42 | $name = $this->console
43 | ->readLine();
44 | }
45 | return $name;
46 | }
47 |
48 | private function getDescription() {
49 | if ($this->description) {
50 | return $this->description;
51 | }
52 | $this->console
53 | ->printLine('Enter description:');
54 | return $this->console
55 | ->readLine();
56 | }
57 | public function execute($callback = false) {
58 | $this->name = $this->getName();
59 | $this->description = $this->getDescription();
60 |
61 | $templateContent = file_get_contents(__DIR__.'/../../../data/scenarioTemplate.tpl');
62 |
63 | $arReplace = array(
64 | '#class_name#' => $className = 'ws_m_' . time(). '_' . \CUtil::translit($this->name, LANGUAGE_ID),
65 | '#name#' => $this->name,
66 | '#description#' => $this->description,
67 | '#db_version#' => $this->module->getPlatformVersion()->getValue(),
68 | '#owner#' => $this->module->getPlatformVersion()->getOwner()
69 | );
70 | $classContent = str_replace(array_keys($arReplace), array_values($arReplace), $templateContent);
71 | $fileName = $className . '.php';
72 | try {
73 | $fileName = $this->module->putScriptClass($fileName, $classContent);
74 | } catch (\Exception $e) {
75 | $this->console->printLine("An error occurred saving file", Console::OUTPUT_ERROR);
76 | return;
77 | }
78 | $this->console->printLine($fileName, Console::OUTPUT_SUCCESS);
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/lib/console/command/helpcommand.php:
--------------------------------------------------------------------------------
1 | console
9 | ->printLine("Action list:")
10 | ->printLine("* list - List of new migrations")
11 | ->printLine("* apply - Apply new migrations, \n -f Without approve")
12 | ->printLine("* rollback - Rollback last applied migrations")
13 | ->printLine("* createScenario - Create new migration scenario, \n -n 'Name' - scenario name \n -d 'Description' - scenario description")
14 | ->printLine("* last - Show last applied migrations list")
15 | ;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/console/command/lastcommand.php:
--------------------------------------------------------------------------------
1 | getLastSetupLog();
11 | if (!$lastSetupLog) {
12 | $this->console
13 | ->printLine("Nothing to show.");
14 | return;
15 | }
16 | $appliedFixes = array();
17 | $errorFixes = array();
18 |
19 | foreach ($lastSetupLog->getAppliedLogs() as $appliedLog) {
20 | !$appliedLog->success && $errorFixes[] = $appliedLog;
21 | $appliedLog->success && $appliedFixes[$appliedLog->description]++;
22 | }
23 | foreach ($appliedFixes as $fixName => $fixCount) {
24 | $this->console
25 | ->printLine($fixName . ($fixCount > 1 ? "[$fixCount]" : ""), Console::OUTPUT_SUCCESS);
26 | }
27 | /** @var \WS\Migrations\Entities\AppliedChangesLogModel $errorApply */
28 | foreach ($errorFixes as $errorApply) {
29 | $errorData = \WS\Migrations\jsonToArray($errorApply->description) ?: $errorApply->description;
30 | if (is_scalar($errorData)) {
31 | $this->console
32 | ->printLine($errorData, Console::OUTPUT_ERROR);
33 | }
34 | if (is_array($errorData)) {
35 | $this->console
36 | ->printLine($errorData['message'], Console::OUTPUT_ERROR);
37 | }
38 |
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/console/command/listcommand.php:
--------------------------------------------------------------------------------
1 | registeredFixes = array();
13 | $this->localization = \WS\Migrations\Module::getInstance()->getLocalization('admin')->fork('cli');
14 | }
15 |
16 | public function execute($callback = false) {
17 | $has = false;
18 | foreach ($this->module->getNotAppliedFixes() as $notAppliedFix) {
19 | $this->registerFix($notAppliedFix->getName());
20 | $has = true;
21 | }
22 | foreach ($this->module->getNotAppliedScenarios() as $notAppliedScenario) {
23 | $this->registerFix($notAppliedScenario::name());
24 | $has = true;
25 | }
26 | !$has && $this->console->printLine("Nothing to apply");
27 | $has && $this->printRegisteredFixes();
28 | }
29 |
30 | private function registerFix($name) {
31 | if ($name == 'Reference fix') {
32 | $name = $this->localization->message('common.reference-fix');
33 | }
34 | $this->registeredFixes[$name]++;
35 | }
36 |
37 | private function printRegisteredFixes() {
38 | foreach ($this->registeredFixes as $name => $count) {
39 | $count = $count > 1 ? '['.$count.']' : '';
40 | $this->console->printLine($name.' '.$count);
41 | }
42 | }
43 |
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/lib/console/command/rollbackcommand.php:
--------------------------------------------------------------------------------
1 | console
11 | ->printLine("Are you sure? (yes|no):");
12 |
13 | $answer = $this->console
14 | ->readLine();
15 |
16 | if ($answer != 'yes') {
17 | return;
18 | }
19 | $this->console
20 | ->printLine("Rollback action started...", Console::OUTPUT_PROGRESS);
21 | $start = microtime(true);
22 | $this->module
23 | ->rollbackLastChanges($callback);
24 |
25 | $interval = round(microtime(true) - $start, 2);
26 |
27 | $this->console
28 | ->printLine("Rollback action finished! Time $interval sec", Console::OUTPUT_PROGRESS);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/console/console.php:
--------------------------------------------------------------------------------
1 | ConvertCharsetArray($args, "UTF-8", LANG_CHARSET);
35 | $this->out = fopen('php://stdout', 'w');
36 | array_shift($args);
37 | $this->params = $args;
38 | $this->action = isset($this->params[0]) ? $this->params[0] : '--help';
39 | $this->successOutput = new Output('green');
40 | $this->errorOutput = new Output('red');
41 | $this->progressOutput = new Output('yellow');
42 | $this->defaultOutput = new Output();
43 | }
44 |
45 | /**
46 | * @param $str
47 | * @param $type
48 | * @return Console
49 | */
50 | public function printLine($str, $type = false) {
51 | global $APPLICATION;
52 | $str = $APPLICATION->ConvertCharset($str, LANG_CHARSET, "UTF-8");
53 | if ($type) {
54 | $str = $this->getOutput($type)->colorize($str);
55 | }
56 | fwrite($this->out, $str . "\n");
57 | return $this;
58 | }
59 |
60 | public function readLine() {
61 | return trim(fgets(STDIN));
62 | }
63 |
64 | /**
65 | * @return BaseCommand
66 | * @throws ConsoleException
67 | */
68 | public function getCommand() {
69 | $commands = array(
70 | '--help' => HelpCommand::className(),
71 | 'list' => ListCommand::className(),
72 | 'apply' => ApplyCommand::className(),
73 | 'rollback' => RollbackCommand::className(),
74 | 'last' => LastCommand::className(),
75 | 'createScenario' => CreateScenarioCommand::className(),
76 | );
77 | if (!$commands[$this->action]) {
78 | throw new ConsoleException("Action `{$this->action}` is not supported");
79 | }
80 | return new $commands[$this->action]($this, $this->params);
81 | }
82 |
83 | /**
84 | * @param $type
85 | * @return Output
86 | */
87 | private function getOutput($type) {
88 | switch ($type) {
89 | case 'success':
90 | return $this->successOutput;
91 | break;
92 | case 'error':
93 | return $this->errorOutput;
94 | break;
95 | case 'progress':
96 | return $this->progressOutput;
97 | break;
98 | default:;
99 | }
100 | return $this->defaultOutput;
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/lib/console/consoleexception.php:
--------------------------------------------------------------------------------
1 | textColors();
13 | $this->color = isset($colors[$color]) ? $colors[$color] : $colors['default'];
14 | }
15 |
16 | public function textColors () {
17 | return array(
18 | 'black' => 30,
19 | 'red' => 31,
20 | 'green' => 32,
21 | 'yellow' => 33,
22 | 'blue' => 34,
23 | 'magenta' => 35,
24 | 'cyan' => 36,
25 | 'white' => 37,
26 | 'default' => 0
27 | );
28 | }
29 |
30 | public function colorize($text) {
31 | return chr(27) . "[{$this->color}m" . $text . chr(27) . "[0m";
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/lib/console/runtimecounter.php:
--------------------------------------------------------------------------------
1 | start = microtime(true);
11 | $this->migrationCount = 0;
12 | $this->migrationNumbe = 0;
13 | }
14 | }
--------------------------------------------------------------------------------
/lib/console/runtimefixcounter.php:
--------------------------------------------------------------------------------
1 | time = 0;
18 | $this->activeFixName = '';
19 | $this->fixNames = array();
20 | $this->fixNumber = 0;
21 | $this->migrationCount = 0;
22 | }
23 |
24 | public function setFixNameByFixes($fixes) {
25 | /** @var CollectorFix $fix */
26 | foreach ($fixes as $fix) {
27 | if ($this->activeFixName != $fix->getName()) {
28 | $this->fixNumber++;
29 | $this->activeFixName = $fix->getName();
30 | }
31 | $this->fixNames[$this->activeFixName . $this->fixNumber]++;
32 | }
33 | }
34 |
35 | /**
36 | * @param AppliedChangesLogModel[] $list
37 | */
38 | public function setFixNamesByLogs($list) {
39 | foreach ($list as $log) {
40 | if (!$log->success) {
41 | continue;
42 | }
43 | $processName = $log->description;
44 | if ($processName == Module::SPECIAL_PROCESS_SCENARIO) {
45 | $this->migrationCount++;
46 | continue;
47 | }
48 | if ($this->activeFixName != $log->description) {
49 | $this->migrationCount++;
50 | $this->fixNumber++;
51 | $this->activeFixName = $log->description;
52 | }
53 | $this->fixNames[$this->activeFixName . $this->fixNumber]++;
54 | }
55 | }
56 |
57 | }
--------------------------------------------------------------------------------
/lib/diagnostic/diagnosticresult.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Diagnostic;
7 |
8 | /**
9 | * Class DiagnosticResult
10 | *
11 | * @package WS\Migrations\Diagnostic
12 | */
13 | class DiagnosticResult {
14 |
15 | /**
16 | * @var bool
17 | */
18 | private $success;
19 |
20 | /**
21 | * @var ErrorMessage[]
22 | */
23 | private $messages;
24 |
25 | /**
26 | * @var string
27 | */
28 | private $time;
29 |
30 | /**
31 | * @var bool
32 | */
33 | private $isNull = false;
34 |
35 | /**
36 | * @param bool $success
37 | * @param ErrorMessage[] $messages
38 | * @param string $time
39 | * @throws \Exception
40 | */
41 | public function __construct($success, array $messages, $time = '') {
42 | $this->success = $success;
43 | $this->messages = $messages;
44 | foreach ($this->messages as $message) {
45 | if (! $message instanceof ErrorMessage) {
46 | throw new \Exception('Message must be as object');
47 | }
48 | }
49 | $this->time = $time;
50 | }
51 |
52 | /**
53 | * @return DiagnosticResult
54 | */
55 | public static function createNull() {
56 | $object = new static(true, array(), '-');
57 | $object->isNull = true;
58 | return $object;
59 | }
60 |
61 | /**
62 | * @return bool
63 | */
64 | public function isNull() {
65 | return $this->isNull;
66 | }
67 |
68 | /**
69 | * @return bool
70 | */
71 | public function isSuccess() {
72 | return $this->success;
73 | }
74 |
75 | /**
76 | * @return ErrorMessage[]
77 | */
78 | public function getMessages() {
79 | return $this->messages;
80 | }
81 |
82 | public function getMessagesText() {
83 | return array_map(function (ErrorMessage $message) {
84 | return $message->getText();
85 | }, $this->getMessages());
86 | }
87 |
88 | /**
89 | * @return string
90 | */
91 | public function getTime() {
92 | return $this->time;
93 | }
94 | }
--------------------------------------------------------------------------------
/lib/diagnostic/diagnostictester.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Diagnostic;
7 |
8 | use WS\Migrations\Module;
9 | use WS\Migrations\SubjectHandlers\BaseSubjectHandler;
10 |
11 | class DiagnosticTester {
12 |
13 | const LOG_TYPE = 'WS_MIGRATIONS_DIAGNOSTIC';
14 |
15 | /**
16 | * @var BaseSubjectHandler[]
17 | */
18 | private $handlers;
19 | /**
20 | * @var Module
21 | */
22 | private $module;
23 |
24 | /**
25 | * @var bool
26 | */
27 | private $lastRun;
28 |
29 | /**
30 | * @param BaseSubjectHandler[] $handlers
31 | * @param Module $module
32 | */
33 | public function __construct(array $handlers, Module $module) {
34 | $this->handlers = $handlers;
35 | $this->module = $module;
36 | }
37 |
38 | /**
39 | * @return bool
40 | */
41 | public function run() {
42 | $success = true;
43 | $messages = array();
44 | if (!$this->module->getPlatformVersion()->isValid()) {
45 | $messages[] = new ErrorMessage('module', '', '', 'Module has not valid version');
46 | }
47 | foreach ($this->handlers as $handler) {
48 | $handlerResult = $handler->diagnostic();
49 | if (!$handlerResult->isSuccess()) {
50 | $success = false;
51 | $messages = array_merge($messages, $handlerResult->getMessages());
52 | }
53 | }
54 |
55 | $this->lastRun = $success;
56 | $jsonData = json_encode(array(
57 | 'success' => $success,
58 | 'messages' => array_map(function (ErrorMessage $message) {
59 | return $message->toArray();
60 | }, $messages)
61 | ));
62 | \CEventLog::Log('INFO', self::LOG_TYPE, 'ws.migrations', null, $jsonData);
63 | return $success;
64 | }
65 |
66 | /**
67 | * @return bool
68 | */
69 | public function hasRun() {
70 | return $this->lastRun !== null;
71 | }
72 |
73 | /**
74 | * @return bool
75 | * @throws \Exception
76 | */
77 | public function isSuccessRunResult() {
78 | if (!$this->hasRun()) {
79 | throw new \Exception("Run is not launched");
80 | }
81 | return $this->lastRun;
82 | }
83 |
84 | /**
85 | * @return DiagnosticResult
86 | */
87 | public function getLastResult() {
88 | $arLog = \CEventLog::GetList(array('ID' => 'DESC'), array(
89 | 'AUDIT_TYPE_ID' => self::LOG_TYPE
90 | ),
91 | array(
92 | 'nPageSize' => 1
93 | )
94 | )->Fetch();
95 |
96 | if (!$arLog) {
97 | return DiagnosticResult::createNull();
98 | }
99 | $arLogData = $arLog ? json_decode($arLog['DESCRIPTION'], true) : array();
100 | $res = new DiagnosticResult(
101 | $arLogData['success'] ?: false,
102 | array_map(
103 | function ($messageData) {
104 | return ErrorMessage::unpack($messageData);
105 | },
106 | $arLogData['messages'] ?: array()
107 | ),
108 | $arLog['TIMESTAMP_X']
109 | );
110 | return $res;
111 | }
112 | }
--------------------------------------------------------------------------------
/lib/diagnostic/errormessage.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Diagnostic;
7 |
8 | /**
9 | * Class ErrorMessage is container for errors handle
10 | *
11 | * @package WS\Migrations\Diagnostic
12 | */
13 | class ErrorMessage {
14 |
15 | const TYPE_ITEM_HAS_NOT_REFERENCE = 'item-has-not-reference';
16 | const TYPE_REFERENCE_WITHOUT_ITEM = 'reference-without-item';
17 |
18 | private $group;
19 | private $item;
20 | private $type;
21 | private $text;
22 |
23 | /**
24 | * @param string $group
25 | * @param string $item
26 | * @param string $type
27 | * @param string $text
28 | */
29 | public function __construct($group, $item, $type, $text) {
30 | $this->group = $group;
31 | $this->item = $item;
32 | $this->type = $type;
33 | $this->text = $text;
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | public function getGroup() {
40 | return $this->group;
41 | }
42 |
43 | /**
44 | * @return string
45 | */
46 | public function getItem() {
47 | return $this->item;
48 | }
49 |
50 | /**
51 | * @return string
52 | */
53 | public function getType() {
54 | return $this->type;
55 | }
56 |
57 | /**
58 | * @return string
59 | */
60 | public function getText() {
61 | return $this->text;
62 | }
63 |
64 | /**
65 | * @param $data
66 | * @return ErrorMessage
67 | */
68 | static public function unpack($data) {
69 | return new static(
70 | $data['group'],
71 | $data['item'],
72 | $data['type'],
73 | $data['text']
74 | );
75 | }
76 |
77 | /**
78 | * @return array
79 | */
80 | public function toArray() {
81 | return array(
82 | 'group' => $this->group,
83 | 'item' => $this->item,
84 | 'type' => $this->type,
85 | 'text' => $this->text
86 | );
87 | }
88 | }
--------------------------------------------------------------------------------
/lib/entities/appliedchangeslog.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Entities;
7 |
8 |
9 | use Bitrix\Main\Entity\DataManager;
10 | use Bitrix\Main;
11 |
12 | class AppliedChangesLogTable extends DataManager {
13 | public static function className() {
14 | return get_called_class();
15 | }
16 |
17 | public static function getFilePath() {
18 | // fuck )))
19 | return __FILE__;
20 | }
21 |
22 | public static function getTableName() {
23 | return 'ws_migrations_apply_changes_log';
24 | }
25 |
26 | public static function getMap() {
27 | return array(
28 | 'ID' => array(
29 | 'data_type' => 'integer',
30 | 'primary' => true,
31 | 'autocomplete' => true
32 | ),
33 | 'SETUP_LOG_ID' => array(
34 | 'data_type' => 'integer'
35 | ),
36 | 'GROUP_LABEL' => array(
37 | 'data_type' => 'string',
38 | 'required' => true,
39 | ),
40 | 'DATE' => array(
41 | 'data_type' => 'datetime',
42 | 'required' => true,
43 | ),
44 | 'PROCESS' => array(
45 | 'data_type' => 'string',
46 | 'required' => true,
47 | ),
48 | 'SUBJECT' => array(
49 | 'data_type' => 'string',
50 | 'required' => true,
51 | ),
52 | 'UPDATE_DATA' => array(
53 | 'data_type' => 'string',
54 | 'required' => true,
55 | ),
56 | 'ORIGINAL_DATA' => array(
57 | 'data_type' => 'string',
58 | 'required' => true,
59 | ),
60 | 'SUCCESS' => array(
61 | 'data_type' => 'boolean',
62 | 'values' => array(false,true)
63 | ),
64 | 'DESCRIPTION' => array(
65 | 'data_type' => 'string',
66 | 'required' => true,
67 | ),
68 | 'SOURCE' => array(
69 | 'data_type' => 'string'
70 | )
71 | );
72 | }
73 | }
--------------------------------------------------------------------------------
/lib/entities/appliedchangeslogmodel.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Entities;
7 |
8 | use Bitrix\Main\Type\DateTime;
9 | use WS\Migrations\factories\DateTimeFactory;
10 |
11 | class AppliedChangesLogModel extends BaseEntity {
12 | public
13 | $id, $groupLabel, $date, $success,
14 | $processName, $subjectName, $source, $updateData,
15 | $originalData, $description, $setupLogId;
16 |
17 | private $_setupLog;
18 |
19 | public function __construct() {
20 | $this->date = DateTimeFactory::createBase();
21 | }
22 |
23 | static protected function modifyFromDb($data) {
24 | $result = array();
25 | foreach ($data as $name => $value) {
26 | if ($name == 'date') {
27 | if ($value instanceof DateTime) {
28 | $timestamp = $value->getTimestamp();
29 | $value = DateTimeFactory::createBase();
30 | $value->setTimestamp($timestamp);
31 | } else {
32 | $value = DateTimeFactory::createBase($value);
33 | }
34 | }
35 | if (in_array($name, array('originalData', 'updateData'))) {
36 | $value = \WS\Migrations\jsonToArray($value);
37 | }
38 | $result[$name] = $value;
39 | }
40 | return $result;
41 | }
42 |
43 | static protected function modifyToDb($data) {
44 | $result = array();
45 | foreach ($data as $name => $value) {
46 | if ($name == 'date' && $value instanceof \DateTime) {
47 | $value = DateTimeFactory::createBitrix($value);
48 | }
49 | if (in_array($name, array('originalData', 'updateData'))) {
50 | $value = \WS\Migrations\arrayToJson($value);
51 | }
52 | $result[$name] = $value;
53 | }
54 | return $result;
55 | }
56 |
57 | static protected function map() {
58 | return array(
59 | 'id' => 'ID',
60 | 'setupLogId' => 'SETUP_LOG_ID',
61 | 'groupLabel' => 'GROUP_LABEL',
62 | 'date' => 'DATE',
63 | 'processName' => 'PROCESS',
64 | 'subjectName' => 'SUBJECT',
65 | 'source' => 'SOURCE',
66 | 'updateData' => 'UPDATE_DATA',
67 | 'originalData' => 'ORIGINAL_DATA',
68 | 'success' => 'SUCCESS',
69 | 'description' => 'DESCRIPTION'
70 | );
71 | }
72 |
73 | /**
74 | * @return SetupLogModel
75 | */
76 | public function getSetupLog() {
77 | if (!$this->_setupLog) {
78 | $this->_setupLog = SetupLogModel::findOne(array(
79 | 'filter' => array('=id' => $this->setupLogId)
80 | )
81 | );
82 | }
83 | return $this->_setupLog;
84 | }
85 |
86 | public function setSetupLog(SetupLogModel $model = null) {
87 | $this->_setupLog = $model;
88 | $model->id && $this->setupLogId = $model->id;
89 | return $this;
90 | }
91 |
92 | static protected function gatewayClass() {
93 | return AppliedChangesLogTable::className();
94 | }
95 | }
--------------------------------------------------------------------------------
/lib/entities/baseentity.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Entities;
7 |
8 |
9 | abstract class BaseEntity {
10 | public $id;
11 |
12 | private $_isNew = true;
13 |
14 | private $_errors = array();
15 |
16 | static private $_oneRequestsCache = array();
17 | /**
18 | * @param $props
19 | * @return $this
20 | */
21 | static public function create($props) {
22 | /** @var $model BaseEntity */
23 | $model = new static;
24 | foreach ($props as $name => $value) {
25 | $model->{$name} = $value;
26 | }
27 | $model->_isNew = false;
28 | return $model;
29 | }
30 |
31 | /**
32 | * @param $fields
33 | * @return $this
34 | */
35 | static private function _createByRow($fields) {
36 | $props = array();
37 | $fieldsToProps = array_flip(static::map());
38 | foreach ($fields as $name => $value) {
39 | $name = $fieldsToProps[$name];
40 | $props[$name] = $value;
41 | }
42 | $props = static::modifyFromDb($props);
43 | return self::create($props);
44 | }
45 |
46 | private function _getRawFields() {
47 | $result = array();
48 | $data = array();
49 | foreach (static::map() as $property => $field) {
50 | $data[$property] = $this->{$property};
51 | }
52 | $data = static::modifyToDb($data);
53 | foreach (static::map() as $property => $field) {
54 | $result[$field] = $data[$property];
55 | }
56 |
57 | return $result;
58 | }
59 |
60 | /**
61 | * @param array $params
62 | * @return AppliedChangesLogModel[]
63 | */
64 | static public function find($params = array()) {
65 | $modelToDb = static::map();
66 | $fReplaceList = function ($list) use ($modelToDb) {
67 | return array_map(function ($item) use ($modelToDb) {
68 | return $modelToDb[$item];
69 | }, $list);
70 | };
71 |
72 | if ($params['select']) {
73 | $params['select'] = $fReplaceList($params['select']);
74 | }
75 | if ($params['group']) {
76 | $pGroup = array();
77 | foreach ($params['group'] as $field => $value) {
78 | $pGroup[$modelToDb[$field]] = $value;
79 | }
80 | $params['group'] = $pGroup;
81 | }
82 | if ($params['order']) {
83 | $pOrder = array();
84 | foreach ($params['order'] as $field => $value) {
85 | $pOrder[$modelToDb[$field]] = $value;
86 | }
87 | $params['order'] = $pOrder;
88 | }
89 |
90 | if ($params['filter']) {
91 | $pFilter = array();
92 | foreach ($params['filter'] as $field => $value) {
93 | $field = preg_replace_callback("/\w+/", function ($matches) use ($modelToDb) {
94 | return $modelToDb[$matches[0]];
95 | }, $field);
96 | $pFilter[$field] = $value;
97 | }
98 | $params['filter'] = $pFilter;
99 | }
100 | $dbResult = static::callGatewayMethod('getList', $params);
101 | $rows = $dbResult->fetchAll();
102 | $items = array();
103 | foreach ($rows as $row) {
104 | $items[] = self::_createByRow($row);
105 | }
106 | return $items;
107 | }
108 |
109 | /**
110 | * @param array $params
111 | * @return $this
112 | */
113 | static public function findOne($params = array()) {
114 | $cacheKey = md5(get_called_class().serialize($params));
115 | if (!self::$_oneRequestsCache[$cacheKey]) {
116 | $params['limit'] = 1;
117 | $items = self::find($params);
118 | self::$_oneRequestsCache[$cacheKey] = $items[0];
119 | }
120 | return self::$_oneRequestsCache[$cacheKey];
121 | }
122 |
123 | /**
124 | * @param $name
125 | * @return mixed
126 | * @internal param $p1
127 | * @internal param $p2
128 | * @internal param $p3
129 | *
130 | */
131 | static public function callGatewayMethod($name) {
132 | $params = func_get_args();
133 | $name = array_shift($params);
134 | return call_user_func_array(array(static::gatewayClass(), $name), $params);
135 | }
136 |
137 | public function delete() {
138 | $res = static::callGatewayMethod('delete', $this->id);
139 | return !(bool)$res->getErrors();
140 | }
141 |
142 | public function insert() {
143 | $res = static::callGatewayMethod('add', $this->_getRawFields());
144 | $this->id = $res->getId();
145 | $this->_errors = $res->getErrors() ?: array();
146 | $this->_isNew = false;
147 | return !(bool)$res->getErrors();
148 | }
149 |
150 | public function update() {
151 | $res = static::callGatewayMethod('update', $this->id, $this->_getRawFields());
152 | $this->_errors = $res->getErrors() ?: array();
153 | return !(bool)$res->getErrors();
154 | }
155 |
156 | public function save() {
157 | return $this->_isNew ? $this->insert() : $this->update();
158 | }
159 |
160 | public function getErrors() {
161 | return $this->_errors;
162 | }
163 |
164 | abstract static protected function map();
165 |
166 | abstract static protected function gatewayClass();
167 |
168 | static protected function modifyFromDb($data) {
169 | return $data;
170 | }
171 |
172 | static protected function modifyToDb($data) {
173 | return $data;
174 | }
175 | }
--------------------------------------------------------------------------------
/lib/entities/dbversionreferences.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Entities;
7 |
8 |
9 | use Bitrix\Main\Entity\DataManager;
10 |
11 | class DbVersionReferencesTable extends DataManager {
12 |
13 | public static function getTableName() {
14 | return 'ws_migrations_db_version_references';
15 | }
16 |
17 | public static function className() {
18 | return get_called_class();
19 | }
20 |
21 | public static function getFilePath() {
22 | // fuck )))
23 | return __FILE__;
24 | }
25 |
26 | public static function getMap() {
27 | return array(
28 | 'ID' => array(
29 | 'data_type' => 'integer',
30 | 'primary' => true,
31 | 'autocomplete' => true
32 | ),
33 | 'REFERENCE' => array(
34 | 'data_type' => 'string',
35 | 'required' => true
36 | ),
37 | 'DB_VERSION' => array(
38 | 'data_type' => 'string',
39 | 'required' => true
40 | ),
41 | 'GROUP' => array(
42 | 'data_type' => 'string',
43 | 'required' => true
44 | ),
45 | 'ITEM_ID' => array(
46 | 'data_type' => 'string',
47 | 'required' => true
48 | )
49 | );
50 | }
51 | }
--------------------------------------------------------------------------------
/lib/entities/setuplog.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Entities;
7 |
8 |
9 | use Bitrix\Main\Entity\DataManager;
10 | use Bitrix\Main;
11 |
12 | class SetupLogTable extends DataManager {
13 |
14 | public static function className() {
15 | return get_called_class();
16 | }
17 |
18 | public static function getTableName() {
19 | return 'ws_migrations_setups_log';
20 | }
21 |
22 | /**
23 | * fuck ))
24 | * @return string|void
25 | */
26 | public static function getFilePath() {
27 | return __FILE__;
28 | }
29 |
30 | public static function getMap() {
31 | return array(
32 | 'ID' => array(
33 | 'data_type' => 'integer',
34 | 'primary' => true,
35 | 'autocomplete' => true
36 | ),
37 | 'DATE' => array(
38 | 'data_type' => 'datetime',
39 | 'required' => true,
40 | ),
41 | 'USER_ID' => array(
42 | 'data_type' => 'integer'
43 | )
44 | );
45 | }
46 | }
--------------------------------------------------------------------------------
/lib/entities/setuplogmodel.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Entities;
7 |
8 |
9 | use Bitrix\Main\Type\DateTime;
10 | use Bitrix\Main\UserTable;
11 | use WS\Migrations\factories\DateTimeFactory;
12 |
13 | class SetupLogModel extends BaseEntity {
14 | public
15 | $id, $userId;
16 | /**
17 | * @var \DateTime
18 | */
19 | public $date;
20 |
21 | private $_userData = false;
22 |
23 | public function __construct() {
24 | $this->date = DateTimeFactory::createBase();
25 | }
26 |
27 | static protected function map() {
28 | return array(
29 | 'id' => 'ID',
30 | 'date' => 'DATE',
31 | 'userId' => 'USER_ID'
32 | );
33 | }
34 |
35 | static protected function gatewayClass() {
36 | return SetupLogTable::className();
37 | }
38 |
39 | static protected function modifyFromDb($data) {
40 | if ($data['date'] instanceof DateTime) {
41 | $timestamp = $data['date']->getTimestamp();
42 | $data['date'] = DateTimeFactory::createBase();
43 | $data['date']->setTimestamp($timestamp);
44 | } else {
45 | $data['date']= DateTimeFactory::createBase($data['date']);
46 | }
47 | return $data;
48 | }
49 |
50 | static protected function modifyToDb($data) {
51 | $data['date'] && $data['date'] instanceof \DateTime && $data['date'] = DateTimeFactory::createBitrix($data['date']);
52 | return $data;
53 | }
54 |
55 | /**
56 | * @return AppliedChangesLogModel[]
57 | */
58 | public function getAppliedLogs() {
59 | return AppliedChangesLogModel::find(array(
60 | 'filter' => array(
61 | '=setupLogId' => $this->id
62 | )
63 | ));
64 | }
65 |
66 | /**
67 | * @return array
68 | */
69 | private function getUserData() {
70 | if ($this->_userData === false) {
71 | $this->_userData = UserTable::getById($this->userId)->fetch();
72 | }
73 | return $this->_userData;
74 | }
75 |
76 | public function shortUserInfo() {
77 | $res = 'cli';
78 | if ($this->userId) {
79 | $data = $this->getUserData();
80 | $res = $data['NAME'].' '.$data['LAST_NAME'];
81 | }
82 | return $res;
83 | }
84 | }
--------------------------------------------------------------------------------
/lib/factories/datetimefactory.php:
--------------------------------------------------------------------------------
1 | format($format), $format, self::timeZone());
29 | return $object;
30 | }
31 |
32 | /**
33 | * @return \DateTimeZone
34 | */
35 | public static function timeZone() {
36 | try {
37 | $obj = new \DateTime();
38 | return $obj->getTimezone();
39 | } catch (\Exception $e) {
40 | $timezoneIdentifier = 'Europe/Moscow';
41 | date_default_timezone_set($timezoneIdentifier);
42 | return new \DateTimeZone($timezoneIdentifier);
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/lib/localization.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Localization {
9 |
10 | /**
11 | * @var Options
12 | */
13 | private $data;
14 |
15 | public function __construct($data) {
16 | $this->data = new Options($data);
17 | }
18 |
19 | /**
20 | * @return Options
21 | */
22 | private function getData() {
23 | return $this->data;
24 | }
25 |
26 | /**
27 | * @param string $path @see Options
28 | * @param array $replace
29 | * @return mixed
30 | */
31 | public function message($path, $replace = null) {
32 | $m = $this->getData()->get($path, '');
33 | $result = $m ?: $path;
34 | if (is_array($replace)) {
35 | $result = str_replace(array_keys($replace), array_values($replace), $m);
36 | }
37 | return $result;
38 | }
39 |
40 | /**
41 | * @param string $path @see Options
42 | * @return Localization
43 | */
44 | public function fork($path) {
45 | return new static($this->getData()->get($path));
46 | }
47 |
48 | public function getDataByPath($path) {
49 | return $this->getData()->get($path, '');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/moduleoptions.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | final class ModuleOptions {
14 | private $_moduleName = 'ws.migrations';
15 |
16 | private $_cache = array();
17 |
18 | private function __construct() {
19 | }
20 |
21 | /**
22 | * @staticvar self $self
23 | * @return Options
24 | */
25 | static public function getInstance() {
26 | static $self = null;
27 | if (!$self) {
28 | $self = new self;
29 | }
30 | return $self;
31 | }
32 |
33 | private function _setToDb($name, $value) {
34 | \COption::SetOptionString($this->_moduleName, $name, serialize($value));
35 | }
36 |
37 | private function _getFromDb($name) {
38 | $value = \COption::GetOptionString($this->_moduleName, $name);
39 | return unserialize($value);
40 | }
41 |
42 | public function __set($name, $value) {
43 | $this->_setToCache($name, $value);
44 | $this->_setToDb($name, $value);
45 | return $value;
46 | }
47 |
48 | public function __get($name) {
49 | $value = $this->_getFormCache($name);
50 | if (is_null($value)) {
51 | $value = $this->_getFromDb($name);
52 | $this->_setToCache($name, $value);
53 | }
54 | return $value;
55 | }
56 |
57 | /**
58 | * @param $class
59 | */
60 | public function disableSubjectHandler($class) {
61 | $this->enabledSubjectHandlers = array_diff($this->enabledSubjectHandlers ?: array(), array($class));
62 | }
63 |
64 | /**
65 | * @param $class
66 | */
67 | public function enableSubjectHandler($class) {
68 | $this->enabledSubjectHandlers = array_unique(array_merge($this->enabledSubjectHandlers ?: array(), array($class)));
69 | }
70 |
71 | /**
72 | * @param $class
73 | * @return bool
74 | */
75 | public function isEnableSubjectHandler($class) {
76 | return in_array($class, $this->enabledSubjectHandlers);
77 | }
78 |
79 | /**
80 | * @return array
81 | */
82 | public function getOtherVersions() {
83 | return $this->otherVersions;
84 | }
85 |
86 | /**
87 | * @param $name
88 | * @return mixed
89 | */
90 | private function _getFormCache($name) {
91 | return $this->_cache[$name];
92 | }
93 |
94 | /**
95 | * @param $name
96 | * @param $value
97 | */
98 | private function _setToCache($name, $value) {
99 | $this->_cache[$name] = $value;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/lib/options.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class Options implements \Serializable, \ArrayAccess {
9 |
10 | private $_data = array();
11 |
12 | public function __construct(array $data = null) {
13 | $data && ($this->_data = $data);
14 | }
15 |
16 | /**
17 | * @param string $path
18 | * @param mixed $default
19 | * @throws \Exception
20 | * @return mixed
21 | */
22 | public function get($path, $default = null) {
23 |
24 | $usesAliases = array();
25 | $rPath = preg_replace_callback('/\[.*?\]/', function ($matches) use (& $usesAliases){
26 | $key = trim($matches[0], '[]');
27 | $alias = str_replace('.', '_', $key);
28 | $usesAliases[$alias] = $key;
29 | return '.'.$alias;
30 | }, $path);
31 |
32 | $arPath = explode('.', $rPath);
33 | $data = $this->_data;
34 | while (($pathItem = array_shift($arPath)) !== null) {
35 | if ($usesAliases[$pathItem]) {
36 | $pathItem = $usesAliases[$pathItem];
37 | unset($usesAliases[$pathItem]);
38 | }
39 |
40 | if ($data instanceof self) {
41 | $data = $data->toArray();
42 | }
43 | if ( ! isset($data[$pathItem])) {
44 | if ( ! is_null($default)) {
45 | return $default;
46 | }
47 | throw new \Exception("Value by path `$path` not exist");
48 | }
49 | $data = $data[$pathItem];
50 | }
51 | return $data;
52 | }
53 |
54 | /**
55 | * @param string $path
56 | * @param null|mixed $default
57 | * @throws \Exception
58 | * @return $this
59 | */
60 | public function getAsObject($path, $default = null) {
61 | $res = $this->get($path, $default);
62 | if (!is_array($res)) {
63 | throw new \Exception("Return value as object not available");
64 | }
65 | return new static($this->get($path));
66 | }
67 |
68 | /**
69 | * @param \ArrayAccess|array $mergedOptions
70 | * @return Options
71 | */
72 | public function merge($mergedOptions) {
73 | if (is_object($mergedOptions) && $mergedOptions instanceof Options) {
74 | $mergedOptions = $mergedOptions->toArray();
75 | }
76 | foreach ($mergedOptions as $path => $value) {
77 | $this->set($path, $value);
78 | }
79 | return $this;
80 | }
81 |
82 | /**
83 | * @param string $path
84 | * @param mixed $value
85 | * @throws \Exception
86 | * @return Options
87 | */
88 | public function set($path, $value) {
89 | $arPath = explode('.', $path);
90 | $data = & $this->_data;
91 | while (($key = array_shift($arPath)) !== null) {
92 | if (empty($arPath)) {
93 | $key ? $data[$key] = $value : $data[] = $value;
94 | } else {
95 | if ( ! $key) {
96 | throw new \Exception('Need last iterated by path. Available: ' . $path);
97 | }
98 | if ( ! isset($data[$key])) {
99 | $data[$key] = array();
100 | }
101 | $data = & $data[$key];
102 | }
103 | }
104 | return $this;
105 | }
106 |
107 | public function __invoke() {
108 | $args = func_get_args();
109 | switch (count($args)) {
110 | case 1:
111 | return $this->get($args[0]);
112 | break;
113 | case 2:
114 | return $this->set($args[0], $args[1]);
115 | break;
116 | }
117 | }
118 |
119 | public function toArray() {
120 | return $this->_data;
121 | }
122 |
123 | public function serialize() {
124 | return serialize($this->_data);
125 | }
126 |
127 | public function unserialize($serialized) {
128 | $this->_data = unserialize($serialized);
129 | }
130 |
131 | public function offsetExists($offset) {
132 | try {
133 | $this->get($offset);
134 | return true;
135 | } catch (\Exception $e) {
136 | return false;
137 | }
138 | }
139 |
140 | public function offsetGet($offset) {
141 | return $this->get($offset);
142 | }
143 |
144 | public function offsetSet($offset, $value) {
145 | $this->set($offset, $value);
146 | return $value;
147 | }
148 |
149 | public function offsetUnset($offset) {
150 | $this->set($offset, null);
151 | }
152 |
153 | public function toJson() {
154 | return json_encode($this->toArray());
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/lib/platformversion.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations;
7 |
8 | class PlatformVersion {
9 |
10 | /**
11 | * @var string
12 | */
13 | private $version;
14 |
15 | /**
16 | * @var string
17 | */
18 | private $checkSum;
19 |
20 | /**
21 | * @var string
22 | */
23 | private $owner;
24 |
25 | /**
26 | * @var array ["asfdsgs" => "Vasiliy Dubinin"]
27 | */
28 | private $mapOtherVersions;
29 |
30 | public function __construct($mapOtherVersions) {
31 | $this->mapOtherVersions = $mapOtherVersions ?: array();
32 | $filePath = $this->filePath();
33 | file_exists($filePath) ? $this->initFromFile() : $this->generate();
34 | }
35 |
36 | private function initFromFile() {
37 | $raw = explode(':#:', file_get_contents($this->filePath()));
38 | $this->version = $raw[0];
39 | $this->checkSum = $raw[1];
40 | $this->owner = $raw[2];
41 | }
42 |
43 | private function generate() {
44 | $this->version = md5(time());
45 | $this->checkSum = md5($this->version.__FILE__);
46 | $this->save();
47 | }
48 |
49 | /**
50 | * @return string
51 | */
52 | public function getValue() {
53 | return $this->version;
54 | }
55 |
56 | /**
57 | * @return bool
58 | */
59 | public function isValid() {
60 | return $this->checkSum == md5($this->version.__FILE__);
61 | }
62 |
63 | /**
64 | * @return string
65 | */
66 | public function getOwner() {
67 | return $this->owner;
68 | }
69 |
70 | /**
71 | * @return array
72 | */
73 | public function getMapVersions() {
74 | return array_merge(
75 | array(
76 | $this->getValue() => $this->getOwner()
77 | ),
78 | $this->mapOtherVersions
79 | );
80 | }
81 |
82 | public function setOwner($owner) {
83 | $this->owner = $owner;
84 | $this->save();
85 | }
86 |
87 | /**
88 | * @return string
89 | */
90 | private function filePath() {
91 | $docRoot = rtrim($_SERVER['DOCUMENT_ROOT'], '/').'/';
92 | return $docRoot . \COption::GetOptionString("main", "upload_dir", "upload")."/ws.migrations/version.dat";
93 | }
94 |
95 | /**
96 | * @throws \Exception
97 | */
98 | private function save() {
99 | $raw = $this->version.':#:'.md5($this->version.__FILE__).':#:'.$this->owner;
100 | $r = fopen($this->filePath(), 'w');
101 | $writeRes = fwrite($r, $raw);
102 | if ($writeRes === false) {
103 | throw new \Exception("File with migration version data isn`t available to record, path ".$this->filePath());
104 | }
105 | }
106 |
107 | public function refresh() {
108 | $this->generate();
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lib/processes/addprocess.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Processes;
7 |
8 | use WS\Migrations\ChangeDataCollector\CollectorFix;
9 | use WS\Migrations\Entities\AppliedChangesLogModel;
10 | use WS\Migrations\Module;
11 | use WS\Migrations\SubjectHandlers\BaseSubjectHandler;
12 |
13 | class AddProcess extends BaseProcess {
14 |
15 | public function update(BaseSubjectHandler $subjectHandler, CollectorFix $fix, AppliedChangesLogModel $log) {
16 | $data = $fix->getUpdateData();
17 | $result = $subjectHandler->applySnapshot($data, $fix->getDbVersion());
18 |
19 | $data = $subjectHandler->getSnapshot($result->getId());
20 | $log->description = $fix->getName();
21 | $log->originalData = array();
22 | $log->updateData = $data;
23 | return $result;
24 | }
25 |
26 | public function rollback(BaseSubjectHandler $subjectHandler, AppliedChangesLogModel $log) {
27 | $id = $subjectHandler->getIdBySnapshot($log->updateData);
28 | return $subjectHandler->delete($id);
29 | }
30 |
31 | public function change(BaseSubjectHandler $subjectHandler, CollectorFix $fix, $data = array()) {
32 | $id = $subjectHandler->getIdByChangeMethod(Module::FIX_CHANGES_AFTER_ADD_KEY, $data);
33 |
34 | $snapshot = $subjectHandler->getSnapshot($id);
35 | if (!$snapshot) {
36 | return false;
37 | }
38 | $fix
39 | ->setOriginalData(array())
40 | ->setUpdateData($snapshot);
41 | return true;
42 | }
43 |
44 | public function getName() {
45 | return $this->getLocalization()->getDataByPath('add');
46 | }
47 | }
--------------------------------------------------------------------------------
/lib/processes/baseprocess.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Processes;
7 |
8 | use WS\Migrations\ApplyResult;
9 | use WS\Migrations\ChangeDataCollector\CollectorFix;
10 | use WS\Migrations\Entities\AppliedChangesLogModel;
11 | use WS\Migrations\Module;
12 | use WS\Migrations\SubjectHandlers\BaseSubjectHandler;
13 |
14 | abstract class BaseProcess {
15 |
16 | public function getLocalization() {
17 | return Module::getInstance()->getLocalization('processes');
18 | }
19 |
20 | static public function className() {
21 | return get_called_class();
22 | }
23 |
24 | abstract public function getName();
25 |
26 | /**
27 | * @param BaseSubjectHandler $subjectHandler
28 | * @param CollectorFix $fix
29 | * @param AppliedChangesLogModel $log
30 | * @return ApplyResult
31 | */
32 | abstract public function update(BaseSubjectHandler $subjectHandler, CollectorFix $fix, AppliedChangesLogModel $log);
33 |
34 | /**
35 | * @param BaseSubjectHandler $subjectHandler
36 | * @param AppliedChangesLogModel $log
37 | * @return ApplyResult
38 | */
39 | abstract public function rollback(BaseSubjectHandler $subjectHandler, AppliedChangesLogModel $log);
40 | }
41 |
--------------------------------------------------------------------------------
/lib/processes/deleteprocess.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Processes;
7 |
8 |
9 | use WS\Migrations\ChangeDataCollector\CollectorFix;
10 | use WS\Migrations\Entities\AppliedChangesLogModel;
11 | use WS\Migrations\Module;
12 | use WS\Migrations\SubjectHandlers\BaseSubjectHandler;
13 | use WS\Migrations\SubjectHandlers\IblockSectionHandler;
14 |
15 | class DeleteProcess extends BaseProcess {
16 | private $_beforeChangesSnapshots = array();
17 |
18 | public function update(BaseSubjectHandler $subjectHandler, CollectorFix $fix, AppliedChangesLogModel $log) {
19 | $id = $fix->getUpdateData();
20 | $originalData = $subjectHandler->getSnapshot($id, $fix->getDbVersion());
21 |
22 | $result = $subjectHandler->delete($id, $fix->getDbVersion());
23 |
24 | $log->description = $fix->getName();
25 | $log->originalData = $originalData;
26 | $log->updateData = $id;
27 | return $result;
28 | }
29 |
30 | public function rollback(BaseSubjectHandler $subjectHandler, AppliedChangesLogModel $log) {
31 | return $subjectHandler->applySnapshot($log->originalData);
32 | }
33 |
34 | public function beforeChange(BaseSubjectHandler $subjectHandler, $data) {
35 | $id = $subjectHandler->getIdByChangeMethod(Module::FIX_CHANGES_BEFORE_DELETE_KEY, $data);
36 | $this->_beforeChangesSnapshots[$id] = $snapshot = $subjectHandler->getSnapshot($id);
37 | }
38 |
39 | public function afterChange(BaseSubjectHandler $subjectHandler, CollectorFix $fix, $data) {
40 | $id = $subjectHandler->getIdByChangeMethod(Module::FIX_CHANGES_AFTER_DELETE_KEY, $data);
41 | $fix
42 | ->setOriginalData($this->_beforeChangesSnapshots[$id])
43 | ->setUpdateData($id);
44 | $subjectHandler->registerDelete($id);
45 | return true;
46 | }
47 |
48 | public function getName() {
49 | return $this->getLocalization()->getDataByPath('delete');
50 | }
51 | }
--------------------------------------------------------------------------------
/lib/processes/updateprocess.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Processes;
7 |
8 |
9 | use WS\Migrations\ChangeDataCollector\CollectorFix;
10 | use WS\Migrations\Entities\AppliedChangesLogModel;
11 | use WS\Migrations\Module;
12 | use WS\Migrations\SubjectHandlers\BaseSubjectHandler;
13 |
14 | class UpdateProcess extends BaseProcess {
15 |
16 | private $_beforeChangesSnapshots = array();
17 |
18 | public function update(BaseSubjectHandler $subjectHandler, CollectorFix $fix, AppliedChangesLogModel $log) {
19 | $data = $fix->getUpdateData();
20 | $id = $subjectHandler->getIdBySnapshot($data);
21 | $originalData = $subjectHandler->getSnapshot($id, $fix->getDbVersion());
22 | $result = $subjectHandler->applyChanges($data, $fix->getDbVersion());
23 |
24 | $log->description = $fix->getName();
25 | $log->originalData = $originalData;
26 | $log->updateData = $data;
27 | return $result;
28 | }
29 |
30 | public function rollback(BaseSubjectHandler $subjectHandler, AppliedChangesLogModel $log) {
31 | return $subjectHandler->applySnapshot($log->originalData);
32 | }
33 |
34 | public function beforeChange(BaseSubjectHandler $subjectHandler, $data) {
35 | $id = $subjectHandler->getIdByChangeMethod(Module::FIX_CHANGES_BEFORE_CHANGE_KEY, $data);
36 | $this->_beforeChangesSnapshots[$id] = $snapshot = $subjectHandler->getSnapshot($id);
37 | }
38 |
39 | public function afterChange(BaseSubjectHandler $subjectHandler, CollectorFix $fix, $data) {
40 | $id = $subjectHandler->getIdByChangeMethod(Module::FIX_CHANGES_AFTER_CHANGE_KEY, $data);
41 | $originalData = $this->_beforeChangesSnapshots[$id];
42 | $actualData = $subjectHandler->getSnapshot($id);
43 | $data = $subjectHandler->analysisOfChanges($actualData, $this->_beforeChangesSnapshots[$id]);
44 | $data && $fix
45 | ->setOriginalData($originalData)
46 | ->setUpdateData($data);
47 | return true;
48 | }
49 |
50 | public function getName() {
51 | return $this->getLocalization()->getDataByPath('update');
52 | }
53 | }
--------------------------------------------------------------------------------
/lib/reference/referenceitem.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Reference;
7 |
8 |
9 | class ReferenceItem {
10 | public $id, $group, $dbVersion, $reference;
11 | }
--------------------------------------------------------------------------------
/lib/scriptscenario.php:
--------------------------------------------------------------------------------
1 | setData($data);
29 | $this->_referenceController = $controller;
30 | }
31 |
32 | /**
33 | * @return Reference\ReferenceController
34 | */
35 | public function getReferenceController(){
36 | return $this->_referenceController;
37 | }
38 |
39 | /**
40 | * @return array
41 | */
42 | public function getData() {
43 | return $this->_data;
44 | }
45 |
46 | /**
47 | * @param array $value
48 | */
49 | protected function setData(array $value = array()) {
50 | $this->_data = $value;
51 | }
52 |
53 |
54 | /**
55 | * Runs to commit migration
56 | */
57 | abstract public function commit();
58 |
59 | /**
60 | * Runs by rollback migration
61 | */
62 | abstract public function rollback();
63 |
64 | /**
65 | * Returns name of migration
66 | * @return string
67 | */
68 | abstract static public function name();
69 |
70 | /**
71 | * @return array First element is hash, second is owner name
72 | */
73 | abstract public function version();
74 |
75 | /**
76 | * Returns description of migration
77 | * @return string
78 | */
79 | abstract static public function description();
80 |
81 | /**
82 | * Check to valid class definition
83 | * @return bool
84 | */
85 | static public function isValid() {
86 | return static::name();
87 | }
88 | }
--------------------------------------------------------------------------------
/lib/subjecthandlers/basesubjecthandler.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lib/subjecthandlers/basesubjecthandler.php
--------------------------------------------------------------------------------
/lib/subjecthandlers/iblockpropertyhandler.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lib/subjecthandlers/iblockpropertyhandler.php
--------------------------------------------------------------------------------
/lib/subjecthandlers/iblocksectionhandler.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\SubjectHandlers;
7 |
8 | use Bitrix\Iblock\SectionTable;
9 | use Bitrix\Main\DB\Exception;
10 | use Bitrix\Main\Type\Date;
11 | use Bitrix\Main\Type\DateTime;
12 | use WS\Migrations\ApplyResult;
13 | use WS\Migrations\Diagnostic\DiagnosticResult;
14 | use WS\Migrations\Module;
15 | use WS\Migrations\Reference\ReferenceController;
16 |
17 | class IblockSectionHandler extends BaseSubjectHandler {
18 |
19 | /**
20 | * Name of Handler in Web interface
21 | * @return string
22 | */
23 | public function getName() {
24 | return $this->getLocalization()->getDataByPath('iblockSection.name');
25 | }
26 |
27 | public function getIdByChangeMethod($method, $data = array()) {
28 | switch ($method) {
29 | case Module::FIX_CHANGES_AFTER_ADD_KEY:
30 | case Module::FIX_CHANGES_BEFORE_CHANGE_KEY:
31 | case Module::FIX_CHANGES_AFTER_CHANGE_KEY:
32 | case Module::FIX_CHANGES_AFTER_DELETE_KEY:
33 | return $data[0]['ID'];
34 | case Module::FIX_CHANGES_BEFORE_DELETE_KEY:
35 | return $data[0];
36 | }
37 | return null;
38 | }
39 |
40 | public function getSnapshot($id, $dbVersion = null) {
41 | if (!$id) {
42 | return false;
43 | }
44 | $dbVersion && $id = $this->getCurrentVersionId($id, $dbVersion);
45 | !$dbVersion && !$this->hasCurrentReference($id) && $this->registerCurrentVersionId($id);
46 | $data = SectionTable::GetByID($id)->Fetch();
47 | $data['~reference'] = $this->getReferenceValue($id);
48 | return $data;
49 | }
50 |
51 | /**
52 | * @param $data
53 | * @param null $dbVersion
54 | * @throws \Exception
55 | * @return ApplyResult
56 | */
57 | public function applySnapshot($data, $dbVersion = null) {
58 | $data = $this->handleNullValues($data);
59 | $sec = new \CIBlockSection();
60 | $res = new ApplyResult();
61 |
62 | $extId = $data['ID'];
63 | if ($dbVersion) {
64 | $data['IBLOCK_ID'] = $this->getReferenceController()->getCurrentIdByOtherVersion($data['IBLOCK_ID'], ReferenceController::GROUP_IBLOCK, $dbVersion);
65 | $data['IBLOCK_SECTION_ID'] && $data['IBLOCK_SECTION_ID'] = $this->getCurrentVersionId($data['IBLOCK_SECTION_ID'], $dbVersion);
66 | $id = $this->getCurrentVersionId($extId, $dbVersion);
67 | } else {
68 | $id = $extId;
69 | }
70 | if ($id && !SectionTable::getList(array('filter' => array('=ID' => $id)))->fetch()) {
71 | $arSec = SectionTable::getList(array(
72 | 'limit' => 1,
73 | 'order' => array(
74 | 'RIGHT_MARGIN' => 'desc'
75 | )
76 | ))->fetch();
77 | $margin = $arSec['RIGHT_MARGIN'] ?: 0;
78 | $dateTime = new DateTime();
79 | $addRes = SectionTable::add(array(
80 | 'ID' => $id,
81 | 'IBLOCK_ID' => $data['IBLOCK_ID'],
82 | 'TIMESTAMP_X' => $dateTime->format('Y-m-d H:i:s'),
83 | 'NAME' => $data['NAME'],
84 | 'DESCRIPTION_TYPE' => $data['DESCRIPTION_TYPE'],
85 | 'LEFT_MARGIN' => $margin + 1,
86 | 'RIGHT_MARGIN' => $margin + 2,
87 | 'DEPTH_LEVEL' => 1
88 | ));
89 | if (!$addRes->isSuccess()) {
90 | throw new \Exception('Can`t create section ' . implode(', ', $addRes->getErrorMessages())."\n".var_export($data, true));
91 | }
92 | }
93 | unset($data['CREATED_BY'], $data['MODIFIED_BY']);
94 | if ($id && ($currentData = SectionTable::getById($id)->fetch())) {
95 | $data['PICTURE'] = $currentData['PICTURE'];
96 | $data['DETAIL_PICTURE'] = $currentData['DETAIL_PICTURE'];
97 | $res->setSuccess((bool)$sec->Update($id, $data));
98 | } else {
99 | unset($data['PICTURE'], $data['DETAIL_PICTURE']);
100 | $res->setSuccess((bool) ($id = $sec->Add($data)));
101 | $this->registerCurrentVersionId($id, $this->getReferenceValue($extId, $dbVersion));
102 | }
103 | $res->setId($id);
104 | $res->setMessage($sec->LAST_ERROR);
105 | return $res;
106 | }
107 |
108 | /**
109 | * Delete subject record
110 | * @param $id
111 | * @param null $dbVersion
112 | * @return ApplyResult
113 | */
114 | public function delete($id, $dbVersion = null) {
115 | $dbVersion && $id = $this->getCurrentVersionId($id, $dbVersion);
116 | !$dbVersion && !$this->hasCurrentReference($id) && $this->registerCurrentVersionId($id);
117 |
118 |
119 | $sec = new \CIBlockSection();
120 | $res = new ApplyResult();
121 | $res
122 | ->setSuccess((bool) $sec->Delete($id))
123 | ->setMessage($sec->LAST_ERROR);
124 | $res->isSuccess() && $this->removeReference($id);
125 | return $res;
126 | }
127 |
128 | protected function getSubjectGroup() {
129 | return ReferenceController::GROUP_IBLOCK_SECTION;
130 | }
131 |
132 | public function existsIds() {
133 | $dbRes = SectionTable::getList(array(
134 | 'select' => array('ID')
135 | ));
136 | $res = array();
137 | while ($item = $dbRes->fetch()) {
138 | $res[] = $item['ID'];
139 | }
140 | return $res;
141 | }
142 |
143 | static public function depends() {
144 | return array(
145 | IblockHandler::className()
146 | );
147 | }
148 |
149 | protected function getExistsSubjectIds() {
150 | $rs = SectionTable::getList(array(
151 | 'select' => array('ID')
152 | ));
153 | $res = array();
154 | while ($arSection = $rs->fetch()) {
155 | $res[] = $arSection['ID'];
156 | }
157 | return $res;
158 | }
159 |
160 | /**
161 | * @return DiagnosticResult
162 | */
163 | public function diagnostic() {
164 | $referenceResult = $this->diagnosticByReference();
165 | $itemsResult = $this->diagnosticByItems(\CIBlockSection::GetList());
166 | $success = $referenceResult->isSuccess() && $itemsResult->isSuccess();
167 | return new DiagnosticResult(
168 | $success,
169 | array_merge($referenceResult->getMessages(), $itemsResult->getMessages())
170 | );
171 | }
172 | }
--------------------------------------------------------------------------------
/lib/tests/abstractcase.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lib/tests/abstractcase.php
--------------------------------------------------------------------------------
/lib/tests/cases/agentbuildercase.php:
--------------------------------------------------------------------------------
1 | localization->message('name');
12 | }
13 |
14 | public function description() {
15 | return $this->localization->message('description');
16 | }
17 |
18 | public function init() {
19 |
20 | \CModule::IncludeModule('iblock');
21 | }
22 |
23 | public function close() {
24 | $agent = \CAgent::GetList(null, array(
25 | 'NAME' => 'abs(0);'
26 | ))->Fetch();
27 | \CAgent::Delete($agent['ID']);
28 | }
29 |
30 |
31 | public function testAdd() {
32 | $date = new DateTime();
33 | $date->add('+1 day');
34 | $builder = new \WS\Migrations\Builder\AgentBuilder();
35 | $builder
36 | ->addAgent('abs(0);')
37 | ->setSort(23)
38 | ->setActive(true)
39 | ->setNextExec($date);
40 | $builder->commit();
41 |
42 | $agent = \CAgent::GetList(null, array(
43 | 'NAME' => $builder->getCurrentAgent()->callback
44 | ))->Fetch();
45 |
46 | $this->assertNotEmpty($agent);
47 | $this->assertEquals($agent['NAME'], $builder->getCurrentAgent()->callback);
48 | $this->assertEquals($agent['SORT'], 23);
49 | $this->assertEquals($agent['ACTIVE'], "Y");
50 | $this->assertEquals($agent['NEXT_EXEC'], $date->format('d.m.Y H:i:s'));
51 | }
52 |
53 |
54 | public function testUpdate() {
55 | $builder = new \WS\Migrations\Builder\AgentBuilder();
56 | $builder
57 | ->getAgent('abs(0);')
58 | ->setActive(false)
59 | ->setIsPeriod(true);
60 |
61 | $builder->commit();
62 |
63 | $agent = \CAgent::GetList(null, array(
64 | 'NAME' => $builder->getCurrentAgent()->callback
65 | ))->Fetch();
66 |
67 | $this->assertNotEmpty($agent);
68 | $this->assertEquals($agent['NAME'], $builder->getCurrentAgent()->callback);
69 | $this->assertEquals($agent['ACTIVE'], 'N');
70 | $this->assertEquals($agent['IS_PERIOD'], 'Y');
71 | }
72 |
73 | }
--------------------------------------------------------------------------------
/lib/tests/cases/errorexception.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Tests\Cases;
7 |
8 |
9 | class ErrorException extends \Exception {
10 |
11 | private $_dumpedValue;
12 |
13 | public function setDump($value) {
14 | $this->_dumpedValue = $value;
15 | }
16 |
17 | public function getDump() {
18 | return $this->_dumpedValue;
19 | }
20 | }
--------------------------------------------------------------------------------
/lib/tests/cases/eventsbuildercase.php:
--------------------------------------------------------------------------------
1 | localization->message('name');
14 | }
15 |
16 | public function description() {
17 | return $this->localization->message('description');
18 | }
19 |
20 | public function init() {
21 |
22 | \CModule::IncludeModule('iblock');
23 | }
24 |
25 | public function close() {
26 | $eventType = \CEventType::GetList(array(
27 | 'TYPE_ID' => 'WS_MIGRATION_TEST_EVENT',
28 | 'LID' => 'en'
29 | ))->Fetch();
30 | $gw = new \CEventType;
31 | $gw->Delete($eventType['ID']);
32 | }
33 |
34 | public function testAdd() {
35 | $builder = new EventsBuilder();
36 | $builder
37 | ->addEventType('WS_MIGRATION_TEST_EVENT', 'ru')
38 | ->setName('Тестовое событие миграций')
39 | ->setSort(10)
40 | ->setDescription('#TEST# - test');
41 |
42 | $builder
43 | ->addEventMessage('#EMAIL_FROM#', '#EMAIL_TO#', 's1')
44 | ->setSubject('Hello')
45 | ->setBodyType(EventMessage::BODY_TYPE_HTML)
46 | ->setActive(true)
47 | ->setMessage('Hello #TEST#!')
48 | ;
49 |
50 | $builder
51 | ->addEventMessage('#FROM#', '#TO#', 's1')
52 | ->setSubject('Hi')
53 | ->setActive(false)
54 | ->setBodyType(EventMessage::BODY_TYPE_TEXT)
55 | ->setMessage('Hi #TEST#!')
56 | ;
57 |
58 | $builder->commit();
59 |
60 | $eventType = \CEventType::GetList(array(
61 | 'TYPE_ID' => 'WS_MIGRATION_TEST_EVENT',
62 | 'LID' => 'ru'
63 | ))->Fetch();
64 | $this->assertNotEmpty($eventType);
65 | $this->assertEquals($eventType['SORT'], 10);
66 | $this->assertNotEmpty($eventType['DESCRIPTION'], '#TEST# - test');
67 | $this->assertNotEmpty($eventType['NAME'], 'Тестовое событие миграций');
68 |
69 | $res = EventMessageTable::getList(array(
70 | 'filter' => array(
71 | 'EVENT_NAME' => 'WS_MIGRATION_TEST_EVENT'
72 | )
73 | ));
74 | $this->assertEquals($res->getSelectedRowsCount(), 2);
75 | while ($item = $res->fetch()) {
76 | if ($item['SUBJECT'] == 'Hi') {
77 | $this->assertEquals($item['BODY_TYPE'], 'text');
78 | $this->assertEquals($item['MESSAGE'], 'Hi #TEST#!');
79 | $this->assertEquals($item['LID'], 's1');
80 | $this->assertEquals($item['ACTIVE'], 'N');
81 | $this->assertEquals($item['EMAIL_FROM'], '#FROM#');
82 | $this->assertEquals($item['EMAIL_TO'], '#TO#');
83 | }
84 | }
85 | }
86 |
87 |
88 | public function testUpdate() {
89 | $builder = new EventsBuilder();
90 | $builder
91 | ->getEventType('WS_MIGRATION_TEST_EVENT', 'ru')
92 | ->setLid('en')
93 | ->setName('Тестовое событие');
94 |
95 | foreach ($builder->getEventMessages() as $message) {
96 | if ($message->subject == 'Hello') {
97 | $message->remove();
98 | }
99 | $message->setBcc('#BCC#');
100 | }
101 |
102 | $builder->commit();
103 |
104 | $eventType = \CEventType::GetList(array(
105 | 'TYPE_ID' => 'WS_MIGRATION_TEST_EVENT',
106 | 'LID' => 'en'
107 | ))->Fetch();
108 | $this->assertTrue(!empty($eventType));
109 | $this->assertNotEmpty($eventType['NAME'], 'Тестовое событие');
110 |
111 | $res = EventMessageTable::getList(array(
112 | 'filter' => array(
113 | 'EVENT_NAME' => 'WS_MIGRATION_TEST_EVENT'
114 | )
115 | ));
116 | $this->assertEquals($res->getSelectedRowsCount(), 1);
117 | while ($item = $res->fetch()) {
118 | $this->assertEquals($item['BCC'], '#BCC#');
119 | }
120 | }
121 |
122 | }
--------------------------------------------------------------------------------
/lib/tests/cases/formbuildercase.php:
--------------------------------------------------------------------------------
1 | localization->message('name');
14 | }
15 |
16 | public function description() {
17 | return $this->localization->message('description');
18 | }
19 |
20 | public function init() {
21 | \CModule::IncludeModule('form');
22 | }
23 |
24 | public function close() {
25 | $form = \CForm::GetList($by, $order, array(
26 | 'SID' => 'TestForm',
27 | ), $isFiltered)->Fetch();
28 | if (!$form) {
29 | return;
30 | }
31 | \CForm::Delete($form['ID'], 'N');
32 | }
33 |
34 | public function testAdd() {
35 | $builder = new FormBuilder();
36 | $builder
37 | ->addForm('TestForm', 'TestForm')
38 | ->setArSiteId(array('s1'))
39 | ->setSort('10')
40 | ->setDescription('Description')
41 | ->setUseCaptcha(true)
42 | ->setArGroup(array(
43 | '2' => 10
44 | ))
45 | ->setArMenu(array("ru" => "Анкета посетителя", "en" => "Visitor Form"))
46 | ->setDescriptionType('html')
47 | ;
48 |
49 | $builder
50 | ->addField('testQuestion')
51 | ->setFieldType(FormField::FIELD_TYPE_INTEGER)
52 | ->setSort(33)
53 | ->setActive(false)
54 | ->setRequired(true)
55 | ->setTitle('testTitle')
56 | ->setArFilterAnswerText(array("dropdown"))
57 | ->setArFilterAnswerValue(array("dropdown"))
58 | ->setArFilterUser(array("dropdown"))
59 | ->setArFilterField(array("integer"))
60 | ->setComments('test comment')
61 | ->addAnswer('Привет мир!');
62 |
63 | $builder
64 | ->addField('testField')
65 | ->setAsField()
66 | ->setTitle('test')
67 | ;
68 | $builder
69 | ->addStatus('status')
70 | ->setArGroupCanDelete(array(2))
71 | ->setIsDefault(true);
72 |
73 | $builder->commit();
74 |
75 | $form = \CForm::GetList($by, $order, array(
76 | 'ID' => $builder->getCurrentForm()->getId(),
77 | ), $isFiltered)->Fetch();
78 |
79 | $this->assertNotEmpty($form);
80 | $this->assertEquals($form['C_SORT'], 10);
81 | $this->assertNotEmpty($form['DESCRIPTION'], 'Description');
82 | $this->assertNotEmpty($form['NAME'], 'TestForm');
83 | $this->assertNotEmpty($form['USE_CAPTCHA'], 'Y');
84 |
85 | $res = \CFormField::GetList($builder->getCurrentForm()->getId(), 'ALL', $by, $order, array(), $isFiltered);
86 |
87 | $this->assertEquals($res->SelectedRowsCount(), 2);
88 | while ($item = $res->fetch()) {
89 | if ($item['SID'] == 'testQuestion') {
90 | $this->assertEquals($item['ACTIVE'], 'N');
91 | $this->assertEquals($item['ADDITIONAL'], 'N');
92 | $this->assertEquals($item['FIELD_TYPE'], 'integer');
93 | $this->assertEquals($item['TITLE'], 'testTitle');
94 | $this->assertEquals($item['C_SORT'], 33);
95 | $this->assertEquals($item['REQUIRED'], 'Y');
96 | $this->assertEquals($item['COMMENTS'], 'test comment');
97 | }
98 | if ($item['SID'] == 'testField') {
99 | $this->assertEquals($item['ADDITIONAL'], 'Y');
100 | $this->assertEquals($item['TITLE'], 'test');
101 | }
102 | }
103 |
104 | $res = \CFormStatus::GetList($builder->getCurrentForm()->getId(), $by, $order, array(), $isFiltered)->Fetch();
105 | $this->assertEquals($res['TITLE'], 'status');
106 | $this->assertEquals($res['DEFAULT_VALUE'], 'Y');
107 | }
108 |
109 |
110 | public function testUpdate() {
111 | $builder = new FormBuilder();
112 | $builder
113 | ->getForm('TestForm')
114 | ->setName('MyTestForm');
115 |
116 | $field = $builder
117 | ->getField('testQuestion')
118 | ->setActive(true)
119 | ->setRequired(false);
120 |
121 | $field->removeAnswer('Привет мир!');
122 |
123 | $field
124 | ->addAnswer('Test')
125 | ->setValue('val1');
126 |
127 | $builder
128 | ->getStatus('status')
129 | ->setDescription('test22')
130 | ->setArGroupCanDelete(array(2, 3));
131 |
132 | $builder->commit();
133 |
134 | $form = \CForm::GetList($by, $order, array(
135 | 'ID' => $builder->getCurrentForm()->getId(),
136 | ), $isFiltered)->Fetch();
137 |
138 | $this->assertNotEmpty($form);
139 | $this->assertNotEmpty($form['NAME'], 'MyTestForm');
140 |
141 | $res = \CFormField::GetList($builder->getCurrentForm()->getId(), 'ALL', $by, $order, array(), $isFiltered);
142 |
143 | $this->assertEquals($res->SelectedRowsCount(), 2);
144 | while ($item = $res->fetch()) {
145 | if ($item['SID'] == 'testQuestion') {
146 | $this->assertEquals($item['ACTIVE'], 'Y');
147 | $this->assertEquals($item['ADDITIONAL'], 'N');
148 | $this->assertEquals($item['FIELD_TYPE'], 'integer');
149 | $this->assertEquals($item['TITLE'], 'testTitle');
150 | $this->assertEquals($item['REQUIRED'], 'N');
151 | $this->assertEquals($item['COMMENTS'], 'test comment');
152 | }
153 | }
154 |
155 | $res = \CFormStatus::GetList($builder->getCurrentForm()->getId(), $by, $order, array(), $isFiltered)->Fetch();
156 | $this->assertEquals($res['DESCRIPTION'], 'test22');
157 | }
158 |
159 | }
--------------------------------------------------------------------------------
/lib/tests/cases/highloadblockbuildercase.php:
--------------------------------------------------------------------------------
1 | localization->message('name');
14 | }
15 |
16 | public function description() {
17 | return $this->localization->message('description');
18 | }
19 |
20 | public function init() {
21 |
22 | \CModule::IncludeModule('iblock');
23 | }
24 |
25 | public function close() {
26 | $arIblock = HighloadBlockTable::getList(array(
27 | 'filter' => array(
28 | 'TABLE_NAME' => 'test_highloadblock'
29 | )
30 | ))->fetch();
31 |
32 | HighloadBlockTable::delete($arIblock['ID']);
33 | }
34 |
35 |
36 | public function testAdd() {
37 | $builder = new HighLoadBlockBuilder();
38 | $builder
39 | ->addHLBlock('TestBlock', 'test_highloadblock')
40 | ;
41 | $prop = $builder
42 | ->addField('uf_test1')
43 | ->setSort(10)
44 | ->setLabel(['ru' => 'Тест'])
45 | ->setUserTypeId(UserField::TYPE_ENUMERATION)
46 | ;
47 | $prop->addEnum('Тест1');
48 | $prop->addEnum('Тест2');
49 | $prop->addEnum('Тест3');
50 |
51 | $builder
52 | ->addField('uf_test2')
53 | ->setLabel(['ru' => 'Тест2'])
54 | ->setUserTypeId(UserField::TYPE_HLBLOCK);
55 |
56 | $builder
57 | ->addField('uf_test3')
58 | ->setLabel(['ru' => 'Тест2'])
59 | ->setUserTypeId(UserField::TYPE_BOOLEAN);
60 |
61 | $builder
62 | ->addField('uf_test4')
63 | ->setLabel(['ru' => 'Тест2'])
64 | ->setUserTypeId(UserField::TYPE_DATETIME);
65 |
66 | $builder
67 | ->addField('uf_test5')
68 | ->setLabel(['ru' => 'Тест2'])
69 | ->setUserTypeId(UserField::TYPE_IBLOCK_ELEMENT);
70 |
71 | $builder
72 | ->addField('uf_test6')
73 | ->setLabel(['ru' => 'Тест2'])
74 | ->setUserTypeId(UserField::TYPE_VOTE);
75 |
76 | $builder
77 | ->addField('uf_test7')
78 | ->setLabel(['ru' => 'Тест2'])
79 | ->setUserTypeId(UserField::TYPE_VIDEO);
80 |
81 | $builder
82 | ->addField('uf_test8')
83 | ->setLabel(['ru' => 'Тест2'])
84 | ->setUserTypeId(UserField::TYPE_IBLOCK_SECTION);
85 |
86 | $builder->commit();
87 |
88 | $arIblock = HighloadBlockTable::getList(array(
89 | 'filter' => array(
90 | 'ID' => $builder->getCurrentHighLoadBlock()->getId()
91 | )
92 | ))->fetch();
93 |
94 | $this->assertNotEmpty($arIblock, "hlblock wasn't created");
95 | $this->assertEquals($arIblock['TABLE_NAME'], $builder->getCurrentHighLoadBlock()->tableName);
96 | $this->assertEquals($arIblock['NAME'], $builder->getCurrentHighLoadBlock()->name);
97 |
98 | $fields = \CUserTypeEntity::GetList(null, array(
99 | 'ENTITY_ID' => "HLBLOCK_" . $builder->getCurrentHighLoadBlock()->getId(),
100 | ));
101 |
102 | $this->assertEquals($fields->SelectedRowsCount(), 8);
103 | while ($field = $fields->Fetch()) {
104 | $field['NAME'] == 'uf_test5' && $this->assertEquals($field['USER_TYPE_ID'], UserField::TYPE_IBLOCK_ELEMENT);
105 | }
106 |
107 | }
108 |
109 |
110 | public function testUpdate() {
111 | $builder = new HighLoadBlockBuilder();
112 | $builder
113 | ->getHLBlock('test_highloadblock')
114 | ->setName('TestBlock2')
115 | ;
116 |
117 | $prop = $builder
118 | ->getField('uf_test1')
119 | ->setMultiple(true)
120 | ->setRequired(true)
121 | ;
122 | $prop->updateEnum('Тест1')->setXmlId('test1');
123 | $prop->removeEnum('Тест2');
124 |
125 | $builder->commit();
126 |
127 | $arIblock = HighloadBlockTable::getList(array(
128 | 'filter' => array(
129 | 'ID' => $builder->getCurrentHighLoadBlock()->getId()
130 | )
131 | ))->fetch();
132 |
133 | $this->assertEquals($arIblock['TABLE_NAME'], $builder->getCurrentHighLoadBlock()->tableName);
134 | $this->assertEquals($arIblock['NAME'], $builder->getCurrentHighLoadBlock()->name);
135 |
136 | $res = \CUserFieldEnum::GetList(null, array(
137 | 'USER_FIELD_ID' => $builder->getCurrentHighLoadBlock()->getId(),
138 | 'VALUE' => 'Тест2',
139 | ))->Fetch();
140 |
141 | $this->assertEmpty($res);
142 |
143 | $res = \CUserFieldEnum::GetList(null, array(
144 | 'USER_FIELD_ID' => $prop->getId(),
145 | 'VALUE' => 'Тест1',
146 | ))->Fetch();
147 |
148 | $this->assertNotEmpty($res);
149 | $this->assertEquals($res['XML_ID'], 'test1');
150 | }
151 |
152 | }
--------------------------------------------------------------------------------
/lib/tests/cases/installtestcase.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Tests\Cases;
7 |
8 |
9 | use Bitrix\Iblock\IblockTable;
10 | use Bitrix\Iblock\PropertyTable;
11 | use Bitrix\Iblock\SectionTable;
12 | use WS\Migrations\Entities\DbVersionReferencesTable;
13 | use WS\Migrations\Module;
14 | use WS\Migrations\Reference\ReferenceController;
15 | use WS\Migrations\Tests\AbstractCase;
16 |
17 | class InstallTestCase extends AbstractCase {
18 |
19 | public function name() {
20 | return $this->localization->message('name');
21 | }
22 |
23 | public function description() {
24 | return $this->localization->message('description');
25 | }
26 |
27 | public function init() {
28 | \CModule::IncludeModule('iblock');
29 | Module::getInstance()->clearReferences();
30 | }
31 |
32 |
33 | public function testExistsReferencesRegister() {
34 | Module::getInstance()->install();
35 |
36 | $dbRsRef = DbVersionReferencesTable::getList(array(
37 | 'filter' => array(
38 | 'GROUP' => ReferenceController::GROUP_IBLOCK
39 | )
40 | ));
41 | $dbRsIblock = IblockTable::getList();
42 | $this->assertEquals($dbRsIblock->getSelectedRowsCount(), $dbRsRef->getSelectedRowsCount(), $this->errorMessage('number of links to the information block and the information block entries must match'));
43 |
44 | $dbRsRef = DbVersionReferencesTable::getList(array(
45 | 'filter' => array(
46 | 'GROUP' => ReferenceController::GROUP_IBLOCK_PROPERTY
47 | )
48 | ));
49 | $dbRsProp = PropertyTable::getList();
50 | $this->assertEquals($dbRsProp->getSelectedRowsCount(), $dbRsRef->getSelectedRowsCount(), $this->errorMessage('number of links on the properties of information blocks and records must match'));
51 |
52 | $dbRsRef = DbVersionReferencesTable::getList(array(
53 | 'filter' => array(
54 | 'GROUP' => ReferenceController::GROUP_IBLOCK_SECTION
55 | )
56 | ));
57 | $dbRsSection = SectionTable::getList();
58 | $this->assertEquals($dbRsSection->getSelectedRowsCount(), $dbRsRef->getSelectedRowsCount(), $this->errorMessage('number of links to information block sections and records must match'));
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/lib/tests/cases/rollbacktestcase.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Tests\Cases;
7 |
8 |
9 | use Bitrix\Iblock\IblockTable;
10 | use Bitrix\Iblock\PropertyTable;
11 | use Bitrix\Iblock\SectionTable;
12 | use WS\Migrations\ChangeDataCollector\Collector;
13 | use WS\Migrations\Module;
14 | use WS\Migrations\Tests\AbstractCase;
15 |
16 | class RollbackTestCase extends AbstractCase {
17 |
18 | public function name() {
19 | return $this->localization->message('name');
20 | }
21 |
22 | public function description() {
23 | return '';
24 | }
25 |
26 | public function init() {
27 | \CModule::IncludeModule('iblock');
28 | Module::getInstance()->clearReferences();
29 | }
30 |
31 | public function testReinitIblockReference() {
32 | $beforeApplyFix = array(
33 | 'iblocks' => IblockTable::getList()->getSelectedRowsCount(),
34 | 'properties' => PropertyTable::getList()->getSelectedRowsCount(),
35 | 'sections' => SectionTable::getList()->getSelectedRowsCount(),
36 | );
37 |
38 | $collector = Collector::createByFile(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'add_collection.json');
39 | $this->assertNotEmpty($collector->getFixes());
40 | Module::getInstance()->applyFixesList($collector->getFixes());
41 |
42 | $afterApplyFix = array(
43 | 'iblocks' => IblockTable::getList()->getSelectedRowsCount(),
44 | 'properties' => PropertyTable::getList()->getSelectedRowsCount(),
45 | 'sections' => SectionTable::getList()->getSelectedRowsCount(),
46 | );
47 |
48 | Module::getInstance()->rollbackLastChanges();
49 | $afterRollback = array(
50 | 'iblocks' => IblockTable::getList()->getSelectedRowsCount(),
51 | 'properties' => PropertyTable::getList()->getSelectedRowsCount(),
52 | 'sections' => SectionTable::getList()->getSelectedRowsCount(),
53 | );
54 |
55 | Module::getInstance()->applyFixesList($collector->getFixes());
56 | $afterRollbackApply = array(
57 | 'iblocks' => IblockTable::getList()->getSelectedRowsCount(),
58 | 'properties' => PropertyTable::getList()->getSelectedRowsCount(),
59 | 'sections' => SectionTable::getList()->getSelectedRowsCount(),
60 | );
61 |
62 | $this->assertEquals($beforeApplyFix['iblocks'], $afterApplyFix['iblocks'] - 1, $this->errorMessage('iblock not created after apply fix'));
63 | $this->assertEquals($beforeApplyFix['properties'], $afterApplyFix['properties'] - 2, $this->errorMessage('properties not created after apply fix'));
64 | $this->assertEquals($beforeApplyFix['sections'], $afterApplyFix['sections'] - 1, $this->errorMessage('sections not created after apply fix'));
65 |
66 | $this->assertEquals($beforeApplyFix['iblocks'], $afterRollback['iblocks'], $this->errorMessage('iblock not removed after rollback fix'));
67 | $this->assertEquals($beforeApplyFix['properties'], $afterRollback['properties'], $this->errorMessage('properties not removed after rollback fix'));
68 | $this->assertEquals($beforeApplyFix['sections'], $afterRollback['sections'], $this->errorMessage('sections not removed after rollback fix'));
69 |
70 | $this->assertEquals($afterRollback['iblocks'] + 1, $afterRollbackApply['iblocks'], $this->errorMessage('iblock not created after apply rollback fix'));
71 | $this->assertEquals($afterRollback['properties'] + 2, $afterRollbackApply['properties'], $this->errorMessage('properties not created after apply rollback fix'));
72 | $this->assertEquals($afterRollback['sections'] + 1, $afterRollbackApply['sections'], $this->errorMessage('sections not created after apply rollback fix'));
73 | }
74 | }
--------------------------------------------------------------------------------
/lib/tests/cases/updatetestcase.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/lib/tests/cases/updatetestcase.php
--------------------------------------------------------------------------------
/lib/tests/fixtures/delete_property.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "process": "reference",
4 | "subject": null,
5 | "data": {
6 | "reference": "d13bd5f833ec98310a112080508580b7",
7 | "group": "iblockProperty",
8 | "dbVersion": "test",
9 | "id": 46
10 | },
11 | "originalData": null,
12 | "name": "Reference fix",
13 | "version": "test"
14 | },
15 | {
16 | "process": "WS\\Migrations\\Processes\\DeleteProcess",
17 | "subject": "WS\\Migrations\\SubjectHandlers\\IblockPropertyHandler",
18 | "data": 46,
19 | "originalData": {
20 | "ID": "46",
21 | "TIMESTAMP_X": "2014-07-23 14:05:54",
22 | "IBLOCK_ID": "6",
23 | "NAME": "Test Add prop 1 ++",
24 | "ACTIVE": "Y",
25 | "SORT": "100",
26 | "CODE": "prop1",
27 | "DEFAULT_VALUE": "",
28 | "PROPERTY_TYPE": "S",
29 | "ROW_COUNT": "1",
30 | "COL_COUNT": "30",
31 | "LIST_TYPE": "L",
32 | "MULTIPLE": "N",
33 | "XML_ID": null,
34 | "FILE_TYPE": "",
35 | "MULTIPLE_CNT": "5",
36 | "TMP_ID": null,
37 | "LINK_IBLOCK_ID": "0",
38 | "WITH_DESCRIPTION": "N",
39 | "SEARCHABLE": "N",
40 | "FILTRABLE": "N",
41 | "IS_REQUIRED": "N",
42 | "VERSION": "1",
43 | "USER_TYPE": null,
44 | "USER_TYPE_SETTINGS": null,
45 | "HINT": ""
46 | },
47 | "name": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430. \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435",
48 | "version": "test"
49 | }
50 | ]
--------------------------------------------------------------------------------
/lib/tests/fixtures/delete_section.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "process": "reference",
4 | "subject": null,
5 | "data": {
6 | "reference": "27cd0bdc8556f84c7d4b77600acefabe",
7 | "group": "iblockSection",
8 | "dbVersion": "test",
9 | "id": 18
10 | },
11 | "originalData": null,
12 | "name": "Reference fix",
13 | "version": "test"
14 | },
15 | {
16 | "process": "WS\\Migrations\\Processes\\DeleteProcess",
17 | "subject": "WS\\Migrations\\SubjectHandlers\\IblockSectionHandler",
18 | "data": "18",
19 | "originalData": null,
20 | "name": "\u0420\u0430\u0437\u0434\u0435\u043b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430. \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435",
21 | "version": "test"
22 | }
23 | ]
--------------------------------------------------------------------------------
/lib/tests/result.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Tests;
7 |
8 |
9 | class Result {
10 | private $_success;
11 | private $_message;
12 | private $_trace;
13 |
14 | /**
15 | * @return mixed
16 | */
17 | public function getMessage() {
18 | return $this->_message;
19 | }
20 |
21 | /**
22 | * @param mixed $value
23 | * @return $this
24 | */
25 | public function setMessage($value) {
26 | $this->_message = $value;
27 | return $this;
28 | }
29 |
30 | public function setTrace($aTrace) {
31 | $this->_trace = $aTrace;
32 | return $this;
33 | }
34 |
35 | /**
36 | * @return mixed
37 | */
38 | public function getTrace() {
39 | return $this->_trace;
40 | }
41 |
42 | /**
43 | * @return mixed
44 | */
45 | public function isSuccess() {
46 | return $this->_success;
47 | }
48 |
49 | /**
50 | * @param mixed $value
51 | * @return $this
52 | */
53 | public function setSuccess($value) {
54 | $this->_success = $value;
55 | return $this;
56 | }
57 |
58 | /**
59 | * @return array
60 | */
61 | public function toArray() {
62 | return array(
63 | 'STATUS' => $this->isSuccess(),
64 | 'MESSAGE' => array(
65 | 'PREVIEW' => str_replace("\n", "
", $this->getMessage()),
66 | 'DETAIL' => $this->getTrace()
67 | )
68 | );
69 | }
70 |
71 | }
--------------------------------------------------------------------------------
/lib/tests/starter.php:
--------------------------------------------------------------------------------
1 |
4 | */
5 |
6 | namespace WS\Migrations\Tests;
7 |
8 |
9 | use WS\Migrations\Module;
10 | use WS\Migrations\Tests\Cases\AgentBuilderCase;
11 | use WS\Migrations\Tests\Cases\EventsBuilderCase;
12 | use WS\Migrations\Tests\Cases\FixTestCase;
13 | use WS\Migrations\Tests\Cases\FormBuilderCase;
14 | use WS\Migrations\Tests\Cases\HighLoadBlockBuilderCase;
15 | use WS\Migrations\Tests\Cases\IblockBuilderCase;
16 | use WS\Migrations\Tests\Cases\InstallTestCase;
17 | use WS\Migrations\Tests\Cases\RollbackTestCase;
18 | use WS\Migrations\Tests\Cases\UpdateTestCase;
19 |
20 | class Starter {
21 |
22 | const SECTION = 'WSMIGRATIONS';
23 |
24 | static public function className() {
25 | return get_called_class();
26 | }
27 |
28 | /**
29 | * @return \WS\Migrations\Localization
30 | */
31 | static public function getLocalization() {
32 | return Module::getInstance()->getLocalization('tests');
33 | }
34 |
35 | static public function cases() {
36 | return array(
37 | FixTestCase::className(),
38 | UpdateTestCase::className(),
39 | InstallTestCase::className(),
40 | RollbackTestCase::className(),
41 | IblockBuilderCase::className(),
42 | HighLoadBlockBuilderCase::className(),
43 | AgentBuilderCase::className(),
44 | EventsBuilderCase::className(),
45 | FormBuilderCase::className(),
46 | );
47 | }
48 |
49 | static private function _getLocalizationByCase ($class) {
50 | return static::getLocalization()->fork('cases.'.$class);
51 | }
52 |
53 | /**
54 | * Run module tests
55 | * @internal param $aCheckList
56 | * @return array
57 | */
58 | static public function items() {
59 | if (!Module::getInstance()->getOptions()->useAutotests) {
60 | return array();
61 | }
62 | $points = array();
63 | $i = 1;
64 | $fGetCaseId = function ($className) {
65 | $arClass = implode('\\', $className);
66 | return array_pop($arClass);
67 | };
68 | foreach (self::cases() as $caseClass) {
69 | /** @var $case AbstractCase */
70 | $case = new $caseClass(static::_getLocalizationByCase($caseClass));
71 | $points[self::SECTION.'-'.$i++] = array(
72 | 'AUTO' => 'Y',
73 | 'NAME' => $case->name(),
74 | 'DESC' => $case->description(),
75 | 'CLASS_NAME' => get_called_class(),
76 | 'METHOD_NAME' => 'run',
77 | 'PARENT' => self::SECTION,
78 | 'PARAMS' => array(
79 | 'class' => $caseClass
80 | )
81 | );
82 | }
83 |
84 | return array(
85 | 'CATEGORIES' => array(
86 | self::SECTION => array(
87 | 'NAME' => static::getLocalization()->message('run.name')
88 | )
89 | ),
90 | 'POINTS' => $points
91 | );
92 | }
93 |
94 | static public function run($params) {
95 | $class = $params['class'];
96 | $result = new Result();
97 | if (!$class) {
98 | $result->setSuccess(false);
99 | $result->setMessage('Params not is correct');
100 | return $result->toArray();
101 | }
102 | $testCase = new $class(static::_getLocalizationByCase($class));
103 | if (!$testCase instanceof AbstractCase) {
104 | $result->setSuccess(false);
105 | $result->setMessage('Case class is not correct');
106 | return $result->toArray();
107 | }
108 | $refClass = new \ReflectionObject($testCase);
109 | $testMethods = array_filter($refClass->getMethods(), function (\ReflectionMethod $method) {
110 | return strpos(strtolower($method->getName()), 'test') === 0;
111 | });
112 | try {
113 | $count = 0;
114 | /** @var $method \ReflectionMethod */
115 | $testCase->init();
116 | foreach ($testMethods as $method) {
117 | $testCase->setUp();
118 | $method->invoke($testCase);
119 | $testCase->tearDown();
120 | $count++;
121 | }
122 | } catch (\Exception $e) {
123 | $result->setSuccess(false)
124 | ->setTrace($e->getTraceAsString());
125 | $message = $method->getShortName(). ', '. $e->getMessage();
126 | if ($e instanceof \WS\Migrations\Tests\Cases\ErrorException) {
127 | $e->getDump() && $message .= "\ndump: \n" . var_export($e->getDump(), true);
128 | }
129 | $result->setMessage($message);
130 | return $result->toArray();
131 | }
132 | $testCase->close();
133 | return $result->setSuccess(true)
134 | ->setMessage(static::getLocalization()->message('run.report.completed').':'.$count."\n".static::getLocalization()->message('run.report.assertions').': '.$testCase->getAssertsCount())
135 | ->toArray();
136 | }
137 | }
--------------------------------------------------------------------------------
/options.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worksolutions/bitrix-module-migrations/9b748cfcfc6e8e3031d07896969839436b4805d4/options.php
--------------------------------------------------------------------------------
/prolog.php:
--------------------------------------------------------------------------------
1 | errorMessage[] = $mess;
13 | };
14 | //=====================================================
15 |
16 | $docRoot = rtrim($_SERVER['DOCUMENT_ROOT'], '/').'/';
17 | // install file platform version
18 | $uploadDir = $docRoot . \COption::GetOptionString("main", "upload_dir", "upload");
19 | $modulePath = rtrim($docRoot, '/').$updater->kernelPath.'/modules/'.$updater->moduleID;
20 | $updatePath = $docRoot.$updater->curModulePath;
21 |
22 | $isInstalled = \Bitrix\Main\ModuleManager::isModuleInstalled($updater->moduleID);
23 |
--------------------------------------------------------------------------------